Tag Folders: Rework favorites display
- Favorites display uses same method than inline avatars - Favorites now respect avatar style
This commit is contained in:
parent
8e184254c8
commit
fc6146fa00
|
@ -24,9 +24,7 @@ body.no-modelIcons .icon-svg {
|
|||
}
|
||||
|
||||
body.square-avatars .avatar,
|
||||
body.square-avatars .avatar img,
|
||||
body.square-avatars .hotswapAvatar,
|
||||
body.square-avatars .hotswapAvatar img {
|
||||
body.square-avatars .avatar img {
|
||||
border-radius: var(--avatar-base-border-radius) !important;
|
||||
}
|
||||
|
||||
|
@ -113,10 +111,6 @@ body.big-avatars .bogus_folder_select .avatar {
|
|||
flex: unset;
|
||||
}
|
||||
|
||||
body:not(.big-avatars) .avatar {
|
||||
border-radius: var(--avatar-base-border-radius-round);
|
||||
}
|
||||
|
||||
body.big-avatars .avatar {
|
||||
width: calc(var(--avatar-base-height) * var(--big-avatar-width-factor));
|
||||
height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor));
|
||||
|
@ -129,7 +123,6 @@ body.big-avatars .avatar {
|
|||
/* align-self: unset; */
|
||||
overflow: visible;
|
||||
border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor));
|
||||
flex: 1
|
||||
}
|
||||
|
||||
body.big-avatars #user_avatar_block .avatar,
|
||||
|
@ -177,30 +170,27 @@ body.big-avatars .avatar-container .ch_description {
|
|||
text-overflow: unset;
|
||||
}
|
||||
|
||||
body.big-avatars .avatars_inline .avatar,
|
||||
body.big-avatars .avatars_inline .avatar img {
|
||||
width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor) * var(--inline-avatar-factor));
|
||||
height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) * var(--inline-avatar-factor));
|
||||
body.big-avatars .avatars_inline_small .avatar,
|
||||
body.big-avatars .avatars_inline_small .avatar img {
|
||||
width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor) * var(--inline-avatar-small-factor));
|
||||
height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) * var(--inline-avatar-small-factor));
|
||||
}
|
||||
|
||||
body.big-avatars .bogus_folder_avatars_block {
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) * var(--inline-avatar-factor) + 2 * var(--avatar-base-border-radius));
|
||||
/* margin-top: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) * var(--inline-avatar-factor) * 0.2); */
|
||||
body.big-avatars .avatars_inline {
|
||||
max-height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) + 2 * var(--avatar-base-border-radius));
|
||||
}
|
||||
|
||||
body.big-avatars .bogus_folder_avatars_block .avatar {
|
||||
margin: calc(var(--avatar-base-border-radius)) 0;
|
||||
body.big-avatars .avatars_inline.avatars_inline_small {
|
||||
height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) * var(--inline-avatar-small-factor) + 2 * var(--avatar-base-border-radius));
|
||||
}
|
||||
|
||||
body:not(.big-avatars) .avatars_inline .avatar_collage {
|
||||
min-width: calc(var(--avatar-base-width) * var(--inline-avatar-factor));
|
||||
body:not(.big-avatars) .avatars_inline_small .avatar_collage {
|
||||
min-width: calc(var(--avatar-base-width) * var(--inline-avatar-small-factor));
|
||||
}
|
||||
|
||||
body.big-avatars .avatars_inline .avatar_collage {
|
||||
min-width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor) * var(--inline-avatar-factor));
|
||||
max-width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor) * var(--inline-avatar-factor));
|
||||
body.big-avatars .avatars_inline_small .avatar_collage {
|
||||
min-width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor) * var(--inline-avatar-small-factor));
|
||||
max-width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor) * var(--inline-avatar-small-factor));
|
||||
}
|
||||
|
||||
/* border radius for big avatars collages */
|
||||
|
|
|
@ -3888,7 +3888,7 @@
|
|||
<div class="right_menu_button fa-solid fa-list-ul" id="rm_button_characters" title="Select/Create Characters" data-i18n="[title]Select/Create Characters"></div>
|
||||
</div>
|
||||
<div id="HotSwapWrapper" class="alignitemscenter flex-container margin0auto width100p">
|
||||
<div class="hotswap flex-container flex1"></div>
|
||||
<div class="hotswap avatars_inline flex-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
@ -5022,15 +5022,10 @@
|
|||
<small class="character_version bogus_folder_counter"></small>
|
||||
<small class="bogus_folder_unit character_unit_name" data="characters">characters</small>
|
||||
</div>
|
||||
<div class="bogus_folder_avatars_block avatars_inline tags tags_inline"></div>
|
||||
<div class="bogus_folder_avatars_block avatars_inline avatars_inline_small tags tags_inline"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bogus_folder_inline_character_template" class="template_element">
|
||||
<div class="avatar flex alignitemscenter textAlignCenter">
|
||||
<img src="">
|
||||
</div>
|
||||
</div>
|
||||
<div id="bogus_folder_back_template" class="template_element">
|
||||
<div class="bogus_folder_select flex-container wide100p alignitemsflexstart" id="BogusFolderBack" tagid="back">
|
||||
<div class="avatar flex alignitemscenter textAlignCenter">
|
||||
|
@ -5043,9 +5038,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="hotswap_template" class="template_element">
|
||||
<div class="hotswapAvatar" title="Add a character/group to favorites to display it here!">
|
||||
<img src="/img/ai4.png">
|
||||
<div id="inline_avatar_template" class="template_element">
|
||||
<div class="avatar inline_avatar flex alignitemscenter textAlignCenter">
|
||||
<img src="">
|
||||
</div>
|
||||
</div>
|
||||
<div id="alternate_greetings_template" class="template_element">
|
||||
|
|
|
@ -249,6 +249,7 @@ export {
|
|||
scrollChatToBottom,
|
||||
isStreamingEnabled,
|
||||
getThumbnailUrl,
|
||||
buildAvatarList,
|
||||
getStoppingStrings,
|
||||
reloadMarkdownProcessor,
|
||||
getCurrentChatId,
|
||||
|
@ -1289,7 +1290,7 @@ async function printCharacters(fullRefresh = false) {
|
|||
favsToHotswap();
|
||||
}
|
||||
|
||||
export function getEntitiesList({ doFilter } = {}) {
|
||||
export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
|
||||
function characterToEntity(character, id) {
|
||||
return { item: character, id, type: 'character' };
|
||||
}
|
||||
|
@ -1327,7 +1328,9 @@ export function getEntitiesList({ doFilter } = {}) {
|
|||
entities = filterByTagState(entities, { globalDisplayFilters: true });
|
||||
}
|
||||
|
||||
sortEntitiesList(entities);
|
||||
if (doSort) {
|
||||
sortEntitiesList(entities);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
|
@ -5245,6 +5248,49 @@ function getThumbnailUrl(type, file) {
|
|||
return `/thumbnail?type=${type}&file=${encodeURIComponent(file)}`;
|
||||
}
|
||||
|
||||
function buildAvatarList(block, entities, { templateId = 'inline_avatar_template', empty = true, selectable = false } = {}) {
|
||||
if (empty) {
|
||||
block.empty();
|
||||
}
|
||||
|
||||
for (const entity of entities) {
|
||||
const id = entity.id;
|
||||
|
||||
// Populate the template
|
||||
const avatarTemplate = $(`#${templateId} .avatar`).clone();
|
||||
|
||||
let this_avatar = default_avatar;
|
||||
if (entity.item.avatar !== undefined && entity.item.avatar != 'none') {
|
||||
this_avatar = getThumbnailUrl('avatar', entity.item.avatar);
|
||||
}
|
||||
|
||||
avatarTemplate.attr('data-type', entity.type);
|
||||
avatarTemplate.attr({ 'chid': id, 'id': `CharID${id}` });
|
||||
avatarTemplate.find('img').attr('src', this_avatar).attr('alt', entity.item.name);
|
||||
avatarTemplate.attr('title', `[Character] ${entity.item.name}`);
|
||||
avatarTemplate.toggleClass('is_fav', entity.item.fav || entity.item.fav == 'true');
|
||||
avatarTemplate.find('.ch_fav').val(entity.item.fav);
|
||||
|
||||
// If this is a group, we need to hack slightly. We still want to keep most of the css classes and layout, but use a group avatar instead.
|
||||
if (entity.type === 'group') {
|
||||
const grpTemplate = getGroupAvatar(entity.item);
|
||||
|
||||
avatarTemplate.addClass(grpTemplate.attr('class'));
|
||||
avatarTemplate.empty();
|
||||
avatarTemplate.append(grpTemplate.children());
|
||||
avatarTemplate.attr('title', `[Group] ${entity.item.name}`);
|
||||
}
|
||||
|
||||
if (selectable) {
|
||||
avatarTemplate.addClass('selectable');
|
||||
avatarTemplate.toggleClass('character_select', entity.type === 'character');
|
||||
avatarTemplate.toggleClass('group_select', entity.type === 'group');
|
||||
}
|
||||
|
||||
block.append(avatarTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
async function getChat() {
|
||||
//console.log('/api/chats/get -- entered for -- ' + characters[this_chid].name);
|
||||
try {
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
setActiveCharacter,
|
||||
getEntitiesList,
|
||||
getThumbnailUrl,
|
||||
buildAvatarList,
|
||||
selectCharacterById,
|
||||
eventSource,
|
||||
menu_type,
|
||||
|
@ -264,82 +265,16 @@ async function RA_autoloadchat() {
|
|||
export async function favsToHotswap() {
|
||||
const entities = getEntitiesList({ doFilter: false });
|
||||
const container = $('#right-nav-panel .hotswap');
|
||||
const template = $('#hotswap_template .hotswapAvatar');
|
||||
const DEFAULT_COUNT = 6;
|
||||
const WIDTH_PER_ITEM = 60; // 50px + 5px gap + 5px padding
|
||||
const containerWidth = container.outerWidth();
|
||||
const maxCount = containerWidth > 0 ? Math.floor(containerWidth / WIDTH_PER_ITEM) : DEFAULT_COUNT;
|
||||
let count = 0;
|
||||
|
||||
const promises = [];
|
||||
const newContainer = container.clone();
|
||||
newContainer.empty();
|
||||
const favs = entities.filter(x => x.item.fav || x.item.fav == 'true');
|
||||
|
||||
for (const entity of entities) {
|
||||
if (count >= maxCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
const isFavorite = entity.item.fav || entity.item.fav == 'true';
|
||||
|
||||
if (!isFavorite) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isCharacter = entity.type === 'character';
|
||||
const isGroup = entity.type === 'group';
|
||||
|
||||
const grid = isGroup ? entity.id : '';
|
||||
const chid = isCharacter ? entity.id : '';
|
||||
|
||||
let slot = template.clone();
|
||||
slot.toggleClass('character_select', isCharacter);
|
||||
slot.toggleClass('group_select', isGroup);
|
||||
slot.attr('grid', isGroup ? grid : '');
|
||||
slot.attr('chid', isCharacter ? chid : '');
|
||||
slot.data('id', isGroup ? grid : chid);
|
||||
|
||||
if (isGroup) {
|
||||
const group = groups.find(x => x.id === grid);
|
||||
const avatar = getGroupAvatar(group);
|
||||
$(slot).find('img').replaceWith(avatar);
|
||||
$(slot).attr('title', group.name);
|
||||
}
|
||||
|
||||
if (isCharacter) {
|
||||
const imgLoadPromise = new Promise((resolve) => {
|
||||
const avatarUrl = getThumbnailUrl('avatar', entity.item.avatar);
|
||||
$(slot).find('img').attr('src', avatarUrl).on('load', resolve);
|
||||
$(slot).attr('title', entity.item.avatar);
|
||||
});
|
||||
|
||||
// if the image doesn't load in 500ms, resolve the promise anyway
|
||||
promises.push(Promise.race([imgLoadPromise, delay(500)]));
|
||||
}
|
||||
|
||||
$(slot).css('cursor', 'pointer');
|
||||
newContainer.append(slot);
|
||||
count++;
|
||||
}
|
||||
|
||||
// don't fill leftover spaces with avatar placeholders
|
||||
// just evenly space the selected avatars instead
|
||||
/*
|
||||
if (count < maxCount) { //if any space is left over
|
||||
let leftOverSlots = maxCount - count;
|
||||
for (let i = 1; i <= leftOverSlots; i++) {
|
||||
newContainer.append(template.clone());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
await Promise.allSettled(promises);
|
||||
//helpful instruction message if no characters are favorited
|
||||
if (count === 0) { container.html('<small><span><i class="fa-solid fa-star"></i> Favorite characters to add them to HotSwaps</span></small>'); }
|
||||
//otherwise replace with fav'd characters
|
||||
if (count > 0) {
|
||||
container.replaceWith(newContainer);
|
||||
if (favs.length == 0) {
|
||||
container.html('<small><span><i class="fa-solid fa-star"></i> Favorite characters to add them to HotSwaps</span></small>');
|
||||
return;
|
||||
}
|
||||
|
||||
buildAvatarList(container, favs, { selectable: true });
|
||||
}
|
||||
|
||||
//changes input bar and send button display depending on connection status
|
||||
|
|
|
@ -7,13 +7,12 @@ import {
|
|||
getCharacters,
|
||||
entitiesFilter,
|
||||
printCharacters,
|
||||
getThumbnailUrl,
|
||||
default_avatar,
|
||||
buildAvatarList,
|
||||
} from '../script.js';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { FILTER_TYPES, FilterHelper } from './filters.js';
|
||||
|
||||
import { groupCandidatesFilter, groups, selected_group, getGroupAvatar } from './group-chats.js';
|
||||
import { groupCandidatesFilter, groups, selected_group } from './group-chats.js';
|
||||
import { download, onlyUnique, parseJsonFile, uuidv4, getSortableDelay } from './utils.js';
|
||||
import { power_user } from './power-user.js';
|
||||
|
||||
|
@ -210,46 +209,11 @@ function getTagBlock(item, entities) {
|
|||
}
|
||||
|
||||
// Fill inline character images
|
||||
buildTagInlineAvatars(template, entities);
|
||||
buildAvatarList(template.find('.bogus_folder_avatars_block'), entities);
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function buildTagInlineAvatars(template, entities) {
|
||||
const inlineAvatars = template.find('.bogus_folder_avatars_block');
|
||||
inlineAvatars.empty();
|
||||
|
||||
for (const entitiy of entities) {
|
||||
const id = entitiy.id;
|
||||
|
||||
// Populate the template
|
||||
const avatarTemplate = $('#bogus_folder_inline_character_template .avatar').clone();
|
||||
|
||||
let this_avatar = default_avatar;
|
||||
if (entitiy.item.avatar !== undefined && entitiy.item.avatar != 'none') {
|
||||
this_avatar = getThumbnailUrl('avatar', entitiy.item.avatar);
|
||||
}
|
||||
|
||||
avatarTemplate.attr({ 'chid': id, 'id': `CharID${id}` });
|
||||
avatarTemplate.find('img').attr('src', this_avatar).attr('alt', entitiy.item.name);
|
||||
avatarTemplate.attr('title', `[Character] ${entitiy.item.name}`);
|
||||
avatarTemplate.toggleClass('is_fav', entitiy.item.fav || entitiy.item.fav == 'true');
|
||||
avatarTemplate.find('.ch_fav').val(entitiy.item.fav);
|
||||
|
||||
// If this is a group, we need to hack slightly. We still want to keep most of the css classes and layout, but use a group avatar instead.
|
||||
if (entitiy.type === 'group') {
|
||||
const grpTemplate = getGroupAvatar(entitiy.item);
|
||||
|
||||
avatarTemplate.addClass(grpTemplate.attr('class'));
|
||||
avatarTemplate.empty();
|
||||
avatarTemplate.append(grpTemplate.children());
|
||||
avatarTemplate.attr('title', `Group: ${entitiy.item.name}`);
|
||||
}
|
||||
|
||||
inlineAvatars.append(avatarTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the favorite filter to the character list.
|
||||
* @param {FilterHelper} filterHelper Instance of FilterHelper class.
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
--avatar-base-width: 50px;
|
||||
--avatar-base-border-radius: 2px;
|
||||
--avatar-base-border-radius-round: 50%;
|
||||
--inline-avatar-factor: 0.6;
|
||||
--inline-avatar-small-factor: 0.6;
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -868,8 +868,10 @@ hr {
|
|||
.avatar {
|
||||
width: var(--avatar-base-width);
|
||||
height: var(--avatar-base-height);
|
||||
border-radius: var(--avatar-base-border-radius-round);
|
||||
border-style: none;
|
||||
flex: 1;
|
||||
transition: 250ms;
|
||||
}
|
||||
|
||||
.last_mes .mesAvatarWrapper {
|
||||
|
@ -880,40 +882,21 @@ hr {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
#HotSwapWrapper .hotswap {
|
||||
justify-content: space-evenly;
|
||||
.hotswap {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.hotswapAvatar,
|
||||
.hotswapAvatar .avatar {
|
||||
width: var(--avatar-base-width) !important;
|
||||
height: var(--avatar-base-height) !important;
|
||||
border-style: none;
|
||||
.avatar.selectable {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.hotswapAvatar {
|
||||
opacity: 0.5;
|
||||
transition: 250ms;
|
||||
overflow: hidden;
|
||||
padding: 0 !important;
|
||||
order: 100;
|
||||
}
|
||||
|
||||
.hotswapAvatar:hover {
|
||||
.avatar.selectable:hover {
|
||||
opacity: 1;
|
||||
background-color: transparent !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.hotswapAvatar .avatar_collage,
|
||||
.hotswapAvatar.group_select {
|
||||
border-radius: var(--avatar-base-border-radius-round) !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-width: var(--avatar-base-width) !important;
|
||||
}
|
||||
|
||||
.hotswapAvatar.group_select .avatar.avatar_collage img {
|
||||
.avatar.avatar_collage img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
|
@ -921,16 +904,6 @@ hr {
|
|||
border: 1px solid var(--SmartThemeBorderColor);
|
||||
}
|
||||
|
||||
.hotswapAvatar .avatar {
|
||||
width: var(--avatar-base-width) !important;
|
||||
height: var(--avatar-base-height) !important;
|
||||
object-fit: cover;
|
||||
object-position: center center;
|
||||
border-radius: var(--avatar-base-border-radius-round) !important;
|
||||
box-shadow: 0 0 5px var(--black50a);
|
||||
}
|
||||
|
||||
.hotswapAvatar img,
|
||||
.avatar img {
|
||||
width: var(--avatar-base-width);
|
||||
height: var(--avatar-base-height);
|
||||
|
@ -943,10 +916,17 @@ hr {
|
|||
}
|
||||
|
||||
.bogus_folder_select .avatar,
|
||||
.character_select .avatar {
|
||||
.character_select .avatar,
|
||||
.avatars_inline .avatar {
|
||||
flex: unset;
|
||||
}
|
||||
|
||||
.avatars_inline {
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
max-height: calc(var(--avatar-base-height) + 2 * var(--avatar-base-border-radius));
|
||||
}
|
||||
|
||||
.bogus_folder_select .avatar {
|
||||
justify-content: center;
|
||||
background-color: var(--SmartThemeBlurTintColor);
|
||||
|
@ -956,24 +936,24 @@ hr {
|
|||
outline-color: var(--SmartThemeBorderColor);
|
||||
}
|
||||
|
||||
.avatars_inline .avatar,
|
||||
.avatars_inline .avatar img {
|
||||
width: calc(var(--avatar-base-width) * var(--inline-avatar-factor));
|
||||
height: calc(var(--avatar-base-height) * var(--inline-avatar-factor));
|
||||
.avatars_inline_small .avatar,
|
||||
.avatars_inline_small .avatar img {
|
||||
width: calc(var(--avatar-base-width) * var(--inline-avatar-small-factor));
|
||||
height: calc(var(--avatar-base-height) * var(--inline-avatar-small-factor));
|
||||
}
|
||||
|
||||
.bogus_folder_avatars_block {
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
height: calc(var(--avatar-base-height) * var(--inline-avatar-factor) + 2 * var(--avatar-base-border-radius));
|
||||
.avatars_inline_small {
|
||||
height: calc(var(--avatar-base-height) * var(--inline-avatar-small-factor) + 2 * var(--avatar-base-border-radius));
|
||||
}
|
||||
|
||||
.bogus_folder_select:not(.folder_closed) .bogus_folder_avatars_block {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.bogus_folder_avatars_block .avatar {
|
||||
margin: calc(var(--avatar-base-border-radius)) 0;
|
||||
.avatars_inline .avatar {
|
||||
margin-top: calc(var(--avatar-base-border-radius));
|
||||
margin-left: calc(var(--avatar-base-border-radius));
|
||||
margin-bottom: calc(var(--avatar-base-border-radius));
|
||||
}
|
||||
|
||||
.group_select_block_list {
|
||||
|
@ -1627,6 +1607,11 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
|||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.character_select.inline_avatar {
|
||||
padding: unset;
|
||||
border-radius: var(--avatar-base-border-radius-round);
|
||||
}
|
||||
|
||||
/*applies to char list and mes_text char display name*/
|
||||
|
||||
.ch_name {
|
||||
|
|
Loading…
Reference in New Issue