diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index e9396e6e8..092b23cde 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -177,6 +177,7 @@ parser.addCommand('run', runCallback, ['call', 'exec'], '(names=off/on [message index or range]) – returns the specified message or range of messages as a string.', true, true); parser.addCommand('setinput', setInputCallback, [], '(text) – sets the user input to the specified text and passes it to the next command through the pipe.', true, true); parser.addCommand('popup', popupCallback, [], '(text) – shows a blocking popup with the specified text.', true, true); +parser.addCommand('buttons', buttonsCallback, [], 'labels=["a","b"] (text) – shows a blocking popup with the specified text and buttons. Returns the clicked button label into the pipe or empty string if canceled.', true, true); parser.addCommand('trimtokens', trimTokensCallback, [], 'limit=number (direction=start/end [text]) – trims the start or end of text to the specified number of tokens.', true, true); parser.addCommand('trimstart', trimStartCallback, [], '(text) – trims the text to the start of the first full sentence.', true, true); parser.addCommand('trimend', trimEndCallback, [], '(text) – trims the text to the end of the last full sentence.', true, true); @@ -255,6 +256,44 @@ function trimTokensCallback(arg, value) { } } +async function buttonsCallback(args, text) { + try { + const buttons = JSON.parse(resolveVariable(args?.labels)); + + if (!Array.isArray(buttons) || !buttons.length) { + console.warn('WARN: Invalid labels provided for /buttons command'); + return ''; + } + + return new Promise(async (resolve) => { + const safeValue = DOMPurify.sanitize(text || ''); + + const buttonContainer = document.createElement('div'); + buttonContainer.classList.add('flex-container', 'flexFlowColumn', 'wide100p', 'm-t-1'); + + for (const button of buttons) { + const buttonElement = document.createElement('div'); + buttonElement.classList.add('menu_button', 'wide100p'); + buttonElement.addEventListener('click', () => { + resolve(button); + $('#dialogue_popup_ok').trigger('click'); + }); + buttonElement.innerText = button; + buttonContainer.appendChild(buttonElement); + } + + const popupContainer = document.createElement('div'); + popupContainer.innerHTML = safeValue; + popupContainer.appendChild(buttonContainer); + callPopup(popupContainer, 'text', '', { okButton: 'Cancel' }) + .then(() => resolve('')) + .catch(() => resolve('')); + }) + } catch { + return ''; + } +} + async function popupCallback(_, value) { const safeValue = DOMPurify.sanitize(value || ''); await delay(1);