diff --git a/public/scripts/extensions.js b/public/scripts/extensions.js index b21d7348a..2f7c834d8 100644 --- a/public/scripts/extensions.js +++ b/public/scripts/extensions.js @@ -57,6 +57,7 @@ const extension_settings = { chromadb: {}, translate: {}, objective: {}, + quickReply: {}, }; let modules = []; diff --git a/public/scripts/extensions/quick-reply/index.js b/public/scripts/extensions/quick-reply/index.js new file mode 100644 index 000000000..c37f4b635 --- /dev/null +++ b/public/scripts/extensions/quick-reply/index.js @@ -0,0 +1,174 @@ +import { saveSettingsDebounced } from "../../../script.js"; +import { getContext, extension_settings } from "../../extensions.js"; +import { initScrollHeight, resetScrollHeight } from "../../utils.js"; + +export { MODULE_NAME }; + +const MODULE_NAME = 'quick-reply'; +const UPDATE_INTERVAL = 1000; + +const defaultSettings = { + quickReply1Mes: '', + quickReply1Label: '', + quickReply2Mes: '', + quickReply2Label: '', + quickReply3Mes: '', + quickReply3Label: '', + quickReply4Mes: '', + quickReply4Label: '', + quickReply5Mes: '', + quickReply5Label: '', + quickReplyEnabled: false, +} + +async function loadSettings() { + if (Object.keys(extension_settings.quickReply).length === 0) { + Object.assign(extension_settings.quickReply, defaultSettings); + } + + $('#quickReplyEnabled').prop('checked', extension_settings.quickReply.quickReplyEnabled); + + $('#quickReply1Mes').val(extension_settings.quickReply.quickReply1Mes).trigger('input'); + $('#quickReply1Label').val(extension_settings.quickReply.quickReply1Label).trigger('input'); + + $('#quickReply2Mes').val(extension_settings.quickReply.quickReply2Mes).trigger('input'); + $('#quickReply2Label').val(extension_settings.quickReply.quickReply2Label).trigger('input'); + + $('#quickReply3Mes').val(extension_settings.quickReply.quickReply3Mes).trigger('input'); + $('#quickReply3Label').val(extension_settings.quickReply.quickReply3Label).trigger('input'); + + $('#quickReply4Mes').val(extension_settings.quickReply.quickReply4Mes).trigger('input'); + $('#quickReply4Label').val(extension_settings.quickReply.quickReply4Label).trigger('input'); + + $('#quickReply5Mes').val(extension_settings.quickReply.quickReply5Mes).trigger('input'); + $('#quickReply5Label').val(extension_settings.quickReply.quickReply5Label).trigger('input'); +} + +function onQuickReplyInput(id) { + extension_settings.quickReply[`quickReply${id}Mes`] = $(`#quickReply${id}Mes`).val(); + $(`#quickReply${id}`).attr('title', ($(`#quickReply${id}Mes`).val())); + resetScrollHeight($(`#quickReply${id}Mes`)); + saveSettingsDebounced(); +} + +function onQuickReplyLabelInput(id) { + extension_settings.quickReply[`quickReply${id}Label`] = $(`#quickReply${id}Label`).val(); + $(`#quickReply${id}`).text($(`#quickReply${id}Label`).val()); + saveSettingsDebounced(); +} + +async function onQuickReplyEnabledInput() { + let isEnabled = $(this).prop('checked') + extension_settings.quickReply.quickReplyEnabled = !!isEnabled; + if (isEnabled === true) { + $("#quickReplyBar").show(); + } else { $("#quickReplyBar").hide(); } + saveSettingsDebounced(); +} + +async function sendQuickReply(id) { + var prompt = extension_settings.quickReply[`${id}Mes`]; + $("#send_textarea").val(prompt); + $("#send_but").trigger('click'); +} + +function addQuickReplyBar(numButtons) { + var numButtons = 5; + const quickReplyBarStartHtml = ` +
+
+ `; + let quickReplyButtonHtml = ''; + for (let i = 0; i < numButtons; i++) { + let quickReplyMes = extension_settings.quickReply[`quickReply${i + 1}Mes`]; + let quickReplyLabel = extension_settings.quickReply[`quickReply${i + 1}Label`]; + console.log(quickReplyMes); + quickReplyButtonHtml += `
${quickReplyLabel}
`; + } + const quickReplyEndHtml = `
` + const quickReplyBarFullHtml = [quickReplyBarStartHtml, quickReplyButtonHtml, quickReplyEndHtml].join(''); + + $('#send_form').prepend(quickReplyBarFullHtml); + + $('.quickReplyButton').on('click', function () { + console.log('got quick reply click'); + let quickReplyButtonID = $(this).attr('id'); + sendQuickReply(quickReplyButtonID); + }); +} + + +async function moduleWorker() { + if (extension_settings.quickReply.quickReplyEnabled === true) { + $('#quickReplyBar').toggle(getContext().onlineStatus !== 'no_connection'); + } +} + +jQuery(async () => { + + moduleWorker(); + setInterval(moduleWorker, UPDATE_INTERVAL); + const settingsHtml = ` +
+
+
+ Quick Reply +
+
+
+ + Customize your Quick Replies:
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
`; + + $('#extensions_settings').append(settingsHtml); + + $('#quickReply1Mes').on('input', function () { onQuickReplyInput(1); }); + $('#quickReply2Mes').on('input', function () { onQuickReplyInput(2); }); + $('#quickReply3Mes').on('input', function () { onQuickReplyInput(3); }); + $('#quickReply4Mes').on('input', function () { onQuickReplyInput(4); }); + $('#quickReply5Mes').on('input', function () { onQuickReplyInput(5); }); + + $('#quickReply1Label').on('input', function () { onQuickReplyLabelInput(1); }); + $('#quickReply2Label').on('input', function () { onQuickReplyLabelInput(2); }); + $('#quickReply3Label').on('input', function () { onQuickReplyLabelInput(3); }); + $('#quickReply4Label').on('input', function () { onQuickReplyLabelInput(4); }); + $('#quickReply5Label').on('input', function () { onQuickReplyLabelInput(5); }); + + $('#quickReplyEnabled').on('input', onQuickReplyEnabledInput); + + $('.quickReplySettings .inline-drawer-toggle').on('click', function () { + initScrollHeight($("#quickReply1Mes")); + initScrollHeight($("#quickReply2Mes")); + initScrollHeight($("#quickReply3Mes")); + initScrollHeight($("#quickReply4Mes")); + initScrollHeight($("#quickReply5Mes")); + }) + + await loadSettings(); + addQuickReplyBar(); +}); + diff --git a/public/scripts/extensions/quick-reply/manifest.json b/public/scripts/extensions/quick-reply/manifest.json new file mode 100644 index 000000000..e104a5761 --- /dev/null +++ b/public/scripts/extensions/quick-reply/manifest.json @@ -0,0 +1,11 @@ +{ + "display_name": "Quick Replies", + "loading_order": 12, + "requires": [], + "optional": [], + "js": "index.js", + "css": "style.css", + "author": "RossAscends#1779", + "version": "1.0.0", + "homePage": "https://github.com/SillyTavern/SillyTavern" +} \ No newline at end of file diff --git a/public/scripts/extensions/quick-reply/style.css b/public/scripts/extensions/quick-reply/style.css new file mode 100644 index 000000000..7df2c3d8f --- /dev/null +++ b/public/scripts/extensions/quick-reply/style.css @@ -0,0 +1,47 @@ +#quickReplyBar { + outline: none; + padding: 5px 0; + border-bottom: 1px solid var(--black30a); + margin: 0; + transition: 0.3s; + opacity: 0.7; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + display: none; +} + +#quickReplies { + margin: 0; + padding: 0; + display: flex; + justify-content: center; + flex-wrap: nowrap; + gap: 5px; + width: 100%; +} + +#quickReplies div { + color: var(--SmartThemeBodyColor); + background-color: var(--black50a); + border: 1px solid var(--white30a); + border-radius: 10px; + padding: 3px 5px; + width: min-content; + cursor: pointer; + transition: 0.3s; + display: flex; + align-items: center; + justify-content: center; + text-align: center; +} + +#quickReplies div:hover { + opacity: 1; + filter: brightness(1.2); + cursor: pointer; + + + +} \ No newline at end of file diff --git a/public/style.css b/public/style.css index 0160a1784..347df934b 100644 --- a/public/style.css +++ b/public/style.css @@ -412,6 +412,7 @@ code { #send_form { display: flex; + flex-wrap: wrap; align-items: center; width: 100%; margin: 0 auto 0 auto; @@ -4477,4 +4478,4 @@ body.waifuMode #avatar_zoom_popup { overflow-y: auto; overflow-x: hidden; } -} +} \ No newline at end of file