From c0e112d1954da6ad640278fd80595130ed2285ab Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Wed, 28 Feb 2024 06:05:04 +0100 Subject: [PATCH] Tag Folders: inline info for groups and avatars - Add list of character avatars to folders (overflow hidden) - Add and/or move count of characters for both groups and folders in overview - Add name list of all chars for groups, above tags - Replace alt texts of all avatar images with the entity name - Made title/mouseover tooltip more useful with separation between types and their names - refactored CSS usage of avatar sizes to global variables - grid view alignment changes --- public/css/tags.css | 1 + public/css/toggle-dependent.css | 86 ++++++++++++++++++++++---------- public/index.html | 22 ++++++--- public/script.js | 45 +++++++++++++++-- public/scripts/group-chats.js | 22 +++++++-- public/scripts/tags.js | 6 --- public/style.css | 88 ++++++++++++++++++++++++--------- 7 files changed, 202 insertions(+), 68 deletions(-) diff --git a/public/css/tags.css b/public/css/tags.css index 8c36ee5b4..242ee4cbc 100644 --- a/public/css/tags.css +++ b/public/css/tags.css @@ -254,3 +254,4 @@ 1px -1px 0px black; opacity: 1; } + diff --git a/public/css/toggle-dependent.css b/public/css/toggle-dependent.css index e405b0eca..6e3c440d0 100644 --- a/public/css/toggle-dependent.css +++ b/public/css/toggle-dependent.css @@ -1,3 +1,9 @@ +:root { + --big-avatar-height-factor: 1.8; + --big-avatar-width-factor: 1.2; + --big-avatar-border-factor: 5; +} + body.tts .mes[is_system="true"] .mes_narrate { display: none; } @@ -21,7 +27,7 @@ body.square-avatars .avatar, body.square-avatars .avatar img, body.square-avatars .hotswapAvatar, body.square-avatars .hotswapAvatar img { - border-radius: 2px !important; + border-radius: var(--avatar-base-border-radius) !important; } /*char list grid mode*/ @@ -89,10 +95,12 @@ body.charListGrid #rm_print_characters_block .group_select .group_name_block { width: 100%; } -body.charListGrid #rm_print_characters_block .bogus_folder_counter_block, body.charListGrid #rm_print_characters_block .ch_description, body.charListGrid #rm_print_characters_block .tags_inline, body.charListGrid #rm_print_characters_block .character_version, +body.charListGrid #rm_print_characters_block .bogus_folder_unit, +body.charListGrid #rm_print_characters_block .group_select_unit, +body.charListGrid #rm_print_characters_block .group_select_block_list, body.charListGrid #rm_print_characters_block .ch_avatar_url, #user_avatar_block.gridView .avatar-container .ch_description { display: none; @@ -106,12 +114,12 @@ body.big-avatars .bogus_folder_select .avatar { } body:not(.big-avatars) .avatar { - border-radius: 50%; + border-radius: var(--avatar-base-border-radius-round); } body.big-avatars .avatar { - width: 60px; - height: 90px; + width: calc(var(--avatar-base-height) * var(--big-avatar-width-factor)); + height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor)); /* width: unset; */ border-style: none; display: flex; @@ -120,33 +128,33 @@ body.big-avatars .avatar { align-items: center; /* align-self: unset; */ overflow: visible; - border-radius: 10px; + border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)); flex: 1 } body.big-avatars #user_avatar_block .avatar, body.big-avatars #user_avatar_block .avatar_upload { - height: 90px; - width: 60px; - border-radius: 10px; + width: calc(var(--avatar-base-height) * var(--big-avatar-width-factor)); + height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor)); + border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)); } body.big-avatars #user_avatar_block .avatar img { - height: 90px; - width: 60px; + width: calc(var(--avatar-base-height) * var(--big-avatar-width-factor)); + height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor)); } body.big-avatars .avatar img { - width: 60px; - height: 90px; + width: calc(var(--avatar-base-height) * var(--big-avatar-width-factor)); + height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor)); object-fit: cover; object-position: center; border: 1px solid var(--SmartThemeBorderColor); - border-radius: 10px; + border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)); } body:not(.big-avatars) .avatar_collage { - min-width: 50px; + min-width: var(--avatar-base-width); aspect-ratio: 1 / 1; } @@ -155,8 +163,8 @@ body:not(.big-avatars) .avatar_collage img { } body.big-avatars .avatar_collage { - min-width: 60px; - max-width: 60px; + min-width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor)); + max-width: calc(var(--avatar-base-width) * var(--big-avatar-width-factor)); aspect-ratio: 2 / 3; } @@ -169,42 +177,68 @@ 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 .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 .bogus_folder_avatars_block .avatar { + margin: calc(var(--avatar-base-border-radius)) 0; +} + +body:not(.big-avatars) .avatars_inline .avatar_collage { + min-width: calc(var(--avatar-base-width) * var(--inline-avatar-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)); +} + /* border radius for big avatars collages */ body.big-avatars .collage_2 .img_1 { - border-radius: 10px 0 0 10px !important; + border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) !important; } body.big-avatars .collage_2 .img_2 { - border-radius: 0 10px 10px 0 !important; + border-radius: 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 !important; } body.big-avatars .collage_3 .img_1 { - border-radius: 10px 0 0 0 !important; + border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 0 0 !important; } body.big-avatars .collage_3 .img_2 { - border-radius: 0 10px 0 0 !important; + border-radius: 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 0 !important; } body.big-avatars .collage_3 .img_3 { - border-radius: 0 0 10px 10px !important; + border-radius: 0 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) !important; } body.big-avatars .collage_4 .img_1 { - border-radius: 10px 0 0 0 !important; + border-radius: calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 0 0 !important; } body.big-avatars .collage_4 .img_2 { - border-radius: 0 10px 0 0 !important; + border-radius: 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 0 !important; } body.big-avatars .collage_4 .img_3 { - border-radius: 0 0 0 10px !important; + border-radius: 0 0 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) !important; } body.big-avatars .collage_4 .img_4 { - border-radius: 0 0 10px 0 !important; + border-radius: 0 0 calc(var(--avatar-base-border-radius) * var(--big-avatar-border-factor)) 0 !important; } diff --git a/public/index.html b/public/index.html index 1f3b24539..2d1e117d7 100644 --- a/public/index.html +++ b/public/index.html @@ -5006,10 +5006,16 @@
-
-
+
+
+
+ group of + 5 + characters +
+
@@ -5022,14 +5028,18 @@
+ + characters
-
- - character card(s) -
+
+
+
+ +
+
diff --git a/public/script.js b/public/script.js index 7cf3e08e6..453665bb6 100644 --- a/public/script.js +++ b/public/script.js @@ -1159,18 +1159,53 @@ export async function selectCharacterById(id) { function getTagBlock(item, entities) { let count = 0; + let subEntities = []; for (const entity of entities) { if (entitiesFilter.isElementTagged(entity, item.id)) { count++; + subEntities.push(entity); } } const template = $('#bogus_folder_template .bogus_folder_select').clone(); template.attr({ 'tagid': item.id, 'id': `BogusFolder${item.id}` }); - template.find('.avatar').css({ 'background-color': item.color, 'color': item.color2 }); - template.find('.ch_name').text(item.name); + template.find('.avatar').css({ 'background-color': item.color, 'color': item.color2 }).attr('title', `[Folder] ${item.name}`); + template.find('.ch_name').text(item.name).attr('title', `[Folder] ${item.name}`);; template.find('.bogus_folder_counter').text(count); + + // Fill inline character images + const inlineAvatars = template.find('.bogus_folder_avatars_block'); + for (const entitiy of subEntities) { + 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 != '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); + } + return template; } @@ -1200,9 +1235,9 @@ function getCharacterBlock(item, id) { // Populate the template const template = $('#character_template .character_select').clone(); template.attr({ 'chid': id, 'id': `CharID${id}` }); - template.find('img').attr('src', this_avatar); - template.find('.avatar').attr('title', item.avatar); - template.find('.ch_name').text(item.name); + template.find('img').attr('src', this_avatar).attr('alt', item.name); + template.find('.avatar').attr('title', `[Character] ${item.name}`); + template.find('.ch_name').text(item.name).attr('title', `[Character] ${item.name}`); if (power_user.show_card_avatar_urls) { template.find('.ch_avatar_url').text(item.avatar); } diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index bb0775624..5d9604aac 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -523,13 +523,27 @@ async function getGroups() { } export function getGroupBlock(group) { + let count = 0; + let namesList = []; + + // Build inline name list + if (Array.isArray(group.members) && group.members.length) { + for (const member of group.members) { + count++; + const character = characters.find(x => x.avatar === member || x.name === member); + namesList.push(`${character.name}`); + } + } + const template = $('#group_list_template .group_select').clone(); template.data('id', group.id); template.attr('grid', group.id); - template.find('.ch_name').text(group.name); + template.find('.ch_name').text(group.name).attr('title', `[Group] ${group.name}`); template.find('.group_fav_icon').css('display', 'none'); template.addClass(group.fav ? 'is_fav' : ''); template.find('.ch_fav').val(group.fav); + template.find('.group_select_counter').text(count); + template.find('.group_select_block_list').append(namesList.join('')); // Display inline tags const tags = getTagsList(group.id); @@ -565,11 +579,11 @@ function isValidImageUrl(url) { function getGroupAvatar(group) { if (!group) { - return $(`
`); + return $(`
`); } // if isDataURL or if it's a valid local file url if (isValidImageUrl(group.avatar_url)) { - return $(`
`); + return $(`
`); } const memberAvatars = []; @@ -595,6 +609,7 @@ function getGroupAvatar(group) { groupAvatar.find(`.img_${i + 1}`).attr('src', memberAvatars[i]); } + groupAvatar.attr('title', `[Group] ${group.name}`); return groupAvatar; } @@ -606,6 +621,7 @@ function getGroupAvatar(group) { // default avatar const groupAvatar = $('#group_avatars_template .collage_1').clone(); groupAvatar.find('.img_1').attr('src', group.avatar_url || system_avatar); + groupAvatar.attr('title', `[Group] ${group.name}`); return groupAvatar; } diff --git a/public/scripts/tags.js b/public/scripts/tags.js index f1ce12beb..d54d2af26 100644 --- a/public/scripts/tags.js +++ b/public/scripts/tags.js @@ -567,14 +567,8 @@ function onViewTagsListClick() { list.append(tagContainer); const sortedTags = sortTags(tags); - // var highestSortOrder = sortedTags.reduce((max, tag) => tag.sort_order !== undefined ? Math.max(max, tag.sort_order) : max, -1); for (const tag of sortedTags) { - // // For drag&drop to work we need a sort_order defined, so set it but not save. Gets persisted if there are any tag settings changes - // if (tag.sort_order === undefined) { - // tag.sort_order = ++highestSortOrder; - // } - appendViewTagToList(tagContainer, tag, everything); } diff --git a/public/style.css b/public/style.css index c8befaf63..f70eb433c 100644 --- a/public/style.css +++ b/public/style.css @@ -96,6 +96,12 @@ /*styles for the color picker*/ --tool-cool-color-picker-btn-bg: transparent; --tool-cool-color-picker-btn-border-color: transparent; + + --avatar-base-height: 50px; + --avatar-base-width: 50px; + --avatar-base-border-radius: 2px; + --avatar-base-border-radius-round: 50%; + --inline-avatar-factor: 0.6; } * { @@ -849,8 +855,8 @@ hr { } .add_avatar { - border: 2px solid var(--SmartThemeBodyColor); - margin: 2px; + border: var(--avatar-base-border-radius) solid var(--SmartThemeBodyColor); + margin: var(--avatar-base-border-radius); cursor: pointer; transition: filter 0.2s ease-in-out; } @@ -860,14 +866,14 @@ hr { } .avatar { - width: 50px; - height: 50px; + width: var(--avatar-base-width); + height: var(--avatar-base-height); border-style: none; flex: 1; } .last_mes .mesAvatarWrapper { - padding-bottom: 50px; + padding-bottom: var(--avatar-base-height); } .mes .avatar { @@ -880,8 +886,8 @@ hr { .hotswapAvatar, .hotswapAvatar .avatar { - width: 50px !important; - height: 50px !important; + width: var(--avatar-base-width) !important; + height: var(--avatar-base-height) !important; border-style: none; } @@ -901,10 +907,10 @@ hr { .hotswapAvatar .avatar_collage, .hotswapAvatar.group_select { - border-radius: 50% !important; + border-radius: var(--avatar-base-border-radius-round) !important; position: relative; overflow: hidden; - min-width: 50px !important; + min-width: var(--avatar-base-width) !important; } .hotswapAvatar.group_select .avatar.avatar_collage img { @@ -916,21 +922,21 @@ hr { } .hotswapAvatar .avatar { - width: 50px !important; - height: 50px !important; + width: var(--avatar-base-width) !important; + height: var(--avatar-base-height) !important; object-fit: cover; object-position: center center; - border-radius: 50% !important; + border-radius: var(--avatar-base-border-radius-round) !important; box-shadow: 0 0 5px var(--black50a); } .hotswapAvatar img, .avatar img { - width: 50px; - height: 50px; + width: var(--avatar-base-width); + height: var(--avatar-base-height); object-fit: cover; object-position: center center; - border-radius: 50%; + border-radius: var(--avatar-base-border-radius-round); border: 1px solid var(--SmartThemeBorderColor); /*--black30a*/ box-shadow: 0 0 5px var(--black50a); @@ -950,6 +956,43 @@ 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)); +} + +.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)); + /* margin-top: calc(var(--avatar-base-height) * var(--inline-avatar-factor) * 0.2); */ +} + +.bogus_folder_avatars_block .avatar { + margin: calc(var(--avatar-base-border-radius)) 0; +} + +.group_select_block_list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + gap: 0.2rem; + align-items: flex-end; + flex-basis: 100%; +} + +.group_select_block_list .group_ch_name:not(:last-child):not(:nth-last-child(2)):after { + content: ", "; + font-size: calc(var(--mainFontSize) * 0.9); +} + +.group_select_block_list .group_ch_name:nth-last-child(2):after { + content: " & "; + font-size: calc(var(--mainFontSize) * 0.9); +} + .mes_block { padding-top: 0; padding-left: 10px; @@ -1778,7 +1821,8 @@ input[type=search]:focus::-webkit-search-cancel-button { .character_select.is_fav .avatar, .group_select.is_fav .avatar, -.group_member.is_fav .avatar { +.group_member.is_fav .avatar, +.avatar.is_fav { outline: 2px solid var(--golden); } @@ -1842,8 +1886,8 @@ input[type=search]:focus::-webkit-search-cancel-button { cursor: pointer; margin-bottom: 1px; width: 100%; - outline: 2px solid transparent; - border: 2px solid transparent; + outline: var(--avatar-base-border-radius) solid transparent; + border: var(--avatar-base-border-radius) solid transparent; } .avatar-container .character_select_container { @@ -2297,18 +2341,18 @@ input[type="checkbox"]:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button .avatar-container .avatar { cursor: pointer; - border-radius: 50%; + border-radius: var(--avatar-base-border-radius-round); align-self: center; - outline: 2px solid transparent; + outline: var(--avatar-base-border-radius) solid transparent; flex: unset; } .avatar-container.selected { - border: 2px solid rgba(255, 255, 255, 0.7); + border: var(--avatar-base-border-radius) solid rgba(255, 255, 255, 0.7); } .avatar-container.default_persona .avatar { - outline: 2px solid var(--golden); + outline: var(--avatar-base-border-radius) solid var(--golden); } .avatar-container.default_persona .set_default_persona {