mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into instruct-rework
This commit is contained in:
@ -4161,7 +4161,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="tags_div">
|
<div id="tags_div">
|
||||||
<div class="tag_controls">
|
<div class="tag_controls">
|
||||||
<input id="tagInput" class="text_pole tag_input wide100p margin0" data-i18n="[placeholder]Search / Create Tags" placeholder="Search / Create tags" maxlength="50" />
|
<input id="tagInput" class="text_pole textarea_compact tag_input wide100p margin0" data-i18n="[placeholder]Search / Create Tags" placeholder="Search / Create tags" maxlength="50" />
|
||||||
<div class="tags_view menu_button fa-solid fa-tags" title="View all tags" data-i18n="[title]View all tags"></div>
|
<div class="tags_view menu_button fa-solid fa-tags" title="View all tags" data-i18n="[title]View all tags"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tagList" class="tags"></div>
|
<div id="tagList" class="tags"></div>
|
||||||
@ -4181,7 +4181,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="descriptionWrapper" class="flex-container flexFlowColumn flex1">
|
<div id="descriptionWrapper" class="flex-container flexFlowColumn flex1">
|
||||||
<hr>
|
<hr>
|
||||||
<div id="description_div" class="marginBot5 flex-container alignitemscenter">
|
<div id="description_div" class="flex-container alignitemscenter">
|
||||||
<span data-i18n="Character Description">Description</span>
|
<span data-i18n="Character Description">Description</span>
|
||||||
<i class="editor_maximize fa-solid fa-maximize right_menu_button" data-for="description_textarea" title="Expand the editor"></i>
|
<i class="editor_maximize fa-solid fa-maximize right_menu_button" data-for="description_textarea" title="Expand the editor"></i>
|
||||||
<a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-description" class="notes-link" target="_blank">
|
<a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-description" class="notes-link" target="_blank">
|
||||||
@ -4194,7 +4194,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="firstMessageWrapper" class="flex-container flexFlowColumn flex1">
|
<div id="firstMessageWrapper" class="flex-container flexFlowColumn flex1">
|
||||||
<div id="first_message_div" class="marginBot5 title_restorable">
|
<div id="first_message_div" class="title_restorable">
|
||||||
<div class="flex-container alignitemscenter flex1">
|
<div class="flex-container alignitemscenter flex1">
|
||||||
<span data-i18n="First message">First message</span>
|
<span data-i18n="First message">First message</span>
|
||||||
<i class="editor_maximize fa-solid fa-maximize right_menu_button" data-for="firstmessage_textarea" title="Expand the editor"></i>
|
<i class="editor_maximize fa-solid fa-maximize right_menu_button" data-for="firstmessage_textarea" title="Expand the editor"></i>
|
||||||
@ -4244,7 +4244,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="group_tags_div" class="wide100p">
|
<div id="group_tags_div" class="wide100p">
|
||||||
<div class="tag_controls">
|
<div class="tag_controls">
|
||||||
<input id="groupTagInput" class="text_pole tag_input flex1 margin0" data-i18n="[placeholder]Search / Create Tags" placeholder="Search / Create tags" maxlength="50" />
|
<input id="groupTagInput" class="text_pole textarea_compact tag_input flex1 margin0" data-i18n="[placeholder]Search / Create Tags" placeholder="Search / Create tags" maxlength="50" />
|
||||||
<div class="tags_view menu_button fa-solid fa-tags margin0" title="View all tags" data-i18n="[title]View all tags"></div>
|
<div class="tags_view menu_button fa-solid fa-tags margin0" title="View all tags" data-i18n="[title]View all tags"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="groupTagList" class="tags paddingTopBot5"></div>
|
<div id="groupTagList" class="tags paddingTopBot5"></div>
|
||||||
|
@ -172,6 +172,7 @@ import {
|
|||||||
importTags,
|
importTags,
|
||||||
tag_filter_types,
|
tag_filter_types,
|
||||||
compareTagsForSort,
|
compareTagsForSort,
|
||||||
|
initTags,
|
||||||
} from './scripts/tags.js';
|
} from './scripts/tags.js';
|
||||||
import {
|
import {
|
||||||
SECRET_KEYS,
|
SECRET_KEYS,
|
||||||
@ -412,6 +413,7 @@ export const event_types = {
|
|||||||
CHARACTER_FIRST_MESSAGE_SELECTED: 'character_first_message_selected',
|
CHARACTER_FIRST_MESSAGE_SELECTED: 'character_first_message_selected',
|
||||||
// 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',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const eventSource = new EventEmitter();
|
export const eventSource = new EventEmitter();
|
||||||
@ -864,6 +866,7 @@ async function firstLoadInit() {
|
|||||||
getSystemMessages();
|
getSystemMessages();
|
||||||
sendSystemMessage(system_message_types.WELCOME);
|
sendSystemMessage(system_message_types.WELCOME);
|
||||||
initLocales();
|
initLocales();
|
||||||
|
initTags();
|
||||||
await getUserAvatars(true, user_avatar);
|
await getUserAvatars(true, user_avatar);
|
||||||
await getCharacters();
|
await getCharacters();
|
||||||
await getBackgrounds();
|
await getBackgrounds();
|
||||||
@ -1237,7 +1240,7 @@ function getCharacterBlock(item, id) {
|
|||||||
const template = $('#character_template .character_select').clone();
|
const template = $('#character_template .character_select').clone();
|
||||||
template.attr({ 'chid': id, 'id': `CharID${id}` });
|
template.attr({ 'chid': id, 'id': `CharID${id}` });
|
||||||
template.find('img').attr('src', this_avatar).attr('alt', item.name);
|
template.find('img').attr('src', this_avatar).attr('alt', item.name);
|
||||||
template.find('.avatar').attr('title', `[Character] ${item.name}`);
|
template.find('.avatar').attr('title', `[Character] ${item.name}\nFile: ${item.avatar}`);
|
||||||
template.find('.ch_name').text(item.name).attr('title', `[Character] ${item.name}`);
|
template.find('.ch_name').text(item.name).attr('title', `[Character] ${item.name}`);
|
||||||
if (power_user.show_card_avatar_urls) {
|
if (power_user.show_card_avatar_urls) {
|
||||||
template.find('.ch_avatar_url').text(item.avatar);
|
template.find('.ch_avatar_url').text(item.avatar);
|
||||||
@ -1855,6 +1858,7 @@ function insertSVGIcon(mes, extra) {
|
|||||||
|
|
||||||
function getMessageFromTemplate({
|
function getMessageFromTemplate({
|
||||||
mesId,
|
mesId,
|
||||||
|
swipeId,
|
||||||
characterName,
|
characterName,
|
||||||
isUser,
|
isUser,
|
||||||
avatarImg,
|
avatarImg,
|
||||||
@ -1872,6 +1876,7 @@ function getMessageFromTemplate({
|
|||||||
const mes = messageTemplate.clone();
|
const mes = messageTemplate.clone();
|
||||||
mes.attr({
|
mes.attr({
|
||||||
'mesid': mesId,
|
'mesid': mesId,
|
||||||
|
'swipeid': swipeId,
|
||||||
'ch_name': characterName,
|
'ch_name': characterName,
|
||||||
'is_user': isUser,
|
'is_user': isUser,
|
||||||
'is_system': !!isSystem,
|
'is_system': !!isSystem,
|
||||||
@ -2018,6 +2023,7 @@ function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true
|
|||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
mesId: forceId ?? chat.length - 1,
|
mesId: forceId ?? chat.length - 1,
|
||||||
|
swipeId: mes.swipe_id ?? 0,
|
||||||
characterName: mes.name,
|
characterName: mes.name,
|
||||||
isUser: mes.is_user,
|
isUser: mes.is_user,
|
||||||
avatarImg: avatarImg,
|
avatarImg: avatarImg,
|
||||||
@ -4320,6 +4326,8 @@ async function DupeChar() {
|
|||||||
});
|
});
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
toastr.success('Character Duplicated');
|
toastr.success('Character Duplicated');
|
||||||
|
const data = await response.json();
|
||||||
|
await eventSource.emit(event_types.CHARACTER_DUPLICATED, { oldAvatar: body.avatar_url, newAvatar: data.path });
|
||||||
getCharacters();
|
getCharacters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,16 +48,24 @@ class CharacterContextMenu {
|
|||||||
* Duplicate one or more characters
|
* Duplicate one or more characters
|
||||||
*
|
*
|
||||||
* @param characterId
|
* @param characterId
|
||||||
* @returns {Promise<Response>}
|
* @returns {Promise<any>}
|
||||||
*/
|
*/
|
||||||
static duplicate = async (characterId) => {
|
static duplicate = async (characterId) => {
|
||||||
const character = CharacterContextMenu.#getCharacter(characterId);
|
const character = CharacterContextMenu.#getCharacter(characterId);
|
||||||
|
const body = { avatar_url: character.avatar };
|
||||||
|
|
||||||
return fetch('/api/characters/duplicate', {
|
const result = await fetch('/api/characters/duplicate', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getRequestHeaders(),
|
headers: getRequestHeaders(),
|
||||||
body: JSON.stringify({ avatar_url: character.avatar }),
|
body: JSON.stringify(body),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
throw new Error('Character not duplicated');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
await eventSource.emit(event_types.CHARACTER_DUPLICATED, { oldAvatar: body.avatar_url, newAvatar: data.path });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,8 @@ import {
|
|||||||
entitiesFilter,
|
entitiesFilter,
|
||||||
printCharacters,
|
printCharacters,
|
||||||
buildAvatarList,
|
buildAvatarList,
|
||||||
|
eventSource,
|
||||||
|
event_types,
|
||||||
} from '../script.js';
|
} from '../script.js';
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
import { FILTER_TYPES, FILTER_STATES, isFilterState, FilterHelper } from './filters.js';
|
import { FILTER_TYPES, FILTER_STATES, isFilterState, FilterHelper } from './filters.js';
|
||||||
@ -1151,7 +1153,17 @@ function onClearAllFiltersClick() {
|
|||||||
$('#character_search_bar').val('').trigger('input');
|
$('#character_search_bar').val('').trigger('input');
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery(() => {
|
/**
|
||||||
|
* Copy tags from one character to another.
|
||||||
|
* @param {{oldAvatar: string, newAvatar: string}} data Event data
|
||||||
|
*/
|
||||||
|
function copyTags(data) {
|
||||||
|
const prevTagMap = tag_map[data.oldAvatar] || [];
|
||||||
|
const newTagMap = tag_map[data.newAvatar] || [];
|
||||||
|
tag_map[data.newAvatar] = Array.from(new Set([...prevTagMap, ...newTagMap]));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initTags() {
|
||||||
createTagInput('#tagInput', '#tagList');
|
createTagInput('#tagInput', '#tagList');
|
||||||
createTagInput('#groupTagInput', '#groupTagList');
|
createTagInput('#groupTagInput', '#groupTagList');
|
||||||
|
|
||||||
@ -1168,5 +1180,5 @@ jQuery(() => {
|
|||||||
$(document).on('click', '.tag_view_create', onTagCreateClick);
|
$(document).on('click', '.tag_view_create', onTagCreateClick);
|
||||||
$(document).on('click', '.tag_view_backup', onTagsBackupClick);
|
$(document).on('click', '.tag_view_backup', onTagsBackupClick);
|
||||||
$(document).on('click', '.tag_view_restore', onBackupRestoreClick);
|
$(document).on('click', '.tag_view_restore', onBackupRestoreClick);
|
||||||
});
|
eventSource.on(event_types.CHARACTER_DUPLICATED, copyTags);
|
||||||
|
}
|
||||||
|
@ -1416,7 +1416,7 @@ input[type="file"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.extension_token_counter {
|
.extension_token_counter {
|
||||||
font-size: calc(var(--mainFontSize) * 0.9);
|
font-size: calc(var(--mainFontSize) * 0.875);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
@ -1008,7 +1008,7 @@ router.post('/duplicate', jsonParser, async function (request, response) {
|
|||||||
|
|
||||||
fs.copyFileSync(filename, newFilename);
|
fs.copyFileSync(filename, newFilename);
|
||||||
console.log(`${filename} was copied to ${newFilename}`);
|
console.log(`${filename} was copied to ${newFilename}`);
|
||||||
response.sendStatus(200);
|
response.send({ path: path.parse(newFilename).base });
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
Reference in New Issue
Block a user