mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add persona connection states to persona list
- Show persona connection/lock states in persona list (chat & char lock) - Refactor persona images url to 'data-avatar-id' attribute - Try make persona blocks' height consistent - Fix persona list not correctly updating selected persona on navigating pages - Fix group/char difference not correctly working - Create common style template for hover-able images buttons/tags where the label only appears on hover
This commit is contained in:
@@ -96,11 +96,6 @@ body.charListGrid #rm_print_characters_block .group_select .group_name_block,
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#user_avatar_block.gridView .avatar-container .avatar-buttons {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.charListGrid #rm_print_characters_block .bogus_folder_select .character_select_container,
|
body.charListGrid #rm_print_characters_block .bogus_folder_select .character_select_container,
|
||||||
body.charListGrid #rm_print_characters_block .character_select .character_select_container,
|
body.charListGrid #rm_print_characters_block .character_select .character_select_container,
|
||||||
body.charListGrid #rm_print_characters_block .group_select .group_select_container,
|
body.charListGrid #rm_print_characters_block .group_select .group_select_container,
|
||||||
|
@@ -5470,27 +5470,20 @@
|
|||||||
<div class="flex-container wide100pLess70px character_select_container">
|
<div class="flex-container wide100pLess70px character_select_container">
|
||||||
<div class="wide100p character_name_block">
|
<div class="wide100p character_name_block">
|
||||||
<span class="ch_name flex1"></span>
|
<span class="ch_name flex1"></span>
|
||||||
<div class="avatar-buttons">
|
|
||||||
<!-- <button class="menu_button bind_user_name" title="Bind user name to that avatar" data-i18n="[title]Bind user name to that avatar">
|
|
||||||
<i class="fa-fw fa-solid fa-user-edit fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
<button class="menu_button set_persona_image" title="Change persona image" data-i18n="[title]Change persona image">
|
|
||||||
<i class="fa-fw fa-solid fa-image fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="menu_button set_default_persona" title="Select this as default persona for the new chats." data-i18n="[title]Select this as default persona for the new chats.">
|
|
||||||
<i class="fa-fw fa-solid fa-crown fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="menu_button duplicate_persona" title="Duplicate persona" data-i18n="[title]Duplicate persona">
|
|
||||||
<i class="fa-fw fa-solid fa-clone fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
<button class="menu_button delete_avatar" title="Delete persona" data-i18n="[title]Delete persona">
|
|
||||||
<i class="fa-fw fa-solid fa-trash-alt fa-sm"></i>
|
|
||||||
</button> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="ch_description"></div>
|
<div class="ch_description"></div>
|
||||||
|
<div class="avatar_container_states buttons_block">
|
||||||
|
<div class="locked_to_chat_label avatar_state has_hover_label menu_button menu_button_icon disabled" title="Persona is locked to the current chat" data-i18n="[title]Persona is locked to the current chat">
|
||||||
|
<i class="icon fa-solid fa-lock fa-fw"></i>
|
||||||
|
<i class="label_icon icon fa-solid fa-comments fa-fw"></i>
|
||||||
|
<div class="label" data-i18n="Chat">Chat</div>
|
||||||
|
</div>
|
||||||
|
<div class="locked_to_character_label avatar_state has_hover_label menu_button menu_button_icon disabled " title="Persona is locked to the current character" data-i18n="[title]Persona is locked to the current character">
|
||||||
|
<i class="icon fa-solid fa-lock fa-fw"></i>
|
||||||
|
<i class="label_icon icon fa-solid fa-user fa-fw"></i>
|
||||||
|
<div class="label" data-i18n="Character">Character</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -10,7 +10,6 @@ import {
|
|||||||
getRequestHeaders,
|
getRequestHeaders,
|
||||||
getThumbnailUrl,
|
getThumbnailUrl,
|
||||||
groupToEntity,
|
groupToEntity,
|
||||||
menu_type,
|
|
||||||
name1,
|
name1,
|
||||||
name2,
|
name2,
|
||||||
reloadCurrentChat,
|
reloadCurrentChat,
|
||||||
@@ -40,6 +39,15 @@ import { saveMetadataDebounced } from './extensions.js';
|
|||||||
|
|
||||||
/** @typedef {'chat' | 'character' | 'default'} PersonaLockType Type of the persona lock */
|
/** @typedef {'chat' | 'character' | 'default'} PersonaLockType Type of the persona lock */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} PersonaState
|
||||||
|
* @property {string} avatarId - The avatar id of the persona
|
||||||
|
* @property {boolean} default - Whether this persona is the default one for all new chats
|
||||||
|
* @property {object} locked - An object containing the lock states
|
||||||
|
* @property {boolean} locked.chat - Whether the persona is locked to the currently open chat
|
||||||
|
* @property {boolean} locked.character - Whether the persona is locked to the currently open character or group
|
||||||
|
*/
|
||||||
|
|
||||||
const USER_AVATAR_PATH = 'User Avatars/';
|
const USER_AVATAR_PATH = 'User Avatars/';
|
||||||
|
|
||||||
let savePersonasPage = 0;
|
let savePersonasPage = 0;
|
||||||
@@ -66,7 +74,7 @@ export function getUserAvatar(avatarImg) {
|
|||||||
export function initUserAvatar(avatar) {
|
export function initUserAvatar(avatar) {
|
||||||
user_avatar = avatar;
|
user_avatar = avatar;
|
||||||
reloadUserAvatar();
|
reloadUserAvatar();
|
||||||
highlightSelectedAvatar();
|
updatePersonaUIStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,19 +82,14 @@ export function initUserAvatar(avatar) {
|
|||||||
* @param {string} imgfile Link to an image file
|
* @param {string} imgfile Link to an image file
|
||||||
*/
|
*/
|
||||||
export function setUserAvatar(imgfile, { toastPersonaNameChange = true } = {}) {
|
export function setUserAvatar(imgfile, { toastPersonaNameChange = true } = {}) {
|
||||||
user_avatar = imgfile && typeof imgfile === 'string' ? imgfile : $(this).attr('imgfile');
|
user_avatar = imgfile && typeof imgfile === 'string' ? imgfile : $(this).attr('data-avatar-id');
|
||||||
reloadUserAvatar();
|
reloadUserAvatar();
|
||||||
highlightSelectedAvatar();
|
updatePersonaUIStates();
|
||||||
selectCurrentPersona({ toastPersonaNameChange: toastPersonaNameChange });
|
selectCurrentPersona({ toastPersonaNameChange: toastPersonaNameChange });
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
$('.zoomed_avatar[forchar]').remove();
|
$('.zoomed_avatar[forchar]').remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlightSelectedAvatar() {
|
|
||||||
$('#user_avatar_block .avatar-container').removeClass('selected');
|
|
||||||
$(`#user_avatar_block .avatar-container[imgfile="${user_avatar}"]`).addClass('selected');
|
|
||||||
}
|
|
||||||
|
|
||||||
function reloadUserAvatar(force = false) {
|
function reloadUserAvatar(force = false) {
|
||||||
$('.mes').each(function () {
|
$('.mes').each(function () {
|
||||||
const avatarImg = $(this).find('.avatar img');
|
const avatarImg = $(this).find('.avatar img');
|
||||||
@@ -146,24 +149,32 @@ function verifyPersonaSearchSortRule() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a rendered avatar block.
|
* Gets a rendered avatar block.
|
||||||
* @param {string} name Avatar file name
|
* @param {string} avatarId Avatar file name
|
||||||
* @returns {JQuery<HTMLElement>} Avatar block
|
* @returns {JQuery<HTMLElement>} Avatar block
|
||||||
*/
|
*/
|
||||||
function getUserAvatarBlock(name) {
|
function getUserAvatarBlock(avatarId) {
|
||||||
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
const template = $('#user_avatar_template .avatar-container').clone();
|
const template = $('#user_avatar_template .avatar-container').clone();
|
||||||
const personaName = power_user.personas[name];
|
const personaName = power_user.personas[avatarId];
|
||||||
const personaDescription = power_user.persona_descriptions[name]?.description;
|
const personaDescription = power_user.persona_descriptions[avatarId]?.description;
|
||||||
|
|
||||||
template.find('.ch_name').text(personaName || '[Unnamed Persona]');
|
template.find('.ch_name').text(personaName || '[Unnamed Persona]');
|
||||||
template.find('.ch_description').text(personaDescription || $('#user_avatar_block').attr('no_desc_text')).toggleClass('text_muted', !personaDescription);
|
template.find('.ch_description').text(personaDescription || $('#user_avatar_block').attr('no_desc_text')).toggleClass('text_muted', !personaDescription);
|
||||||
template.attr('imgfile', name);
|
template.attr('data-avatar-id', avatarId);
|
||||||
template.find('.avatar').attr('imgfile', name).attr('title', name);
|
template.find('.avatar').attr('data-avatar-id', avatarId).attr('title', avatarId);
|
||||||
template.toggleClass('default_persona', name === power_user.default_persona);
|
template.toggleClass('default_persona', avatarId === power_user.default_persona);
|
||||||
let avatarUrl = getUserAvatar(name);
|
let avatarUrl = getUserAvatar(avatarId);
|
||||||
if (isFirefox) {
|
if (isFirefox) {
|
||||||
avatarUrl += '?t=' + Date.now();
|
avatarUrl += '?t=' + Date.now();
|
||||||
}
|
}
|
||||||
template.find('img').attr('src', avatarUrl);
|
template.find('img').attr('src', avatarUrl);
|
||||||
|
|
||||||
|
// Make sure description block has at least three rows. Otherwise height looks inconsistent. I don't have a better idea for this.
|
||||||
|
const currentText = template.find('.ch_description').text();
|
||||||
|
if (currentText.split('\n').length < 3) {
|
||||||
|
template.find('.ch_description').text(currentText + '\n\xa0\n\xa0');
|
||||||
|
}
|
||||||
|
|
||||||
$('#user_avatar_block').append(template);
|
$('#user_avatar_block').append(template);
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
@@ -218,7 +229,7 @@ export async function getUserAvatars(doRender = true, openPageAt = '') {
|
|||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
$(listId).append(getUserAvatarBlock(item));
|
$(listId).append(getUserAvatarBlock(item));
|
||||||
}
|
}
|
||||||
highlightSelectedAvatar();
|
updatePersonaUIStates();
|
||||||
},
|
},
|
||||||
afterSizeSelectorChange: function (e) {
|
afterSizeSelectorChange: function (e) {
|
||||||
localStorage.setItem(storageKey, e.target.value);
|
localStorage.setItem(storageKey, e.target.value);
|
||||||
@@ -486,7 +497,7 @@ export function setPersonaDescription() {
|
|||||||
$('#persona_lore_button').toggleClass('world_set', !!power_user.persona_description_lorebook);
|
$('#persona_lore_button').toggleClass('world_set', !!power_user.persona_description_lorebook);
|
||||||
countPersonaDescriptionTokens();
|
countPersonaDescriptionTokens();
|
||||||
|
|
||||||
updatePersonaLockIcons();
|
updatePersonaUIStates();
|
||||||
updatePersonaConnectionsAvatarList();
|
updatePersonaConnectionsAvatarList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,7 +791,7 @@ function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
|
|||||||
toastr.success(`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`);
|
toastr.success(`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`);
|
||||||
}
|
}
|
||||||
saveMetadataDebounced();
|
saveMetadataDebounced();
|
||||||
updatePersonaLockIcons();
|
updatePersonaUIStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
// As the last step, inform user if the persona is only temporarily chosen
|
// As the last step, inform user if the persona is only temporarily chosen
|
||||||
@@ -806,8 +817,8 @@ function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
|
|||||||
* @returns {boolean} Whether the connection is locked
|
* @returns {boolean} Whether the connection is locked
|
||||||
*/
|
*/
|
||||||
export function isPersonaConnectionLocked(connection) {
|
export function isPersonaConnectionLocked(connection) {
|
||||||
return (menu_type === 'character_edit' && connection.type === 'character' && connection.id === characters[this_chid]?.avatar)
|
return (!selected_group && connection.type === 'character' && connection.id === characters[this_chid]?.avatar)
|
||||||
|| (menu_type === 'group_edit' && connection.type === 'group' && connection.id === selected_group);
|
|| (selected_group && connection.type === 'group' && connection.id === selected_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -894,7 +905,7 @@ async function unlockPersona(type = 'chat') {
|
|||||||
throw new Error(`Unknown persona lock type: ${type}`);
|
throw new Error(`Unknown persona lock type: ${type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePersonaLockIcons();
|
updatePersonaUIStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -969,7 +980,7 @@ async function lockPersona(type = 'chat') {
|
|||||||
throw new Error(`Unknown persona lock type: ${type}`);
|
throw new Error(`Unknown persona lock type: ${type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePersonaLockIcons();
|
updatePersonaUIStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1149,7 +1160,7 @@ function getOrCreatePersonaDescriptor() {
|
|||||||
|
|
||||||
async function toggleDefaultPersonaClicked(e) {
|
async function toggleDefaultPersonaClicked(e) {
|
||||||
e?.stopPropagation();
|
e?.stopPropagation();
|
||||||
const avatarId = $(e.currentTarget).closest('.avatar-container').find('.avatar').attr('imgfile');
|
const avatarId = $(e.currentTarget).closest('.avatar-container').find('.avatar').attr('data-avatar-id');
|
||||||
if (avatarId) {
|
if (avatarId) {
|
||||||
await toggleDefaultPersona(avatarId);
|
await toggleDefaultPersona(avatarId);
|
||||||
} else {
|
} else {
|
||||||
@@ -1213,26 +1224,62 @@ async function toggleDefaultPersona(avatarId, { quiet: quiet = false } = {}) {
|
|||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
await getUserAvatars(true, avatarId);
|
await getUserAvatars(true, avatarId);
|
||||||
updatePersonaLockIcons();
|
updatePersonaUIStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePersonaLockIcons() {
|
/**
|
||||||
const isDefaultPersona = power_user.default_persona === user_avatar;
|
* Returns an object with 3 properties that describe the state of the given persona
|
||||||
$('#lock_persona_default').toggleClass('locked', isDefaultPersona);
|
*
|
||||||
|
* - default: Whether this persona is the default one for all new chats
|
||||||
const hasChatLock = chat_metadata['persona'] == user_avatar;
|
* - locked: An object containing the lock states
|
||||||
$('#lock_user_name').toggleClass('locked', hasChatLock);
|
* - chat: Whether the persona is locked to the currently open chat
|
||||||
$('#lock_user_name i.icon').toggleClass('fa-lock', hasChatLock);
|
* - character: Whether the persona is locked to the currently open character or group
|
||||||
$('#lock_user_name i.icon').toggleClass('fa-unlock', !hasChatLock);
|
* @param {string} avatarId - The avatar id of the persona to get the state for
|
||||||
|
* @returns {PersonaState} An object describing the state of the given persona
|
||||||
|
*/
|
||||||
|
function getPersonaStates(avatarId) {
|
||||||
|
const isDefaultPersona = power_user.default_persona === avatarId;
|
||||||
|
const hasChatLock = chat_metadata['persona'] == avatarId;
|
||||||
|
|
||||||
/** @type {PersonaConnection[]} */
|
/** @type {PersonaConnection[]} */
|
||||||
const connections = power_user.persona_descriptions[user_avatar]?.connections;
|
const connections = power_user.persona_descriptions[avatarId]?.connections;
|
||||||
const hasCharLock = !!connections?.some(c =>
|
const hasCharLock = !!connections?.some(c =>
|
||||||
(menu_type === 'character_edit' && c.type === 'character' && c.id === characters[this_chid]?.avatar)
|
(!selected_group && c.type === 'character' && c.id === characters[this_chid]?.avatar)
|
||||||
|| (menu_type === 'group_edit' && c.type === 'group' && c.id === selected_group));
|
|| (selected_group && c.type === 'group' && c.id === selected_group));
|
||||||
$('#lock_persona_to_char').toggleClass('locked', hasCharLock);
|
|
||||||
$('#lock_persona_to_char i.icon').toggleClass('fa-lock', hasCharLock);
|
return {
|
||||||
$('#lock_persona_to_char i.icon').toggleClass('fa-unlock', !hasCharLock);
|
avatarId: avatarId,
|
||||||
|
default: isDefaultPersona,
|
||||||
|
locked: {
|
||||||
|
chat: hasChatLock,
|
||||||
|
character: hasCharLock,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePersonaUIStates() {
|
||||||
|
// Update the persona list
|
||||||
|
$('#user_avatar_block .avatar-container').each(function () {
|
||||||
|
const avatarId = $(this).attr('data-avatar-id');
|
||||||
|
const states = getPersonaStates(avatarId);
|
||||||
|
$(this).toggleClass('default_persona', states.default);
|
||||||
|
$(this).toggleClass('locked_to_chat', states.locked.chat);
|
||||||
|
$(this).toggleClass('locked_to_character', states.locked.character);
|
||||||
|
$(this).toggleClass('selected', avatarId === user_avatar);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Buttons for the persona panel on the right
|
||||||
|
const personaStates = getPersonaStates(user_avatar);
|
||||||
|
|
||||||
|
$('#lock_persona_default').toggleClass('locked', personaStates.default);
|
||||||
|
|
||||||
|
$('#lock_user_name').toggleClass('locked', personaStates.locked.chat);
|
||||||
|
$('#lock_user_name i.icon').toggleClass('fa-lock', personaStates.locked.chat);
|
||||||
|
$('#lock_user_name i.icon').toggleClass('fa-unlock', !personaStates.locked.chat);
|
||||||
|
|
||||||
|
$('#lock_persona_to_char').toggleClass('locked', personaStates.locked.character);
|
||||||
|
$('#lock_persona_to_char i.icon').toggleClass('fa-lock', personaStates.locked.character);
|
||||||
|
$('#lock_persona_to_char i.icon').toggleClass('fa-unlock', !personaStates.locked.character);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadPersonaForCurrentChat({ doRender = false } = {}) {
|
async function loadPersonaForCurrentChat({ doRender = false } = {}) {
|
||||||
@@ -1315,7 +1362,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePersonaLockIcons();
|
updatePersonaUIStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1325,7 +1372,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
|
|||||||
* @returns {string[]} - An array of persona keys that are connected to the given character key
|
* @returns {string[]} - An array of persona keys that are connected to the given character key
|
||||||
*/
|
*/
|
||||||
export function getConnectedPersonas(characterKey = undefined) {
|
export function getConnectedPersonas(characterKey = undefined) {
|
||||||
characterKey ??= menu_type === 'group_edit' ? selected_group : characters[this_chid]?.avatar;
|
characterKey ??= selected_group || characters[this_chid]?.avatar;
|
||||||
const connectedPersonas = Object.entries(power_user.persona_descriptions)
|
const connectedPersonas = Object.entries(power_user.persona_descriptions)
|
||||||
.filter(([_, desc]) => desc.connections?.some(conn => conn.type === 'character' && conn.id === characterKey))
|
.filter(([_, desc]) => desc.connections?.some(conn => conn.type === 'character' && conn.id === characterKey))
|
||||||
.map(([key, _]) => key);
|
.map(([key, _]) => key);
|
||||||
@@ -1339,9 +1386,9 @@ export function getConnectedPersonas(characterKey = undefined) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function getCurrentConnectionObj() {
|
export function getCurrentConnectionObj() {
|
||||||
if (menu_type === 'group_edit')
|
if (selected_group)
|
||||||
return { type: 'group', id: selected_group };
|
return { type: 'group', id: selected_group };
|
||||||
if (menu_type == 'character_edit')
|
if (characters[this_chid]?.avatar)
|
||||||
return { type: 'character', id: characters[this_chid]?.avatar };
|
return { type: 'character', id: characters[this_chid]?.avatar };
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1538,7 +1585,7 @@ export function initPersonas() {
|
|||||||
$('#avatar_upload_file').on('change', changeUserAvatar);
|
$('#avatar_upload_file').on('change', changeUserAvatar);
|
||||||
|
|
||||||
$(document).on('click', '#user_avatar_block .avatar-container', function () {
|
$(document).on('click', '#user_avatar_block .avatar-container', function () {
|
||||||
const imgfile = $(this).attr('imgfile');
|
const imgfile = $(this).attr('data-avatar-id');
|
||||||
setUserAvatar(imgfile);
|
setUserAvatar(imgfile);
|
||||||
|
|
||||||
// force firstMes {{user}} update on persona switch
|
// force firstMes {{user}} update on persona switch
|
||||||
|
@@ -222,6 +222,37 @@ table.responsiveTable {
|
|||||||
animation-name: flash;
|
animation-name: flash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.has_hover_label .label_icon {
|
||||||
|
transition: opacity var(--animation-duration) ease, max-width var(--animation-duration) ease;
|
||||||
|
}
|
||||||
|
.has_hover_label .label {
|
||||||
|
transition: opacity var(--animation-duration-slow) ease, max-width var(--animation-duration-slow) ease;
|
||||||
|
/* Prevent double gap on hidden icon */
|
||||||
|
margin-left: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.has_hover_label .label_icon,
|
||||||
|
.has_hover_label .label {
|
||||||
|
transition-delay: var(--animation-duration-slow);
|
||||||
|
}
|
||||||
|
.has_hover_label.fast .label_icon,
|
||||||
|
.has_hover_label.fast .label {
|
||||||
|
transition-delay: var(--animation-duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
.has_hover_label .label_icon,
|
||||||
|
.has_hover_label:hover .label {
|
||||||
|
opacity: 1;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.has_hover_label:hover .label_icon,
|
||||||
|
.has_hover_label .label {
|
||||||
|
opacity: 0;
|
||||||
|
max-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* Keyboard/focus navigation styling */
|
/* Keyboard/focus navigation styling */
|
||||||
/* Mimic the outline of keyboard navigation for most most focusable controls */
|
/* Mimic the outline of keyboard navigation for most most focusable controls */
|
||||||
.interactable {
|
.interactable {
|
||||||
@@ -2805,6 +2836,7 @@ select option:not(:checked) {
|
|||||||
.menu_button.disabled {
|
.menu_button.disabled {
|
||||||
filter: brightness(75%) grayscale(1);
|
filter: brightness(75%) grayscale(1);
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
cursor: inherit;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2880,8 +2912,7 @@ 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;
|
||||||
@@ -2915,8 +2946,9 @@ select option:not(:checked) {
|
|||||||
width: max-content;
|
width: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
#persona-management-block .menu_button {
|
#persona-management-block .avatar_container_states .menu_button {
|
||||||
filter: grayscale(0.5);
|
padding: 3px 5px;
|
||||||
|
pointer-events: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
#persona_controls .persona_name {
|
#persona_controls .persona_name {
|
||||||
@@ -3321,28 +3353,6 @@ grammarly-extension {
|
|||||||
z-index: 35;
|
z-index: 35;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-container .avatar-buttons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 3px;
|
|
||||||
opacity: 0.3;
|
|
||||||
transition: opacity 0.25s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-container .avatar-buttons:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-container .avatar-buttons .menu_button {
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ross should be able to handle this later */
|
|
||||||
/*.big-avatars .avatar-buttons{
|
|
||||||
justify-content: center;
|
|
||||||
width: fit-content;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
.avatar_div .avatar {
|
.avatar_div .avatar {
|
||||||
/* margin-left: 4px;
|
/* margin-left: 4px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
@@ -3603,6 +3613,7 @@ grammarly-extension {
|
|||||||
|
|
||||||
.menu_button {
|
.menu_button {
|
||||||
color: var(--SmartThemeBodyColor);
|
color: var(--SmartThemeBodyColor);
|
||||||
|
filter: grayscale(0.5);
|
||||||
background-color: var(--SmartThemeBlurTintColor);
|
background-color: var(--SmartThemeBlurTintColor);
|
||||||
border: 1px solid var(--SmartThemeBorderColor);
|
border: 1px solid var(--SmartThemeBorderColor);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@@ -3622,8 +3633,8 @@ grammarly-extension {
|
|||||||
min-width: calc(1.25em + 12px);
|
min-width: calc(1.25em + 12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu_button:hover,
|
.menu_button:not(.disabled):hover,
|
||||||
.menu_button.active {
|
.menu_button:not(.disabled).active {
|
||||||
background-color: var(--white30a);
|
background-color: var(--white30a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3876,11 +3887,28 @@ input[type='checkbox'].del_checkbox {
|
|||||||
color: var(--golden);
|
color: var(--golden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-container .avatar_state .fa-lock {
|
||||||
|
color: var(--active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-container:not(.locked_to_chat) .locked_to_chat_label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.avatar-container:not(.locked_to_character) .locked_to_character_label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#lock_persona_default.locked i.icon {
|
#lock_persona_default.locked i.icon {
|
||||||
color: var(--golden);
|
color: var(--golden);
|
||||||
}
|
}
|
||||||
#lock_user_name.locked i.icon,
|
|
||||||
#lock_persona_to_char.locked i.icon {
|
#lock_user_name.locked .icon,
|
||||||
|
.avatar-container.locked_to_chat .locked_to_chat_label .icon {
|
||||||
|
color: var(--SmartThemeQuoteColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
#lock_persona_to_char.locked .icon,
|
||||||
|
.avatar-container.locked_to_character .locked_to_character_label .icon {
|
||||||
color: var(--active);
|
color: var(--active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user