Merge pull request #3497 from SillyTavern/fix-char-rename-aux-connections

Fix renaming characters losing connections of several aux fields
This commit is contained in:
Cohee
2025-02-17 21:14:41 +02:00
committed by GitHub
4 changed files with 72 additions and 12 deletions

View File

@ -497,6 +497,7 @@ export const event_types = {
// TODO: Naming convention is inconsistent with other events // TODO: Naming convention is inconsistent with other events
CHARACTER_DELETED: 'characterDeleted', CHARACTER_DELETED: 'characterDeleted',
CHARACTER_DUPLICATED: 'character_duplicated', CHARACTER_DUPLICATED: 'character_duplicated',
CHARACTER_RENAMED: 'character_renamed',
/** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */ /** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */
SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received', SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received',
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`); 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) { 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) { 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 data = await response.json();
const newAvatar = data.avatar; 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); 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 // Reload characters list
await getCharacters(); await getCharacters();

View File

@ -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 // 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) { if (active_character !== null && active_character !== undefined) {
const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character); 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)); await selectCharacterById(String(active_character_id));
// Do a little tomfoolery to spoof the tag selector // Do a little tomfoolery to spoof the tag selector
const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`); const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`);
applyTagsOnCharacterSelect.call(selectedCharElement); 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) { 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. // if the character list hadn't been loaded yet, try again.

View File

@ -1664,12 +1664,12 @@ function updateFavButtonState(state) {
export async function openGroupById(groupId) { export async function openGroupById(groupId) {
if (isChatSaving) { if (isChatSaving) {
toastr.info(t`Please wait until the chat is saved before switching characters.`, t`Your chat is still saving...`); 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)) { if (!groups.find(x => x.id === groupId)) {
console.log('Group not found', groupId); console.log('Group not found', groupId);
return; return false;
} }
if (!is_send_press && !is_group_generating) { if (!is_send_press && !is_group_generating) {
@ -1686,8 +1686,11 @@ export async function openGroupById(groupId) {
updateChatMetadata({}, true); updateChatMetadata({}, true);
chat.length = 0; chat.length = 0;
await getGroupChat(groupId); await getGroupChat(groupId);
return true;
} }
} }
return false;
} }
function openCharacterDefinition(characterSelect) { function openCharacterDefinition(characterSelect) {

View File

@ -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 context = getContext();
const fileName = context.characters[chid ?? context.characterId]?.avatar; const fileName = manualAvatarKey ?? context.characters[chid ?? context.characterId]?.avatar;
if (fileName) { return fileName?.replace(/\.[^/.]+$/, '') ?? null;
return fileName.replace(/\.[^/.]+$/, '');
}
} }
/** /**