diff --git a/public/script.js b/public/script.js index 181e91c80..d86945523 100644 --- a/public/script.js +++ b/public/script.js @@ -497,6 +497,7 @@ export const event_types = { // TODO: Naming convention is inconsistent with other events CHARACTER_DELETED: 'characterDeleted', CHARACTER_DUPLICATED: 'character_duplicated', + CHARACTER_RENAMED: 'character_renamed', /** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */ SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received', STREAM_TOKEN_RECEIVED: 'stream_token_received', @@ -1031,12 +1032,22 @@ export function setAnimationDuration(ms = null) { document.documentElement.style.setProperty('--animation-duration', `${animation_duration}ms`); } +/** + * Sets the currently active character + * @param {object|number|string} [entityOrKey] - An entity with id property (character, group, tag), or directly an id or tag key. If not provided, the active character is reset to `null`. + */ export function setActiveCharacter(entityOrKey) { - active_character = getTagKeyForEntity(entityOrKey); + active_character = entityOrKey ? getTagKeyForEntity(entityOrKey) : null; + if (active_character) active_group = null; } +/** + * Sets the currently active group. + * @param {object|number|string} [entityOrKey] - An entity with id property (character, group, tag), or directly an id or tag key. If not provided, the active group is reset to `null`. + */ export function setActiveGroup(entityOrKey) { - active_group = getTagKeyForEntity(entityOrKey); + active_group = entityOrKey ? getTagKeyForEntity(entityOrKey) : null; + if (active_group) active_character = null; } /** @@ -6246,9 +6257,35 @@ export async function renameCharacter(name = null, { silent = false, renameChats const data = await response.json(); const newAvatar = data.avatar; - // Replace tags list + const oldName = getCharaFilename(null, { manualAvatarKey: oldAvatar }); + const newName = getCharaFilename(null, { manualAvatarKey: newAvatar }); + + // Replace other auxillery fields where was referenced by avatar key + // Tag List renameTagKey(oldAvatar, newAvatar); + // Addtional lore books + const charLore = world_info.charLore?.find(x => x.name == oldName); + if (charLore) { + charLore.name = newName; + saveSettingsDebounced(); + } + + // Char-bound Author's Notes + const charNote = extension_settings.note.chara?.find(x => x.name == oldName); + if (charNote) { + charNote.name = newName; + saveSettingsDebounced(); + } + + // Update active character, if the current one was the currently active one + if (active_character === oldAvatar) { + active_character = newAvatar; + saveSettingsDebounced(); + } + + await eventSource.emit(event_types.CHARACTER_RENAMED, oldAvatar, newAvatar); + // Reload characters list await getCharacters(); diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js index 236955596..2702976a8 100644 --- a/public/scripts/RossAscends-mods.js +++ b/public/scripts/RossAscends-mods.js @@ -280,17 +280,32 @@ async function RA_autoloadchat() { // active character is the name, we should look it up in the character list and get the id if (active_character !== null && active_character !== undefined) { const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character); - if (active_character_id !== null) { + if (active_character_id !== -1) { await selectCharacterById(String(active_character_id)); // Do a little tomfoolery to spoof the tag selector const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`); applyTagsOnCharacterSelect.call(selectedCharElement); + } else { + setActiveCharacter(null); + saveSettingsDebounced(); + console.warn(`Currently active character with ID ${active_character} not found. Resetting to no active character.`); } } if (active_group !== null && active_group !== undefined) { - await openGroupById(String(active_group)); + if (active_character) { + console.warn('Active character and active group are both set. Only active character will be loaded. Resetting active group.'); + setActiveGroup(null); + saveSettingsDebounced(); + } else { + const result = await openGroupById(String(active_group)); + if (!result) { + setActiveGroup(null); + saveSettingsDebounced(); + console.warn(`Currently active group with ID ${active_group} not found. Resetting to no active group.`); + } + } } // if the character list hadn't been loaded yet, try again. diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index 54f19e90e..0d0af4a3f 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -1664,12 +1664,12 @@ function updateFavButtonState(state) { export async function openGroupById(groupId) { if (isChatSaving) { toastr.info(t`Please wait until the chat is saved before switching characters.`, t`Your chat is still saving...`); - return; + return false; } if (!groups.find(x => x.id === groupId)) { console.log('Group not found', groupId); - return; + return false; } if (!is_send_press && !is_group_generating) { @@ -1686,8 +1686,11 @@ export async function openGroupById(groupId) { updateChatMetadata({}, true); chat.length = 0; await getGroupChat(groupId); + return true; } } + + return false; } function openCharacterDefinition(characterSelect) { diff --git a/public/scripts/utils.js b/public/scripts/utils.js index 90ef3fee4..2006eee23 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -1007,13 +1007,18 @@ export function getImageSizeFromDataURL(dataUrl) { }); } -export function getCharaFilename(chid) { +/** + * Gets the filename of the character avatar without extension + * @param {number?} [chid=null] - Character ID. If not provided, uses the current character ID + * @param {object} [options={}] - Options arguments + * @param {string?} [options.manualAvatarKey=null] - Manually take the following avatar key, instead of using the chid to determine the name + * @returns {string?} The filename of the character avatar without extension, or null if the character ID is invalid + */ +export function getCharaFilename(chid = null, { manualAvatarKey = null } = {}) { const context = getContext(); - const fileName = context.characters[chid ?? context.characterId]?.avatar; + const fileName = manualAvatarKey ?? context.characters[chid ?? context.characterId]?.avatar; - if (fileName) { - return fileName.replace(/\.[^/.]+$/, ''); - } + return fileName?.replace(/\.[^/.]+$/, '') ?? null; } /**