Merge pull request #3497 from SillyTavern/fix-char-rename-aux-connections Fix renaming characters losing connections of several aux fields

fa4a75215be893798e838b2a3b27d2fbf729486e

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
4 files changed, +72 -12Showing whitespace changes
public/script.js+40 -3
@@ -497,6 +497,7 @@ export const event_types = {
497 // TODO: Naming convention is inconsistent with other events497 // TODO: Naming convention is inconsistent with other events
498 CHARACTER_DELETED: 'characterDeleted',498 CHARACTER_DELETED: 'characterDeleted',
499 CHARACTER_DUPLICATED: 'character_duplicated',499 CHARACTER_DUPLICATED: 'character_duplicated',
500 CHARACTER_RENAMED: 'character_renamed',
500 /** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */501 /** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */
501 SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received',502 SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received',
502 STREAM_TOKEN_RECEIVED: 'stream_token_received',503 STREAM_TOKEN_RECEIVED: 'stream_token_received',
@@ -1031,12 +1032,22 @@ export function setAnimationDuration(ms = null) {
1031 document.documentElement.style.setProperty('--animation-duration', `${animation_duration}ms`);1032 document.documentElement.style.setProperty('--animation-duration', `${animation_duration}ms`);
1032}1033}
10331034
1035/**
1036 * Sets the currently active character
1037 * @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`.
1038 */
1034export function setActiveCharacter(entityOrKey) {1039export function setActiveCharacter(entityOrKey) {
1035 active_character = getTagKeyForEntity(entityOrKey);1040 active_character = entityOrKey ? getTagKeyForEntity(entityOrKey) : null;
1041 if (active_character) active_group = null;
1036}1042}
10371043
1044/**
1045 * Sets the currently active group.
1046 * @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`.
1047 */
1038export function setActiveGroup(entityOrKey) {1048export function setActiveGroup(entityOrKey) {
1039 active_group = getTagKeyForEntity(entityOrKey);1049 active_group = entityOrKey ? getTagKeyForEntity(entityOrKey) : null;
1050 if (active_group) active_character = null;
1040}1051}
10411052
1042/**1053/**
@@ -6246,9 +6257,35 @@ export async function renameCharacter(name = null, { silent = false, renameChats
6246 const data = await response.json();6257 const data = await response.json();
6247 const newAvatar = data.avatar;6258 const newAvatar = data.avatar;
62486259
6249 // Replace tags list6260 const oldName = getCharaFilename(null, { manualAvatarKey: oldAvatar });
6261 const newName = getCharaFilename(null, { manualAvatarKey: newAvatar });
6262
6263 // Replace other auxillery fields where was referenced by avatar key
6264 // Tag List
6250 renameTagKey(oldAvatar, newAvatar);6265 renameTagKey(oldAvatar, newAvatar);
62516266
6267 // Addtional lore books
6268 const charLore = world_info.charLore?.find(x => x.name == oldName);
6269 if (charLore) {
6270 charLore.name = newName;
6271 saveSettingsDebounced();
6272 }
6273
6274 // Char-bound Author's Notes
6275 const charNote = extension_settings.note.chara?.find(x => x.name == oldName);
6276 if (charNote) {
6277 charNote.name = newName;
6278 saveSettingsDebounced();
6279 }
6280
6281 // Update active character, if the current one was the currently active one
6282 if (active_character === oldAvatar) {
6283 active_character = newAvatar;
6284 saveSettingsDebounced();
6285 }
6286
6287 await eventSource.emit(event_types.CHARACTER_RENAMED, oldAvatar, newAvatar);
6288
6252 // Reload characters list6289 // Reload characters list
6253 await getCharacters();6290 await getCharacters();
62546291
public/scripts/RossAscends-mods.js+17 -2
@@ -280,17 +280,32 @@ async function RA_autoloadchat() {
280 // active character is the name, we should look it up in the character list and get the id280 // active character is the name, we should look it up in the character list and get the id
281 if (active_character !== null && active_character !== undefined) {281 if (active_character !== null && active_character !== undefined) {
282 const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character);282 const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character);
283 if (active_character_id !== null) {283 if (active_character_id !== -1) {
284 await selectCharacterById(String(active_character_id));284 await selectCharacterById(String(active_character_id));
285285
286 // Do a little tomfoolery to spoof the tag selector286 // Do a little tomfoolery to spoof the tag selector
287 const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`);287 const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`);
288 applyTagsOnCharacterSelect.call(selectedCharElement);288 applyTagsOnCharacterSelect.call(selectedCharElement);
289 } else {
290 setActiveCharacter(null);
291 saveSettingsDebounced();
292 console.warn(`Currently active character with ID ${active_character} not found. Resetting to no active character.`);
289 }293 }
290 }294 }
291295
292 if (active_group !== null && active_group !== undefined) {296 if (active_group !== null && active_group !== undefined) {
293 await openGroupById(String(active_group));297 if (active_character) {
298 console.warn('Active character and active group are both set. Only active character will be loaded. Resetting active group.');
299 setActiveGroup(null);
300 saveSettingsDebounced();
301 } else {
302 const result = await openGroupById(String(active_group));
303 if (!result) {
304 setActiveGroup(null);
305 saveSettingsDebounced();
306 console.warn(`Currently active group with ID ${active_group} not found. Resetting to no active group.`);
307 }
308 }
294 }309 }
295310
296 // if the character list hadn't been loaded yet, try again.311 // if the character list hadn't been loaded yet, try again.
public/scripts/group-chats.js+5 -2
@@ -1664,12 +1664,12 @@ function updateFavButtonState(state) {
1664export async function openGroupById(groupId) {1664export async function openGroupById(groupId) {
1665 if (isChatSaving) {1665 if (isChatSaving) {
1666 toastr.info(t`Please wait until the chat is saved before switching characters.`, t`Your chat is still saving...`);1666 toastr.info(t`Please wait until the chat is saved before switching characters.`, t`Your chat is still saving...`);
1667 return;1667 return false;
1668 }1668 }
16691669
1670 if (!groups.find(x => x.id === groupId)) {1670 if (!groups.find(x => x.id === groupId)) {
1671 console.log('Group not found', groupId);1671 console.log('Group not found', groupId);
1672 return;1672 return false;
1673 }1673 }
16741674
1675 if (!is_send_press && !is_group_generating) {1675 if (!is_send_press && !is_group_generating) {
@@ -1686,8 +1686,11 @@ export async function openGroupById(groupId) {
1686 updateChatMetadata({}, true);1686 updateChatMetadata({}, true);
1687 chat.length = 0;1687 chat.length = 0;
1688 await getGroupChat(groupId);1688 await getGroupChat(groupId);
1689 return true;
1689 }1690 }
1690 }1691 }
1692
1693 return false;
1691}1694}
16921695
1693function openCharacterDefinition(characterSelect) {1696function openCharacterDefinition(characterSelect) {
public/scripts/utils.js+10 -5
@@ -1007,13 +1007,18 @@ export function getImageSizeFromDataURL(dataUrl) {
1007 });1007 });
1008}1008}
10091009
1010export function getCharaFilename(chid) {1010/**
1011 * Gets the filename of the character avatar without extension
1012 * @param {number?} [chid=null] - Character ID. If not provided, uses the current character ID
1013 * @param {object} [options={}] - Options arguments
1014 * @param {string?} [options.manualAvatarKey=null] - Manually take the following avatar key, instead of using the chid to determine the name
1015 * @returns {string?} The filename of the character avatar without extension, or null if the character ID is invalid
1016 */
1017export function getCharaFilename(chid = null, { manualAvatarKey = null } = {}) {
1011 const context = getContext();1018 const context = getContext();
1012 const fileName = context.characters[chid ?? context.characterId]?.avatar;1019 const fileName = manualAvatarKey ?? context.characters[chid ?? context.characterId]?.avatar;
10131020
1014 if (fileName) {1021 return fileName?.replace(/\.[^/.]+$/, '') ?? null;
1015 return fileName.replace(/\.[^/.]+$/, '');
1016 }
1017}1022}
10181023
1019/**1024/**