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;