diff --git a/public/scripts/extensions.js b/public/scripts/extensions.js index 49b834539..d0172539b 100644 --- a/public/scripts/extensions.js +++ b/public/scripts/extensions.js @@ -147,6 +147,36 @@ function autoConnectInputHandler() { saveSettingsDebounced(); } +function addExtensionsButtonAndMenu() { + const buttonHTML = + `
`; + const extensionsMenuHTML = `
`; + + $(document.body).append(extensionsMenuHTML); + + $('#send_but_sheld').prepend(buttonHTML); + + const button = $('#extensionsMenuButton'); + const dropdown = $('#extensionsMenu'); + + let popper = Popper.createPopper(button.get(0), dropdown.get(0), { + placement: 'top-end', + }); + + $(document).on('click touchend', function (e) { + const target = $(e.target); + if (target.is(dropdown)) return; + if (target.is(button) && !dropdown.is(":visible")) { + e.preventDefault(); + + dropdown.show(200); + popper.update(); + } else { + dropdown.hide(200); + } + }); +} + async function connectToApi(baseUrl) { if (!baseUrl) { return; @@ -163,6 +193,7 @@ async function connectToApi(baseUrl) { modules = data.modules; await activateExtensions(); eventSource.emit(event_types.EXTRAS_CONNECTED, modules); + $("#extensionsMenuButton").css("display", "flex"); } updateStatus(getExtensionsResult.ok); @@ -287,6 +318,7 @@ async function loadExtensionSettings(settings) { } $(document).ready(async function () { + setTimeout(function () { addExtensionsButtonAndMenu(); }, 100) $("#extensions_connect").on('click', connectClickHandler); $("#extensions_autoconnect").on('input', autoConnectInputHandler); $("#extensions_details").on('click', showExtensionsDetails); diff --git a/public/scripts/extensions/dice/index.js b/public/scripts/extensions/dice/index.js index 35f791140..ebac90681 100644 --- a/public/scripts/extensions/dice/index.js +++ b/public/scripts/extensions/dice/index.js @@ -8,7 +8,7 @@ const UPDATE_INTERVAL = 1000; function setDiceIcon() { const sendButton = document.getElementById('roll_dice'); /* sendButton.style.backgroundImage = `url(/img/dice-solid.svg)`; */ - sendButton.classList.remove('spin'); + //sendButton.classList.remove('spin'); } async function doDiceRoll() { @@ -29,7 +29,7 @@ async function doDiceRoll() { function addDiceRollButton() { const buttonHtml = ` -
+
`; const dropdownHtml = `
@@ -45,7 +45,8 @@ function addDiceRollButton() {
`; - $('#send_but_sheld').prepend(buttonHtml); + $('#extensionsMenu').prepend(buttonHtml); + $(document.body).append(dropdownHtml) $('#dice_dropdown li').on('click', doDiceRoll); const button = $('#roll_dice'); @@ -54,7 +55,7 @@ function addDiceRollButton() { button.hide(); let popper = Popper.createPopper(button.get(0), dropdown.get(0), { - placement: 'top-start', + placement: 'left-end', }); $(document).on('click touchend', function (e) { diff --git a/public/scripts/extensions/dice/style.css b/public/scripts/extensions/dice/style.css index e7cf3c0bf..f574d81fe 100644 --- a/public/scripts/extensions/dice/style.css +++ b/public/scripts/extensions/dice/style.css @@ -1,9 +1,9 @@ #roll_dice { order: 100; - width: 40px; + /* width: 40px; height: 40px; margin: 0; - padding: 1px; + padding: 1px; */ outline: none; border: none; cursor: pointer; diff --git a/public/scripts/extensions/stable-diffusion/index.js b/public/scripts/extensions/stable-diffusion/index.js index e6f190516..c6f175192 100644 --- a/public/scripts/extensions/stable-diffusion/index.js +++ b/public/scripts/extensions/stable-diffusion/index.js @@ -537,11 +537,11 @@ async function sendMessage(prompt, image) { function addSDGenButtons() { const buttonHtml = ` -
+
`; const waitButtonHtml = ` -
+
` const dropdownHtml = `
@@ -556,8 +556,8 @@ function addSDGenButtons() {
`; - $('#send_but_sheld').prepend(buttonHtml); - $('#send_but_sheld').prepend(waitButtonHtml); + $('#extensionsMenu').prepend(buttonHtml); + $('#extensionsMenu').prepend(waitButtonHtml); $(document.body).append(dropdownHtml); const messageButton = $('.sd_message_gen'); @@ -570,7 +570,7 @@ function addSDGenButtons() { messageButton.hide(); let popper = Popper.createPopper(button.get(0), dropdown.get(0), { - placement: 'top-end', + placement: 'left-end', }); $(document).on('click', '.sd_message_gen', sdMessageButton); diff --git a/public/scripts/extensions/stable-diffusion/style.css b/public/scripts/extensions/stable-diffusion/style.css index 3cb72e138..b7f4f3839 100644 --- a/public/scripts/extensions/stable-diffusion/style.css +++ b/public/scripts/extensions/stable-diffusion/style.css @@ -4,10 +4,10 @@ #sd_gen { order: 100; - width: 40px; + /* width: 40px; height: 40px; margin: 0; - padding: 1px; + padding: 1px; */ outline: none; border: none; cursor: pointer; diff --git a/public/scripts/extensions/tts/index.js b/public/scripts/extensions/tts/index.js index 0531752fb..e5fd6e1e6 100644 --- a/public/scripts/extensions/tts/index.js +++ b/public/scripts/extensions/tts/index.js @@ -70,10 +70,10 @@ async function moduleWorker() { processTtsQueue() processAudioJobQueue() updateUiAudioPlayState() - + // Auto generation is disabled - if (extension_settings.tts.auto_generation == false){ + if (extension_settings.tts.auto_generation == false) { return } @@ -153,7 +153,7 @@ function isTtsProcessing() { let processing = false // Check job queues - if (ttsJobQueue.length > 0 || audioJobQueue > 0){ + if (ttsJobQueue.length > 0 || audioJobQueue > 0) { processing = true } // Check current jobs @@ -178,7 +178,7 @@ let lastAudioPosition = 0 async function playAudioData(audioBlob) { // Since current audio job can be cancelled, don't playback if it is null - if (currentAudioJob == null){ + if (currentAudioJob == null) { console.log("Cancelled TTS playback because currentAudioJob was null") } const reader = new FileReader() @@ -212,7 +212,12 @@ async function onTtsVoicesClick() { const voiceIds = await ttsProvider.fetchTtsVoiceIds() for (const voice of voiceIds) { - popupText += `
${voice.lang || ''} ${voice.name}
` + popupText += ` +
+ ${voice.lang || ''} + ${voice.name} + +
` popupText += `` } } catch { @@ -227,10 +232,10 @@ function updateUiAudioPlayState() { audioControl.style.display = 'flex' let img // Give user feedback that TTS is active by setting the stop icon if processing or playing - if (!audioElement.paused || isTtsProcessing()){ - img = 'fa-solid fa-stop-circle' + if (!audioElement.paused || isTtsProcessing()) { + img = 'fa-solid fa-stop-circle list-group-item' } else { - img = 'fa-solid fa-circle-play' + img = 'fa-solid fa-circle-play list-group-item' } audioControl.className = img } else { @@ -241,7 +246,7 @@ function updateUiAudioPlayState() { function onAudioControlClicked() { let context = getContext() // Not pausing, doing a full stop to anything TTS is doing. Better UX as pause is not as useful - if (!audioElement.paused || isTtsProcessing()){ + if (!audioElement.paused || isTtsProcessing()) { resetTtsPlayback() } else { // Default play behavior if not processing or playing is to play the last message. @@ -251,7 +256,7 @@ function onAudioControlClicked() { } function addAudioControl() { - $('#send_but_sheld').prepend('
') + $('#extensionsMenu').prepend('
') $('#tts_media_control').attr('title', 'TTS play/pause').on('click', onAudioControlClicked) audioControl = document.getElementById('tts_media_control') updateUiAudioPlayState() @@ -459,7 +464,7 @@ function onApplyClick() { console.error(error) setTtsStatus(error, false) }) - + extension_settings.tts[ttsProviderName] = ttsProvider.settings saveSettingsDebounced() setTtsStatus('Successfully applied settings', true) @@ -539,7 +544,7 @@ function onTtsProviderSettingsInput() { ttsProvider.onSettingsChange() // Persist changes to SillyTavern tts extension settings - + extension_settings.tts[ttsProviderName] = ttsProvider.setttings saveSettingsDebounced() console.info(`Saved settings ${ttsProviderName} ${JSON.stringify(ttsProvider.settings)}`) diff --git a/public/scripts/extensions/tts/style.css b/public/scripts/extensions/tts/style.css index 3785f0b04..77ece89cd 100644 --- a/public/scripts/extensions/tts/style.css +++ b/public/scripts/extensions/tts/style.css @@ -1,9 +1,9 @@ #tts_media_control { order: 100; - width: 40px; + /* width: 40px; height: 40px; margin: 0; - padding: 1px; + padding: 1px; */ outline: none; border: none; cursor: pointer; diff --git a/public/style.css b/public/style.css index fafad3328..e1ba569d6 100644 --- a/public/style.css +++ b/public/style.css @@ -486,6 +486,38 @@ code { border-top: 1px solid var(--white30a); } +#extensionsMenuButton { + order: 100; + width: 40px; + height: 40px; + margin: 0; + padding: 1px; + outline: none; + border: none; + cursor: pointer; + transition: 0.3s; + opacity: 0.7; + display: flex; + align-items: center; + justify-content: center; + display: none; + +} + +#extensionsMenuButton:hover { + opacity: 1; + filter: brightness(1.2); +} + +#extensionsMenu { + z-index: 100; + backdrop-filter: blur(var(--SmartThemeBlurStrength)); + font-size: 30px; + /* padding: 10px; */ + display: flex; + gap: 10px; +} + #right-nav-panel hr, #personality_div hr, #top-settings-holder hr { @@ -493,7 +525,8 @@ code { min-height: 1px; } -.options-content a { +.options-content a, +#extensionsMenu div { color: var(--SmartThemeBodyColor); padding: 12px 16px; text-decoration: none;