diff --git a/public/scripts/extensions/quick-reply/contextMenuEditor.html b/public/scripts/extensions/quick-reply/contextMenuEditor.html
new file mode 100644
index 000000000..00e77c0ac
--- /dev/null
+++ b/public/scripts/extensions/quick-reply/contextMenuEditor.html
@@ -0,0 +1,21 @@
+
diff --git a/public/scripts/extensions/quick-reply/index.js b/public/scripts/extensions/quick-reply/index.js
index ed0c0b0f4..6b2f4f3ad 100644
--- a/public/scripts/extensions/quick-reply/index.js
+++ b/public/scripts/extensions/quick-reply/index.js
@@ -103,14 +103,69 @@ function onQuickReplyInput(id) {
function onQuickReplyLabelInput(id) {
extension_settings.quickReply.quickReplySlots[id - 1].label = $(`#quickReply${id}Label`).val();
let quickReplyLabel = extension_settings.quickReply.quickReplySlots[id - 1]?.label || '';
- const parts = quickReplyLabel.split('...');
- if (parts.length > 1) {
- quickReplyLabel = `${parts.shift()}…`;
- }
- $(`#quickReply${id}`).text(quickReplyLabel);
+ $(`#quickReply${id}`).text(quickReplyLabel + (extension_settings.quickReply.quickReplySlots[id - 1]?.contextMenu?.length?'…':''));
saveSettingsDebounced();
}
+async function onQuickReplyContextMenuChange(id) {
+ extension_settings.quickReply.quickReplySlots[id - 1].contextMenu = JSON.parse($(`#quickReplyContainer > [data-order="${id}"]`).attr('data-contextMenu'))
+ saveSettingsDebounced();
+}
+
+async function onQuickReplyCtxButtonClick(id) {
+ const editorHtml = $(await $.get('scripts/extensions/quick-reply/contextMenuEditor.html'));
+ const popupResult = callPopup(editorHtml, "confirm", undefined, { okButton: "Save", wide:false, large:false, rows: 1 });
+ const qr = extension_settings.quickReply.quickReplySlots[id - 1];
+ if (!qr.contextMenu) {
+ qr.contextMenu = [];
+ }
+ /**@type {HTMLTemplateElement}*/
+ const tpl = document.querySelector('#quickReply_contextMenuEditor_itemTemplate');
+ const fillPresetSelect = (select, item) => {
+ [{name:'Select a preset', value:''}, ...presets].forEach(preset=>{
+ const opt = document.createElement('option'); {
+ opt.value = preset.value ?? preset.name;
+ opt.textContent = preset.name;
+ opt.selected = preset.name == item.preset;
+ select.append(opt);
+ }
+ });
+ };
+ const addCtxItem = (item, idx) => {
+ const dom = tpl.content.cloneNode(true);
+ const ctxItem = dom.querySelector('.quickReplyContextMenuEditor_item');
+ ctxItem.setAttribute('data-order', idx);
+ const select = ctxItem.querySelector('.quickReply_contextMenuEditor_preset');
+ fillPresetSelect(select, item);
+ dom.querySelector('.quickReply_contextMenuEditor_chaining').checked = item.chain;
+ $('.quickReply_contextMenuEditor_remove', ctxItem).on('click', ()=>ctxItem.remove());
+ document.querySelector('#quickReply_contextMenuEditor_content').append(ctxItem);
+ }
+ [...qr.contextMenu, {}].forEach((item,idx)=>{
+ addCtxItem(item, idx)
+ });
+ $('#quickReply_contextMenuEditor_addPreset').on('click', ()=>{
+ addCtxItem({}, document.querySelector('#quickReply_contextMenuEditor_content').children.length);
+ });
+
+ $('#quickReply_contextMenuEditor_content').sortable({
+ delay: getSortableDelay(),
+ stop: ()=>{},
+ });
+
+ if (await popupResult) {
+ qr.contextMenu = Array.from(document.querySelectorAll('#quickReply_contextMenuEditor_content > .quickReplyContextMenuEditor_item'))
+ .map(item=>({
+ preset: item.querySelector('.quickReply_contextMenuEditor_preset').value,
+ chain: item.querySelector('.quickReply_contextMenuEditor_chaining').checked,
+ }))
+ .filter(item=>item.preset);
+ $(`#quickReplyContainer[data-order="${id}"]`).attr('data-contextMenu', JSON.stringify(qr.contextMenu));
+ updateQuickReplyPreset();
+ onQuickReplyLabelInput(id);
+ }
+}
+
async function onQuickReplyEnabledInput() {
let isEnabled = $(this).prop('checked')
extension_settings.quickReply.quickReplyEnabled = !!isEnabled;
@@ -186,40 +241,33 @@ function buildContextMenu(qr, chainMes=null, hierarchy=[], labelHierarchy=[]) {
mes: (chainMes&&qr.mes ? `${chainMes} | ` : '') + qr.mes,
children: [],
};
- const parts = qr.label.split('...');
- if (parts.length > 1) {
- tree.label = parts.shift();
- parts.forEach(subName=>{
- let chain = false;
- if (subName[0] == '!') {
- chain = true;
- subName = subName.substring(1);
+ qr.contextMenu?.forEach(ctxItem=>{
+ let chain = ctxItem.chain;
+ let subName = ctxItem.preset;
+ const sub = presets.find(it=>it.name == subName);
+ if (sub) {
+ // prevent circular references
+ if (hierarchy.indexOf(sub.name) == -1) {
+ const nextHierarchy = [...hierarchy, sub.name];
+ const nextLabelHierarchy = [...labelHierarchy, tree.label];
+ tree.children.push(new MenuHeader(sub.name));
+ sub.quickReplySlots.forEach(subQr=>{
+ const subInfo = buildContextMenu(subQr, chain?tree.mes:null, nextHierarchy, nextLabelHierarchy);
+ tree.children.push(new MenuItem(
+ subInfo.label,
+ subInfo.mes,
+ (evt)=>{
+ evt.stopPropagation();
+ performQuickReply(subInfo.mes.replace(/%%parent(-\d+)?%%/g, (_, index)=>{
+ return nextLabelHierarchy.slice(parseInt(index ?? '-1'))[0];
+ }));
+ },
+ subInfo.children,
+ ));
+ });
}
- const sub = presets.find(it=>it.name == subName);
- if (sub) {
- // prevent circular references
- if (hierarchy.indexOf(sub.name) == -1) {
- const nextHierarchy = [...hierarchy, sub.name];
- const nextLabelHierarchy = [...labelHierarchy, tree.label];
- tree.children.push(new MenuHeader(sub.name));
- sub.quickReplySlots.forEach(subQr=>{
- const subInfo = buildContextMenu(subQr, chain?tree.mes:null, nextHierarchy, nextLabelHierarchy);
- tree.children.push(new MenuItem(
- subInfo.label,
- subInfo.mes,
- (evt)=>{
- evt.stopPropagation();
- performQuickReply(subInfo.mes.replace(/%%parent(-\d+)?%%/g, (_, index)=>{
- return nextLabelHierarchy.slice(parseInt(index ?? '-1'))[0];
- }));
- },
- subInfo.children,
- ));
- });
- }
- }
- });
- }
+ }
+ });
return tree;
}
function addQuickReplyBar() {
@@ -229,9 +277,8 @@ function addQuickReplyBar() {
for (let i = 0; i < extension_settings.quickReply.numberOfSlots; i++) {
let quickReplyMes = extension_settings.quickReply.quickReplySlots[i]?.mes || '';
let quickReplyLabel = extension_settings.quickReply.quickReplySlots[i]?.label || '';
- const parts = quickReplyLabel.split('...');
- if (parts.length > 1) {
- quickReplyLabel = `${parts.shift()}…`;
+ if (extension_settings.quickReply.quickReplySlots[i]?.contextMenu?.length) {
+ quickReplyLabel = `${quickReplyLabel}…`;
}
quickReplyButtonHtml += `
+
☰
+
`;
@@ -414,6 +464,8 @@ function generateQuickReplyElements() {
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
$(`#quickReply${i}Mes`).on('input', function () { onQuickReplyInput(i); });
$(`#quickReply${i}Label`).on('input', function () { onQuickReplyLabelInput(i); });
+ $(`#quickReply${i}CtxButton`).on('click', function () { onQuickReplyCtxButtonClick(i); });
+ $(`#quickReplyContainer > [data-order="${i}"]`).attr('data-contextMenu', JSON.stringify(extension_settings.quickReply.quickReplySlots[i-1]?.contextMenu??[]));
}
$('.quickReplySettings .inline-drawer-toggle').off('click').on('click', function () {
@@ -475,6 +527,7 @@ function saveQROrder() {
//rebuild the extension_Settings array based on new order
i = 1
$('#quickReplyContainer').children().each(function () {
+ onQuickReplyContextMenuChange(i)
onQuickReplyLabelInput(i)
onQuickReplyInput(i)
i++