mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Ability to set default persona for chats
This commit is contained in:
@ -324,7 +324,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="range-block-range-and-counter">
|
<div class="range-block-range-and-counter">
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input type="range" id="rep_pen_slope_novel" name="volume" min="0" max="10" step="0.01">
|
<input type="range" id="rep_pen_slope_novel" name="volume" min="0.01" max="10" step="0.01">
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-counter">
|
<div class="range-block-counter">
|
||||||
<div contenteditable="true" data-for="rep_pen_slope_novel" id="rep_pen_slope_counter_novel">
|
<div contenteditable="true" data-for="rep_pen_slope_novel" id="rep_pen_slope_counter_novel">
|
||||||
@ -3122,10 +3122,19 @@
|
|||||||
<div imgfile="" class="avatar">
|
<div imgfile="" class="avatar">
|
||||||
<img src="" alt="User Avatar">
|
<img src="" alt="User Avatar">
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar-buttons">
|
<div class="avatar-buttons avatar-buttons-top">
|
||||||
<button class="menu_button bind_user_name" title="Bind user name to that avatar">
|
<button class="menu_button bind_user_name" title="Bind user name to that avatar">
|
||||||
<i class="fa-solid fa-user-edit"></i>
|
<i class="fa-solid fa-user-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="menu_button set_default_persona" title="Select this as default persona for the new chats.">
|
||||||
|
<i class="fa-solid fa-crown"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="avatar-buttons avatar-buttons-bottom">
|
||||||
|
<button class="menu_button set_user_info" title="Under construction">
|
||||||
|
<i class="fa-solid fa-circle-user"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class="menu_button delete_avatar" title="Delete persona">
|
<button class="menu_button delete_avatar" title="Delete persona">
|
||||||
<i class="fa-solid fa-trash-alt"></i>
|
<i class="fa-solid fa-trash-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
|
135
public/script.js
135
public/script.js
@ -3919,6 +3919,7 @@ function appendUserAvatar(name) {
|
|||||||
template.attr('title', personaName);
|
template.attr('title', personaName);
|
||||||
}
|
}
|
||||||
template.find('.avatar').attr('imgfile', name);
|
template.find('.avatar').attr('imgfile', name);
|
||||||
|
template.toggleClass('default_persona', name === power_user.default_persona)
|
||||||
template.find('img').attr('src', `User Avatars/${name}`);
|
template.find('img').attr('src', `User Avatars/${name}`);
|
||||||
$("#user_avatar_block").append(template);
|
$("#user_avatar_block").append(template);
|
||||||
highlightSelectedAvatar();
|
highlightSelectedAvatar();
|
||||||
@ -3939,9 +3940,9 @@ export function setUserName(value) {
|
|||||||
name1 = value;
|
name1 = value;
|
||||||
if (name1 === undefined || name1 == "")
|
if (name1 === undefined || name1 == "")
|
||||||
name1 = default_user_name;
|
name1 = default_user_name;
|
||||||
console.log(name1);
|
console.log(`User name changed to ${name1}`);
|
||||||
$("#your_name").val(name1);
|
$("#your_name").val(name1);
|
||||||
toastr.success(`Your messages will now be sent as ${name1}`, 'User Name updated');
|
toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
|
||||||
saveSettings("change_name");
|
saveSettings("change_name");
|
||||||
} else {
|
} else {
|
||||||
toastr.warning('You cannot change your name while sending a message', 'Warning');
|
toastr.warning('You cannot change your name while sending a message', 'Warning');
|
||||||
@ -3951,6 +3952,7 @@ export function setUserName(value) {
|
|||||||
export function autoSelectPersona(name) {
|
export function autoSelectPersona(name) {
|
||||||
for (const [key, value] of Object.entries(power_user.personas)) {
|
for (const [key, value] of Object.entries(power_user.personas)) {
|
||||||
if (value === name) {
|
if (value === name) {
|
||||||
|
console.log(`Auto-selecting persona ${key} for name ${name}`);
|
||||||
$(`.avatar[imgfile="${key}"]`).trigger('click');
|
$(`.avatar[imgfile="${key}"]`).trigger('click');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3967,11 +3969,22 @@ async function bindUserNameToPersona() {
|
|||||||
|
|
||||||
const existingPersona = power_user.personas[avatarId];
|
const existingPersona = power_user.personas[avatarId];
|
||||||
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>(If empty name is provided, this will unbind the name from this avatar)', 'input', existingPersona || '');
|
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>(If empty name is provided, this will unbind the name from this avatar)', 'input', existingPersona || '');
|
||||||
if (personaName) {
|
|
||||||
|
// If the user clicked cancel, don't do anything
|
||||||
|
if (personaName === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (personaName.length > 0) {
|
||||||
|
// If the user clicked ok and entered a name, bind the name to the persona
|
||||||
|
console.log(`Binding persona ${avatarId} to name ${personaName}`);
|
||||||
power_user.personas[avatarId] = personaName;
|
power_user.personas[avatarId] = personaName;
|
||||||
} else {
|
} else {
|
||||||
|
// If the user clicked ok, but didn't enter a name, delete the persona
|
||||||
|
console.log(`Unbinding persona ${avatarId}`);
|
||||||
delete power_user.personas[avatarId];
|
delete power_user.personas[avatarId];
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
await getUserAvatars();
|
await getUserAvatars();
|
||||||
}
|
}
|
||||||
@ -3997,6 +4010,57 @@ function setUserAvatar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setUserInfo() {
|
||||||
|
// TODO Replace with actual implementation
|
||||||
|
callPopup('This functionality is under development.<br>Please check back later.', 'text');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setDefaultPersona() {
|
||||||
|
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||||
|
|
||||||
|
if (!avatarId) {
|
||||||
|
console.warn('No avatar id found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentDefault = power_user.default_persona;
|
||||||
|
|
||||||
|
if (power_user.personas[avatarId] === undefined) {
|
||||||
|
console.warn(`No persona name found for avatar ${avatarId}`);
|
||||||
|
toastr.warning('You must bind a name to this persona before you can set it as the default.', 'Persona name not set');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const personaName = power_user.personas[avatarId];
|
||||||
|
|
||||||
|
if (avatarId === currentDefault) {
|
||||||
|
const confirm = await callPopup('Are you sure you want to remove the default persona?', 'confirm');
|
||||||
|
|
||||||
|
if (!confirm) {
|
||||||
|
console.debug('User cancelled removing default persona');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Removing default persona ${avatarId}`);
|
||||||
|
toastr.info('This persona will no longer be used by default when you open a new chat.', `Default persona removed`);
|
||||||
|
delete power_user.default_persona;
|
||||||
|
} else {
|
||||||
|
const confirm = await callPopup(`<h3>Are you sure you want to set "${personaName}" as the default persona?</h3>
|
||||||
|
This name and avatar will be used for all new chats, as well as existing chats where the user persona is not locked.`, 'confirm');
|
||||||
|
|
||||||
|
if (!confirm) {
|
||||||
|
console.debug('User cancelled setting default persona');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
power_user.default_persona = avatarId;
|
||||||
|
toastr.success('This persona will be used by default when you open a new chat.', `Default persona set to ${personaName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSettingsDebounced();
|
||||||
|
await getUserAvatars();
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteUserAvatar() {
|
async function deleteUserAvatar() {
|
||||||
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||||
|
|
||||||
@ -4006,6 +4070,7 @@ async function deleteUserAvatar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (avatarId == user_avatar) {
|
if (avatarId == user_avatar) {
|
||||||
|
console.warn(`User tried to delete their current avatar ${avatarId}`);
|
||||||
toastr.warning('You cannot delete the avatar you are currently using', 'Warning');
|
toastr.warning('You cannot delete the avatar you are currently using', 'Warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4013,6 +4078,7 @@ async function deleteUserAvatar() {
|
|||||||
const confirm = await callPopup('Are you sure you want to delete this avatar?', 'confirm');
|
const confirm = await callPopup('Are you sure you want to delete this avatar?', 'confirm');
|
||||||
|
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
|
console.debug('User cancelled deleting avatar');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4025,7 +4091,14 @@ async function deleteUserAvatar() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (request.ok) {
|
if (request.ok) {
|
||||||
|
console.log(`Deleted avatar ${avatarId}`);
|
||||||
delete power_user.personas[avatarId];
|
delete power_user.personas[avatarId];
|
||||||
|
|
||||||
|
if (avatarId === power_user.default_persona) {
|
||||||
|
toastr.warning('The default persona was deleted. You will need to set a new default persona.', 'Default persona deleted');
|
||||||
|
power_user.default_persona = null;
|
||||||
|
}
|
||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
await getUserAvatars();
|
await getUserAvatars();
|
||||||
}
|
}
|
||||||
@ -4033,6 +4106,7 @@ async function deleteUserAvatar() {
|
|||||||
|
|
||||||
function lockUserNameToChat() {
|
function lockUserNameToChat() {
|
||||||
if (chat_metadata['persona']) {
|
if (chat_metadata['persona']) {
|
||||||
|
console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`);
|
||||||
delete chat_metadata['persona'];
|
delete chat_metadata['persona'];
|
||||||
saveMetadata();
|
saveMetadata();
|
||||||
toastr.info('User persona is now unlocked for this chat. Click the "Lock" to bind again.', 'Persona unlocked');
|
toastr.info('User persona is now unlocked for this chat. Click the "Lock" to bind again.', 'Persona unlocked');
|
||||||
@ -4040,6 +4114,7 @@ function lockUserNameToChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(user_avatar in power_user.personas)) {
|
if (!(user_avatar in power_user.personas)) {
|
||||||
|
console.log(`Creating a new persona ${user_avatar}`);
|
||||||
toastr.info('Creating a new persona for currently selected user name and avatar...', 'Persona not set for this avatar');
|
toastr.info('Creating a new persona for currently selected user name and avatar...', 'Persona not set for this avatar');
|
||||||
power_user.personas[user_avatar] = name1;
|
power_user.personas[user_avatar] = name1;
|
||||||
}
|
}
|
||||||
@ -4047,24 +4122,50 @@ function lockUserNameToChat() {
|
|||||||
chat_metadata['persona'] = user_avatar;
|
chat_metadata['persona'] = user_avatar;
|
||||||
saveMetadata();
|
saveMetadata();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
console.log(`Locking persona for this chat ${user_avatar}`);
|
||||||
toastr.success(`User persona is locked to ${name1} in this chat`);
|
toastr.success(`User persona is locked to ${name1} in this chat`);
|
||||||
}
|
}
|
||||||
|
|
||||||
eventSource.on(event_types.CHAT_CHANGED, () => {
|
eventSource.on(event_types.CHAT_CHANGED, () => {
|
||||||
// If persona is locked, select it
|
// Define a persona for this chat
|
||||||
|
let chatPersona = '';
|
||||||
|
|
||||||
if (chat_metadata['persona']) {
|
if (chat_metadata['persona']) {
|
||||||
// Find the avatar file
|
// If persona is locked in chat metadata, select it
|
||||||
const personaAvatar = $(`.avatar[imgfile="${chat_metadata['persona']}"]`).trigger('click');
|
console.log(`Using locked persona ${chat_metadata['persona']}`);
|
||||||
|
chatPersona = chat_metadata['persona'];
|
||||||
// Avatar missing (persona deleted)
|
} else if (power_user.default_persona) {
|
||||||
if (personaAvatar.length == 0) {
|
// If default persona is set, select it
|
||||||
console.warn('Persona avatar not found, unlocking persona');
|
console.log(`Using default persona ${power_user.default_persona}`);
|
||||||
delete chat_metadata['persona'];
|
chatPersona = power_user.default_persona;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
personaAvatar.trigger('click');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No persona set: user current settings
|
||||||
|
if (!chatPersona) {
|
||||||
|
console.debug('No default or locked persona set for this chat');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the avatar file
|
||||||
|
const personaAvatar = $(`.avatar[imgfile="${chatPersona}"]`).trigger('click');
|
||||||
|
|
||||||
|
// Avatar missing (persona deleted)
|
||||||
|
if (chat_metadata['persona'] && personaAvatar.length == 0) {
|
||||||
|
console.warn('Persona avatar not found, unlocking persona');
|
||||||
|
delete chat_metadata['persona'];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default persona missing
|
||||||
|
if (power_user.default_persona && personaAvatar.length == 0) {
|
||||||
|
console.warn('Default persona avatar not found, clearing default persona');
|
||||||
|
power_user.default_persona = null;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Persona avatar found, select it
|
||||||
|
personaAvatar.trigger('click');
|
||||||
});
|
});
|
||||||
|
|
||||||
//***************SETTINGS****************//
|
//***************SETTINGS****************//
|
||||||
@ -6690,7 +6791,7 @@ $(document).ready(function () {
|
|||||||
if (this_chid !== undefined || selected_group) {
|
if (this_chid !== undefined || selected_group) {
|
||||||
// Previously system messages we're allowed to be edited
|
// Previously system messages we're allowed to be edited
|
||||||
/*const message = $(this).closest(".mes");
|
/*const message = $(this).closest(".mes");
|
||||||
|
|
||||||
if (message.data("isSystem")) {
|
if (message.data("isSystem")) {
|
||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
@ -6947,6 +7048,8 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
$(document).on('click', '.bind_user_name', bindUserNameToPersona);
|
$(document).on('click', '.bind_user_name', bindUserNameToPersona);
|
||||||
$(document).on('click', '.delete_avatar', deleteUserAvatar);
|
$(document).on('click', '.delete_avatar', deleteUserAvatar);
|
||||||
|
$(document).on('click', '.set_default_persona', setDefaultPersona);
|
||||||
|
$(document).on('click', '.set_user_info', setUserInfo);
|
||||||
$('#lock_user_name').on('click', lockUserNameToChat);
|
$('#lock_user_name').on('click', lockUserNameToChat);
|
||||||
|
|
||||||
//**************************CHARACTER IMPORT EXPORT*************************//
|
//**************************CHARACTER IMPORT EXPORT*************************//
|
||||||
|
@ -146,6 +146,7 @@ let power_user = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
personas: {},
|
personas: {},
|
||||||
|
default_persona: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
let themes = [];
|
let themes = [];
|
||||||
|
@ -262,6 +262,7 @@ function executeSlashCommands(text) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.debug('Slash command executing:', result);
|
||||||
result.command.callback(result.args, result.value);
|
result.command.callback(result.args, result.value);
|
||||||
|
|
||||||
if (result.command.interruptsGeneration) {
|
if (result.command.interruptsGeneration) {
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
--orangered: rgb(255, 90, 0);
|
--orangered: rgb(255, 90, 0);
|
||||||
--greyCAIbg: rgb(36, 36, 37);
|
--greyCAIbg: rgb(36, 36, 37);
|
||||||
--ivory: rgb(220, 220, 210);
|
--ivory: rgb(220, 220, 210);
|
||||||
|
--golden: rgba(212, 175, 55, 1);
|
||||||
|
|
||||||
|
|
||||||
/*Default Theme, will be changed by ToolCool Color Picker*/
|
/*Default Theme, will be changed by ToolCool Color Picker*/
|
||||||
@ -1239,7 +1240,8 @@ select option:not(:checked) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#form_character_search_form .menu_button,
|
#form_character_search_form .menu_button,
|
||||||
#GroupFavDelOkBack .menu_button {
|
#GroupFavDelOkBack .menu_button,
|
||||||
|
.avatar-container .menu_button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
@ -1529,12 +1531,26 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-buttons-bottom {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-buttons-top {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ross should be able to handle this later */
|
||||||
|
/*.big-avatars .avatar-buttons{
|
||||||
|
justify-content: center;
|
||||||
|
width: fit-content;
|
||||||
|
}*/
|
||||||
|
|
||||||
.avatar-buttons {
|
.avatar-buttons {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
@ -2077,6 +2093,11 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
|||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Override toastr default styles */
|
||||||
|
body #toast-container>div {
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
#dialogue_del_mes {
|
#dialogue_del_mes {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -2152,6 +2173,15 @@ input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button
|
|||||||
outline: 2px solid transparent;
|
outline: 2px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#user_avatar_block .default_persona .avatar {
|
||||||
|
border: 2px solid var(--golden);
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user_avatar_block .default_persona .set_default_persona {
|
||||||
|
color: var(--golden);
|
||||||
|
}
|
||||||
|
|
||||||
#user_avatar_block .avatar img {
|
#user_avatar_block .avatar img {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
@ -4621,4 +4651,4 @@ body.waifuMode #avatar_zoom_popup {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user