From d64d16bdf2425991fb725c2e5ade1ce3116667b1 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 00:27:55 +0200 Subject: [PATCH 01/11] Fix popup onClose executing after resolver --- public/scripts/popup.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/scripts/popup.js b/public/scripts/popup.js index ddd7dd5d0..c31824f0b 100644 --- a/public/scripts/popup.js +++ b/public/scripts/popup.js @@ -451,9 +451,9 @@ export class Popup { else popup.setAutoFocus(); } } - }); - this.resolver(this.value); + this.resolver(this.value); + }); } /** From 360c2985f50e21495e91dc1d2d6064a67726f32b Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 00:29:25 +0200 Subject: [PATCH 02/11] Switch char deletion to new popup - New popup - Move char CHARACTER_DELETED to after char deleting, and inside the correct function --- public/script.js | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/public/script.js b/public/script.js index 6e303a2f7..e69466d62 100644 --- a/public/script.js +++ b/public/script.js @@ -8659,13 +8659,11 @@ function doCloseChat() { * it proceeds to delete character from UI and saves settings. * In case of error during the fetch request, it logs the error details. * - * @param {string} popup_type - The type of popup currently active. * @param {string} this_chid - The character ID to be deleted. * @param {boolean} delete_chats - Whether to delete chats or not. */ -export async function handleDeleteCharacter(popup_type, this_chid, delete_chats) { - if (popup_type !== 'del_ch' || - !characters[this_chid]) { +export async function handleDeleteCharacter(this_chid, delete_chats) { + if (!characters[this_chid]) { return; } @@ -8711,6 +8709,8 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {}) await eventSource.emit(event_types.CHAT_DELETED, name); } } + + eventSource.emit(event_types.CHARACTER_DELETED, { id: this_chid, character: characters[this_chid] }); } /** @@ -9212,11 +9212,6 @@ jQuery(async function () { }, 2000); } } - if (popup_type == 'del_ch') { - const deleteChats = !!$('#del_char_checkbox').prop('checked'); - eventSource.emit(event_types.CHARACTER_DELETED, { id: this_chid, character: characters[this_chid] }); - await handleDeleteCharacter(popup_type, this_chid, deleteChats); - } if (popup_type == 'alternate_greeting' && menu_type !== 'create') { createOrEditCharacter(); } @@ -9297,15 +9292,27 @@ jQuery(async function () { $('#form_create').submit(createOrEditCharacter); - $('#delete_button').on('click', function () { - callPopup(` -

Delete the character?

- THIS IS PERMANENT!

+ $('#delete_button').on('click', async function () { + if (!this_chid) { + toastr.warning('No character selected.'); + return; + } + + let deleteChats = false; + + const confirm = await Popup.show.confirm('Delete the character?', ` + THIS IS PERMANENT!


`, 'del_ch', '', - ); +
`, { + onClose: () => deleteChats = !!$('#del_char_checkbox').prop('checked'), + }); + if (!confirm) { + return; + } + + await deleteCharacter(characters[this_chid].avatar, { deleteChats: deleteChats }); }); //////// OPTIMIZED ALL CHAR CREATION/EDITING TEXTAREA LISTENERS /////////////// From efb9fbcc7eb44c486736ffc6be4c01f94b710403 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 00:45:26 +0200 Subject: [PATCH 03/11] Refactor new chat to new popup --- public/script.js | 79 ++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/public/script.js b/public/script.js index e69466d62..507791c19 100644 --- a/public/script.js +++ b/public/script.js @@ -8551,6 +8551,39 @@ async function doImpersonate(args, prompt) { return ''; } +async function doNewChat({ deleteCurrentChat = false } = {}) { + //Make a new chat for selected character + if ((!selected_group && this_chid == undefined) || menu_type != 'create') { + return; + } + + //Fix it; New chat doesn't create while open create character menu + await clearChat(); + chat.length = 0; + + chat_file_for_del = getCurrentChatDetails()?.sessionName; + + // Make it easier to find in backups + if (deleteCurrentChat) { + await saveChatConditional(); + } + + if (selected_group) { + await createNewGroupChat(selected_group); + if (deleteCurrentChat) await deleteGroupChat(selected_group, chat_file_for_del); + } + else { + //RossAscends: added character name to new chat filenames and replaced Date.now() with humanizedDateTime; + chat_metadata = {}; + characters[this_chid].chat = `${name2} - ${humanizedDateTime()}`; + $('#selected_chat_pole').val(characters[this_chid].chat); + await getChat(); + await createOrEditCharacter(new CustomEvent('newChat')); + if (deleteCurrentChat) await delChat(chat_file_for_del + '.jsonl'); + } + +} + async function doDeleteChat() { await displayPastChats(); let currentChatDeleteButton = $('.select_chat_block[highlight=\'true\']').parent().find('.PastChat_cross'); @@ -9215,38 +9248,6 @@ jQuery(async function () { if (popup_type == 'alternate_greeting' && menu_type !== 'create') { createOrEditCharacter(); } - //Make a new chat for selected character - if ( - popup_type == 'new_chat' && - (selected_group || this_chid !== undefined) && - menu_type != 'create' - ) { - //Fix it; New chat doesn't create while open create character menu - await clearChat(); - chat.length = 0; - - chat_file_for_del = getCurrentChatDetails()?.sessionName; - const isDelChatCheckbox = document.getElementById('del_chat_checkbox')?.checked; - - // Make it easier to find in backups - if (isDelChatCheckbox) { - await saveChatConditional(); - } - - if (selected_group) { - await createNewGroupChat(selected_group); - if (isDelChatCheckbox) await deleteGroupChat(selected_group, chat_file_for_del); - } - else { - //RossAscends: added character name to new chat filenames and replaced Date.now() with humanizedDateTime; - chat_metadata = {}; - characters[this_chid].chat = `${name2} - ${humanizedDateTime()}`; - $('#selected_chat_pole').val(characters[this_chid].chat); - await getChat(); - await createOrEditCharacter(new CustomEvent('newChat')); - if (isDelChatCheckbox) await delChat(chat_file_for_del + '.jsonl'); - } - } if (dialogueResolve) { if (popup_type == 'input') { @@ -9574,14 +9575,20 @@ jQuery(async function () { else if (id == 'option_start_new_chat') { if ((selected_group || this_chid !== undefined) && !is_send_press) { - callPopup(` -

Start new chat?


+ let deleteCurrentChat = false; + const result = await Popup.show.confirm('Start new chat?', `
- `, 'new_chat', ''); + `, { + onClose: () => deleteCurrentChat = !!$('#del_chat_checkbox').prop('checked'), + }); + if (!result) { + return; + } + + await doNewChat({ deleteCurrentChat: deleteCurrentChat }); } } From 1c6c9efba18182f297b6755c17e27717ed05f8a8 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 01:01:43 +0200 Subject: [PATCH 04/11] Refactor convert to group chat to new popup --- public/script.js | 2 +- public/scripts/bookmarks.js | 4 ++-- public/scripts/popup.js | 16 ++++++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/public/script.js b/public/script.js index 507791c19..519865dec 100644 --- a/public/script.js +++ b/public/script.js @@ -8553,7 +8553,7 @@ async function doImpersonate(args, prompt) { async function doNewChat({ deleteCurrentChat = false } = {}) { //Make a new chat for selected character - if ((!selected_group && this_chid == undefined) || menu_type != 'create') { + if ((!selected_group && this_chid == undefined) || menu_type == 'create') { return; } diff --git a/public/scripts/bookmarks.js b/public/scripts/bookmarks.js index f099ba047..f6a2d1d70 100644 --- a/public/scripts/bookmarks.js +++ b/public/scripts/bookmarks.js @@ -24,6 +24,7 @@ import { saveGroupBookmarkChat, selected_group, } from './group-chats.js'; +import { Popup } from './popup.js'; import { createTagMapFromList } from './tags.js'; import { @@ -239,8 +240,7 @@ async function convertSoloToGroupChat() { return; } - const confirm = await callPopup('Are you sure you want to convert this chat to a group chat?', 'confirm'); - + const confirm = await Popup.show.confirm('Convert to group chat', 'Are you sure you want to convert this chat to a group chat?
This cannot be reverted.'); if (!confirm) { return; } diff --git a/public/scripts/popup.js b/public/scripts/popup.js index c31824f0b..d2138b722 100644 --- a/public/scripts/popup.js +++ b/public/scripts/popup.js @@ -78,8 +78,8 @@ const showPopupHelper = { /** * Asynchronously displays a confirmation popup with the given header and text, returning the clicked result button value. * - * @param {string} header - The header text for the popup. - * @param {string} text - The main text for the popup. + * @param {string?} header - The header text for the popup. + * @param {string?} text - The main text for the popup. * @param {PopupOptions} [popupOptions={}] - Options for the popup. * @return {Promise} A Promise that resolves with the result of the user's interaction. */ @@ -491,9 +491,17 @@ export class Popup { } class PopupUtils { + /** + * Builds popup content with header and text below + * + * @param {string} header - The header to be added to the text + * @param {string} text - The main text content + */ static BuildTextWithHeader(header, text) { - return ` -

${header}

+ if (!header) { + return text; + } + return `

${header}

${text}`; } } From f73986d23f8f35b250cf0319bab105acc2f8ddcc Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 27 Jun 2024 02:25:08 +0300 Subject: [PATCH 05/11] Remove extra linebreak --- public/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/script.js b/public/script.js index 519865dec..8b3e9a30d 100644 --- a/public/script.js +++ b/public/script.js @@ -9306,7 +9306,7 @@ jQuery(async function () {
`, { + `, { onClose: () => deleteChats = !!$('#del_char_checkbox').prop('checked'), }); if (!confirm) { From 7bf793d2be2ab1e92297520bccc6cdc233fd36de Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 01:39:05 +0200 Subject: [PATCH 06/11] Update /newchat command skip popup --- public/script.js | 2 +- public/scripts/power-user.js | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/public/script.js b/public/script.js index 8b3e9a30d..499f5cc6f 100644 --- a/public/script.js +++ b/public/script.js @@ -8551,7 +8551,7 @@ async function doImpersonate(args, prompt) { return ''; } -async function doNewChat({ deleteCurrentChat = false } = {}) { +export async function doNewChat({ deleteCurrentChat = false } = {}) { //Make a new chat for selected character if ((!selected_group && this_chid == undefined) || menu_type == 'create') { return; diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index 654e479b2..e167109e8 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -22,6 +22,7 @@ import { setActiveGroup, setActiveCharacter, entitiesFilter, + doNewChat, } from '../script.js'; import { isMobile, initMovingUI, favsToHotswap } from './RossAscends-mods.js'; import { @@ -39,11 +40,11 @@ import { tokenizers } from './tokenizers.js'; import { BIAS_CACHE } from './logit-bias.js'; import { renderTemplateAsync } from './templates.js'; -import { countOccurrences, debounce, delay, download, getFileText, isOdd, onlyUnique, resetScrollHeight, shuffle, sortMoments, stringToRange, timestampToMoment } from './utils.js'; +import { countOccurrences, debounce, delay, download, getFileText, isOdd, isTrueBoolean, onlyUnique, resetScrollHeight, shuffle, sortMoments, stringToRange, timestampToMoment } from './utils.js'; import { FILTER_TYPES } from './filters.js'; import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js'; import { SlashCommand } from './slash-commands/SlashCommand.js'; -import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashCommandArgument.js'; +import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; import { AUTOCOMPLETE_WIDTH } from './autocomplete/AutoComplete.js'; import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; @@ -2530,14 +2531,6 @@ async function resetMovablePanels(type) { }); } -async function doNewChat() { - $('#option_start_new_chat').trigger('click'); - await delay(1); - $('#dialogue_popup_ok').trigger('click'); - await delay(1); - return ''; -} - /** * Finds the ID of the tag with the given name. * @param {string} name @@ -3926,7 +3919,20 @@ $(document).ready(() => { })); SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'newchat', - callback: doNewChat, + /** @type {(args: { delete: string?}, string) => Promise<''>} */ + callback: async (args, _) => { + await doNewChat({ deleteCurrentChat: isTrueBoolean(args.delete) }); + return ''; + }, + namedArgumentList: [ + SlashCommandNamedArgument.fromProps({ + name: 'delete', + description: 'delete the current chat', + typeList: [ARGUMENT_TYPE.BOOLEAN], + defaultValue: 'false', + enumList: commonEnumProviders.boolean('trueFalse')(), + }), + ], helpString: 'Start a new chat with the current character', })); SlashCommandParser.addCommandObject(SlashCommand.fromProps({ From 124cbfdfa40f646eb8a00d42d3eccd2064a23417 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 02:28:25 +0200 Subject: [PATCH 07/11] Update Popup to support custom input checkboxes --- public/css/popup.css | 18 ++++++++ public/index.html | 1 + public/scripts/popup.js | 95 +++++++++++++++++++++++++++++++---------- public/style.css | 12 ------ 4 files changed, 92 insertions(+), 34 deletions(-) diff --git a/public/css/popup.css b/public/css/popup.css index 045bfc2e5..90d0914f0 100644 --- a/public/css/popup.css +++ b/public/css/popup.css @@ -92,6 +92,24 @@ dialog { text-align: left; } +.popup-crop-wrap { + margin: 10px auto; + max-height: 75vh; + max-height: 75svh; + max-width: 100%; +} + +.popup-crop-wrap img { + max-width: 100%; + /* This rule is very important, please do not ignore this! */ +} + +.popup-inputs { + margin-top: 10px; + font-size: smaller; + opacity: 0.7; +} + .popup-input { margin-top: 10px; } diff --git a/public/index.html b/public/index.html index d815e2300..8593d2ffc 100644 --- a/public/index.html +++ b/public/index.html @@ -4883,6 +4883,7 @@ + - - - - From b8ae54fb2c9e8f5899cda8fe856c9cf5fa423c73 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 27 Jun 2024 03:01:07 +0200 Subject: [PATCH 11/11] Add i18n to popup controls --- public/scripts/popup.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/public/scripts/popup.js b/public/scripts/popup.js index 7f61b8ac5..a34b9f1f0 100644 --- a/public/scripts/popup.js +++ b/public/scripts/popup.js @@ -178,7 +178,9 @@ export class Popup { // If custom button captions are provided, we set them beforehand this.okButton.textContent = typeof okButton === 'string' ? okButton : 'OK'; + this.okButton.dataset.i18n = this.okButton.textContent; this.cancelButton.textContent = typeof cancelButton === 'string' ? cancelButton : template.getAttribute('popup-button-cancel'); + this.cancelButton.dataset.i18n = this.cancelButton.textContent; this.defaultResult = defaultResult; this.customButtons = customButtons; @@ -191,6 +193,7 @@ export class Popup { buttonElement.classList.add(...(button.classes ?? [])); buttonElement.dataset.result = String(button.result ?? undefined); buttonElement.textContent = button.text; + buttonElement.dataset.i18n = buttonElement.textContent; buttonElement.tabIndex = 0; if (button.appendAtEnd) { @@ -226,8 +229,9 @@ export class Popup { if (input.tooltip) { const tooltip = document.createElement('div'); - tooltip.title = input.tooltip; tooltip.classList.add('fa-solid', 'fa-circle-info', 'opacity50p'); + tooltip.title = input.tooltip; + tooltip.dataset.i18n = '[title]' + input.tooltip; label.appendChild(tooltip); } @@ -462,7 +466,7 @@ export class Popup { if (!shouldClose) return; } - Popup.util.lastResult = { value, result }; + Popup.util.lastResult = { value, result, inputResults: this.inputResults }; this.#hide(); } @@ -518,10 +522,10 @@ export class Popup { * Contains the list of all currently open popups, and it'll remember the result of the last closed popup. */ static util = { - /** @type {Popup[]} Remember all popups */ + /** @readonly @type {Popup[]} Remember all popups */ popups: [], - /** @type {{value: any, result: POPUP_RESULT|number?}?} Last popup result */ + /** @type {{value: any, result: POPUP_RESULT|number?, inputResults: Map?}?} Last popup result */ lastResult: null, /** @returns {boolean} Checks if any modal popup dialog is open */