diff --git a/public/index.html b/public/index.html index c7c65dcaa..6ac83f389 100644 --- a/public/index.html +++ b/public/index.html @@ -1513,7 +1513,7 @@ - + @@ -3789,6 +3789,7 @@ Chat History +
diff --git a/public/script.js b/public/script.js index 4d4b711a9..4cca3d855 100644 --- a/public/script.js +++ b/public/script.js @@ -7833,20 +7833,22 @@ jQuery(async function () { if (popup_type == "del_chat") { //close past chat popup - $("#select_chat_cross").click(); - + $("#select_chat_cross").trigger('click'); + showLoader() if (selected_group) { await deleteGroupChat(selected_group, chat_file_for_del); } else { await delChat(chat_file_for_del); } - //open the history view again after 100ms + //open the history view again after 2seconds (delay to avoid edge cases for deleting last chat) //hide option popup menu setTimeout(function () { $("#option_select_chat").click(); $("#options").hide(); + hideLoader() }, 2000); + } if (popup_type == "del_ch") { const deleteChats = !!$("#del_char_checkbox").prop("checked"); @@ -8306,6 +8308,17 @@ jQuery(async function () { hideMenu(); }); + $("#newChatFromManageScreenButton").on('click', function () { + setTimeout(() => { + $("#option_start_new_chat").trigger('click'); + }, 1); + setTimeout(() => { + $("#dialogue_popup_ok").trigger('click'); + }, 1); + $("#select_chat_cross").trigger('click') + + }) + ////////////////////////////////////////////////////////////////////////////////////////////// //functionality for the cancel delete messages button, reverts to normal display of input form diff --git a/public/scripts/extensions/quick-reply/index.js b/public/scripts/extensions/quick-reply/index.js index fbedc200a..fc8669ab4 100644 --- a/public/scripts/extensions/quick-reply/index.js +++ b/public/scripts/extensions/quick-reply/index.js @@ -1,6 +1,6 @@ import { saveSettingsDebounced, callPopup, getRequestHeaders, substituteParams } from "../../../script.js"; import { getContext, extension_settings } from "../../extensions.js"; -import { initScrollHeight, resetScrollHeight } from "../../utils.js"; +import { initScrollHeight, resetScrollHeight, getSortableDelay } from "../../utils.js"; import { executeSlashCommands, registerSlashCommand } from "../../slash-commands.js"; import { ContextMenu } from "./src/ContextMenu.js"; import { MenuItem } from "./src/MenuItem.js"; @@ -308,6 +308,50 @@ async function saveQuickReplyPreset() { } } +//just a copy of save function with the name hardcoded to currently selected preset +async function updateQuickReplyPreset() { + const name = $("#quickReplyPresets").val() + + if (!name) { + return; + } + + const quickReplyPreset = { + name: name, + quickReplyEnabled: extension_settings.quickReply.quickReplyEnabled, + quickReplySlots: extension_settings.quickReply.quickReplySlots, + numberOfSlots: extension_settings.quickReply.numberOfSlots, + AutoInputInject: extension_settings.quickReply.AutoInputInject, + selectedPreset: name, + } + + const response = await fetch('/savequickreply', { + method: 'POST', + headers: getRequestHeaders(), + body: JSON.stringify(quickReplyPreset) + }); + + if (response.ok) { + const quickReplyPresetIndex = presets.findIndex(x => x.name == name); + + if (quickReplyPresetIndex == -1) { + presets.push(quickReplyPreset); + const option = document.createElement('option'); + option.selected = true; + option.value = name; + option.innerText = name; + $('#quickReplyPresets').append(option); + } + else { + presets[quickReplyPresetIndex] = quickReplyPreset; + $(`#quickReplyPresets option[value="${name}"]`).prop('selected', true); + } + saveSettingsDebounced(); + } else { + toastr.warning('Failed to save Quick Reply Preset.') + } +} + async function onQuickReplyNumberOfSlotsInput() { const $input = $('#quickReplyNumberOfSlots'); let numberOfSlots = Number($input.val()); @@ -351,8 +395,10 @@ function generateQuickReplyElements() { let quickReplyHtml = ''; for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) { + let itemNumber = i + 1 quickReplyHtml += ` -
+
+
@@ -412,6 +458,25 @@ async function doQR(_, text) { whichQR.trigger('click') } +function saveQROrder() { + //update html-level order data to match new sort + let i = 1 + $('#quickReplyContainer').children().each(function () { + $(this).attr('data-order', i) + $(this).find('input').attr('id', `quickReply${i}Label`) + $(this).find('textarea').attr('id', `quickReply${i}Mes`) + i++ + }); + + //rebuild the extension_Settings array based on new order + i = 1 + $('#quickReplyContainer').children().each(function () { + onQuickReplyLabelInput(i) + onQuickReplyInput(i) + i++ + }); +} + jQuery(async () => { moduleWorker(); setInterval(moduleWorker, UPDATE_INTERVAL); @@ -446,7 +511,10 @@ jQuery(async () => { +
@@ -473,6 +541,12 @@ jQuery(async () => { $('#quickReplyEnabled').on('input', onQuickReplyEnabledInput); $('#quickReplyNumberOfSlotsApply').on('click', onQuickReplyNumberOfSlotsInput); $("#quickReplyPresetSaveButton").on('click', saveQuickReplyPreset); + $("#quickReplyPresetUpdateButton").on('click', updateQuickReplyPreset); + + $('#quickReplyContainer').sortable({ + delay: getSortableDelay(), + stop: saveQROrder, + }); $("#quickReplyPresets").on('change', async function () { const quickReplyPresetSelected = $(this).find(':selected').val(); diff --git a/server.js b/server.js index a07e6cb56..12375c627 100644 --- a/server.js +++ b/server.js @@ -596,6 +596,10 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request, const modelName = modelInfo?.id; result = modelName || result; + } else { + // TabbyAPI returns an error 400 if a model isn't loaded + + result = "None" } } catch (error) { console.error(`Failed to get TabbyAPI model info: ${error}`);