mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Refactor overwrite check to utility function
- Refactor overwrite check to utility function - Don't mind me refactoring character delete functions. I tried something, but I think the refactoring still makes sense
This commit is contained in:
@@ -4,7 +4,6 @@ import {
|
||||
characterGroupOverlay,
|
||||
callPopup,
|
||||
characters,
|
||||
deleteCharacter,
|
||||
event_types,
|
||||
eventSource,
|
||||
getCharacters,
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
buildAvatarList,
|
||||
characterToEntity,
|
||||
printCharactersDebounced,
|
||||
deleteCharacter,
|
||||
} from '../script.js';
|
||||
|
||||
import { favsToHotswap } from './RossAscends-mods.js';
|
||||
@@ -115,24 +115,7 @@ class CharacterContextMenu {
|
||||
static delete = async (characterId, deleteChats = false) => {
|
||||
const character = CharacterContextMenu.#getCharacter(characterId);
|
||||
|
||||
return fetch('/api/characters/delete', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ avatar_url: character.avatar, delete_chats: deleteChats }),
|
||||
cache: 'no-cache',
|
||||
}).then(response => {
|
||||
if (response.ok) {
|
||||
eventSource.emit(event_types.CHARACTER_DELETED, { id: characterId, character: character });
|
||||
return deleteCharacter(character.name, character.avatar, false).then(() => {
|
||||
if (deleteChats) getPastCharacterChats(characterId).then(pastChats => {
|
||||
for (const chat of pastChats) {
|
||||
const name = chat.file_name.replace('.jsonl', '');
|
||||
eventSource.emit(event_types.CHAT_DELETED, name);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
await deleteCharacter(character.avatar, { deleteChats: deleteChats });
|
||||
};
|
||||
|
||||
static #getCharacter = (characterId) => characters[characterId] ?? null;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { getContext } from './extensions.js';
|
||||
import { getRequestHeaders } from '../script.js';
|
||||
import { callPopup, getRequestHeaders } from '../script.js';
|
||||
import { isMobile } from './RossAscends-mods.js';
|
||||
import { collapseNewlines } from './power-user.js';
|
||||
import { debounce_timeout } from './constants.js';
|
||||
@@ -1720,3 +1720,38 @@ export function highlightRegex(regexStr) {
|
||||
|
||||
return `<span class="regex-highlight">${regexStr}</span>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms if the user wants to overwrite an existing data object (like character, world info, etc) if one exists.
|
||||
* If no data with the name exists, this simply returns true.
|
||||
*
|
||||
* @param {string} type - The type of the check ("World Info", "Character", etc)
|
||||
* @param {string[]} existingNames - The list of existing names to check against
|
||||
* @param {string} name - The new name
|
||||
* @param {object} options - Optional parameters
|
||||
* @param {boolean} [options.interactive=false] - Whether to show a confirmation dialog when needing to overwrite an existing data object
|
||||
* @param {string} [options.actionName='overwrite'] - The action name to display in the confirmation dialog
|
||||
* @param {(existingName:string)=>void} [options.deleteAction=null] - Optional action to execute wen deleting an existing data object on overwrite
|
||||
* @returns {Promise<boolean>} True if the user confirmed the overwrite or there is no overwrite needed, false otherwise
|
||||
*/
|
||||
export async function checkOverwriteExistingData(type, existingNames, name, { interactive = false, actionName = 'Overwrite', deleteAction = null } = {}) {
|
||||
const existing = existingNames.find(x => equalsIgnoreCaseAndAccents(x, name));
|
||||
if (!existing) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const overwrite = interactive ? await callPopup(`<h3>${type} ${actionName}</h3><p>A ${type.toLowerCase()} with the same name already exists:<br />${existing}</p>Do you want to overwrite it?`, 'confirm') : false;
|
||||
if (!overwrite) {
|
||||
toastr.warning(`${type} ${actionName.toLowerCase()} cancelled. A ${type.toLowerCase()} with the same name already exists:<br />${existing}`, `${type} ${actionName}`, { escapeHtml: false });
|
||||
return false;
|
||||
}
|
||||
|
||||
toastr.info(`Overwriting Existing ${type}:<br />${existing}`, `${type} ${actionName}`, { escapeHtml: false });
|
||||
|
||||
// If there is an action to delete the existing data, do it, as the name might be slightly different so file name would not be the same
|
||||
if (deleteAction) {
|
||||
deleteAction(existing);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles } from '../script.js';
|
||||
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, equalsIgnoreCaseAndAccents, getSanitizedFilename } from './utils.js';
|
||||
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, equalsIgnoreCaseAndAccents, getSanitizedFilename, checkOverwriteExistingData } from './utils.js';
|
||||
import { extension_settings, getContext } from './extensions.js';
|
||||
import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';
|
||||
import { isMobile } from './RossAscends-mods.js';
|
||||
@@ -2619,27 +2619,27 @@ function getFreeWorldName() {
|
||||
* Creates a new world info/lorebook with the given name.
|
||||
* Checks if a world with the same name already exists, providing a warning or optionally a user confirmation dialog.
|
||||
*
|
||||
* @param {string} worldInfoName - The name of the new world info
|
||||
* @param {string} worldName - The name of the new world info
|
||||
* @param {Object} options - Optional parameters
|
||||
* @param {boolean} [options.interactive=false] - Whether to show a confirmation dialog when overwriting an existing world
|
||||
* @returns {Promise<boolean>} - True if the world info was successfully created, false otherwise
|
||||
*/
|
||||
async function createNewWorldInfo(worldInfoName, { interactive = false } = {}) {
|
||||
async function createNewWorldInfo(worldName, { interactive = false } = {}) {
|
||||
const worldInfoTemplate = { entries: {} };
|
||||
|
||||
if (!worldInfoName) {
|
||||
if (!worldName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const allowed = await checkCanOverwriteWorldInfo(worldInfoName, { interactive: interactive, actionName: 'Create' });
|
||||
const allowed = await checkOverwriteExistingData('World Info', world_names, worldName, { interactive: interactive, actionName: 'Create', deleteAction: (existingName) => deleteWorldInfo(existingName) });
|
||||
if (!allowed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await saveWorldInfo(worldInfoName, worldInfoTemplate, true);
|
||||
await saveWorldInfo(worldName, worldInfoTemplate, true);
|
||||
await updateWorldInfoList();
|
||||
|
||||
const selectedIndex = world_names.indexOf(worldInfoName);
|
||||
const selectedIndex = world_names.indexOf(worldName);
|
||||
if (selectedIndex !== -1) {
|
||||
$('#world_editor_select').val(selectedIndex).trigger('change');
|
||||
} else {
|
||||
@@ -2649,37 +2649,6 @@ async function createNewWorldInfo(worldInfoName, { interactive = false } = {}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Confirms if the user wants to overwrite an existing world info with the same name.
|
||||
* If no world info with the name exists, this simply returns true
|
||||
*
|
||||
* @param {string} name - The name of the world info to create
|
||||
* @param {Object} options - Optional parameters
|
||||
* @param {boolean} [options.interactive=false] - Whether to show a confirmation dialog when overwriting an existing world
|
||||
* @param {string} [options.actionName='overwrite'] - The action name to display in the confirmation dialog
|
||||
* @returns {Promise<boolean>} True if the user confirmed the overwrite, false otherwise
|
||||
*/
|
||||
async function checkCanOverwriteWorldInfo(name, { interactive = false, actionName = 'Overwrite' } = {}) {
|
||||
const existingWorld = world_names.find(x => equalsIgnoreCaseAndAccents(x, name));
|
||||
if (!existingWorld) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const overwrite = interactive ? await callPopup(`<h3>World Info ${actionName}</h3><p>A world with the same name already exists:<br />${existingWorld}</p>Do you want to overwrite it?`, 'confirm') : false;
|
||||
if (!overwrite) {
|
||||
toastr.warning(`World ${actionName.toLowerCase()} cancelled. A world with the same name already exists:<br />${existingWorld}`, `World Info ${actionName}`, { escapeHtml: false });
|
||||
return false;
|
||||
}
|
||||
|
||||
toastr.info(`Overwriting Existing World Info:<br />${existingWorld}`, `World Info ${actionName}`, { escapeHtml: false });
|
||||
|
||||
// Manually delete, as we want to overwrite. The name might be slightly different so file name would not be the same.
|
||||
await deleteWorldInfo(existingWorld);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function getCharacterLore() {
|
||||
const character = characters[this_chid];
|
||||
const name = character?.name;
|
||||
@@ -3612,7 +3581,7 @@ export async function importWorldInfo(file) {
|
||||
|
||||
const worldName = file.name.substr(0, file.name.lastIndexOf("."));
|
||||
const sanitizedWorldName = await getSanitizedFilename(worldName);
|
||||
const allowed = await checkCanOverwriteWorldInfo(sanitizedWorldName, { interactive: true, actionName: 'Import' });
|
||||
const allowed = await checkOverwriteExistingData('World Info', world_names, sanitizedWorldName, { interactive: true, actionName: 'Import', deleteAction: (existingName) => deleteWorldInfo(existingName) });
|
||||
if (!allowed) {
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user