mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-03-03 03:17:54 +01:00
Tag Folders: Refactor tag code into tag.js
This commit is contained in:
parent
e578d3dbb6
commit
4ab45330c4
100
public/script.js
100
public/script.js
@ -153,10 +153,13 @@ import {
|
||||
import { ModuleWorkerWrapper, doDailyExtensionUpdatesCheck, extension_settings, getContext, loadExtensionSettings, renderExtensionTemplate, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js';
|
||||
import { COMMENT_NAME_DEFAULT, executeSlashCommands, getSlashCommandsHelp, processChatSlashCommands, registerSlashCommand } from './scripts/slash-commands.js';
|
||||
import {
|
||||
TAG_FOLDER_DEFAULT_TYPE,
|
||||
tag_map,
|
||||
tags,
|
||||
filterByTagState,
|
||||
isBogusFolder,
|
||||
isBogusFolderOpen,
|
||||
chooseBogusFolder,
|
||||
getTagBlock,
|
||||
loadTagsSettings,
|
||||
printTagFilters,
|
||||
getTagsList,
|
||||
@ -166,7 +169,6 @@ import {
|
||||
importTags,
|
||||
tag_filter_types,
|
||||
compareTagsForSort,
|
||||
TAG_FOLDER_TYPES,
|
||||
} from './scripts/tags.js';
|
||||
import {
|
||||
SECRET_KEYS,
|
||||
@ -275,8 +277,6 @@ export {
|
||||
printCharacters,
|
||||
isOdd,
|
||||
countOccurrences,
|
||||
chooseBogusFolder,
|
||||
isBogusFolder,
|
||||
};
|
||||
|
||||
showLoader();
|
||||
@ -1161,57 +1161,6 @@ export async function selectCharacterById(id) {
|
||||
}
|
||||
}
|
||||
|
||||
function getTagBlock(item, entities) {
|
||||
let count = entities.length;
|
||||
|
||||
const tagFolder = TAG_FOLDER_TYPES[item.folder_type];
|
||||
|
||||
const template = $('#bogus_folder_template .bogus_folder_select').clone();
|
||||
template.addClass(tagFolder.class);
|
||||
template.attr({ 'tagid': item.id, 'id': `BogusFolder${item.id}` });
|
||||
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);
|
||||
template.find('.bogus_folder_icon').addClass(tagFolder.fa_icon);
|
||||
if (count == 1) {
|
||||
template.find('.character_unit_name').text('character');
|
||||
}
|
||||
|
||||
// Fill inline character images
|
||||
const inlineAvatars = template.find('.bogus_folder_avatars_block');
|
||||
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 != '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;
|
||||
}
|
||||
|
||||
function getBackBlock() {
|
||||
const template = $('#bogus_folder_back_template .bogus_folder_select').clone();
|
||||
return template;
|
||||
@ -1337,26 +1286,6 @@ async function printCharacters(fullRefresh = false) {
|
||||
favsToHotswap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a given tag is defined as a folder. Meaning it's neither undefined nor 'NONE'.
|
||||
* @returns {boolean} If it's a tag folder
|
||||
*/
|
||||
function isBogusFolder(tag) {
|
||||
return tag?.folder_type !== undefined && tag.folder_type !== TAG_FOLDER_DEFAULT_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a user is currently in a bogus folder.
|
||||
* @returns {boolean} If currently viewing a folder
|
||||
*/
|
||||
function isBogusFolderOpen() {
|
||||
const anyIsFolder = entitiesFilter.getFilterData(FILTER_TYPES.TAG)?.selected
|
||||
.map(tagId => tags.find(x => x.id === tagId))
|
||||
.some(isBogusFolder);
|
||||
|
||||
return !!anyIsFolder;
|
||||
}
|
||||
|
||||
export function getEntitiesList({ doFilter } = {}) {
|
||||
function characterToEntity(character, id) {
|
||||
return { item: character, id, type: 'character' };
|
||||
@ -8099,27 +8028,6 @@ function doTogglePanels() {
|
||||
$('#option_settings').trigger('click');
|
||||
}
|
||||
|
||||
function chooseBogusFolder(source, tagId, remove = false) {
|
||||
// If we are here via the 'back' action, we implicitly take the last filtered folder as one to remove
|
||||
const isBack = tagId === 'back';
|
||||
if (isBack) {
|
||||
const drilldown = $(source).closest('#rm_characters_block').find('.rm_tag_bogus_drilldown');
|
||||
const lastTag = drilldown.find('.tag:last').last();
|
||||
tagId = lastTag.attr('id');
|
||||
remove = true;
|
||||
}
|
||||
|
||||
// Instead of manually updating the filter conditions, we just "click" on the filter tag
|
||||
// We search inside which filter block we are located in and use that one
|
||||
const FILTER_SELECTOR = ($(source).closest('#rm_characters_block') ?? $(source).closest('#rm_group_chats_block')).find('.rm_tag_filter');
|
||||
if (remove) {
|
||||
// Click twice to skip over the 'excluded' state
|
||||
$(FILTER_SELECTOR).find(`.tag[id=${tagId}]`).trigger('click').trigger('click');
|
||||
} else {
|
||||
$(FILTER_SELECTOR).find(`.tag[id=${tagId}]`).trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
function addDebugFunctions() {
|
||||
const doBackfill = async () => {
|
||||
for (const message of chat) {
|
||||
|
@ -7,13 +7,13 @@ import {
|
||||
getCharacters,
|
||||
entitiesFilter,
|
||||
printCharacters,
|
||||
chooseBogusFolder,
|
||||
isBogusFolder,
|
||||
getThumbnailUrl,
|
||||
default_avatar,
|
||||
} from '../script.js';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { FILTER_TYPES, FilterHelper } from './filters.js';
|
||||
|
||||
import { groupCandidatesFilter, groups, selected_group } from './group-chats.js';
|
||||
import { groupCandidatesFilter, groups, selected_group, getGroupAvatar } from './group-chats.js';
|
||||
import { download, onlyUnique, parseJsonFile, uuidv4, getSortableDelay } from './utils.js';
|
||||
import { power_user } from './power-user.js';
|
||||
|
||||
@ -23,6 +23,10 @@ export {
|
||||
tags,
|
||||
tag_map,
|
||||
filterByTagState,
|
||||
isBogusFolder,
|
||||
isBogusFolderOpen,
|
||||
chooseBogusFolder,
|
||||
getTagBlock,
|
||||
loadTagsSettings,
|
||||
printTagFilters,
|
||||
getTagsList,
|
||||
@ -142,7 +146,109 @@ function filterTagSubEntities(tag, entities) {
|
||||
return entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a given tag is defined as a folder. Meaning it's neither undefined nor 'NONE'.
|
||||
* @returns {boolean} If it's a tag folder
|
||||
*/
|
||||
function isBogusFolder(tag) {
|
||||
return tag?.folder_type !== undefined && tag.folder_type !== TAG_FOLDER_DEFAULT_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a user is currently in a bogus folder.
|
||||
* @returns {boolean} If currently viewing a folder
|
||||
*/
|
||||
function isBogusFolderOpen() {
|
||||
const anyIsFolder = entitiesFilter.getFilterData(FILTER_TYPES.TAG)?.selected
|
||||
.map(tagId => tags.find(x => x.id === tagId))
|
||||
.some(isBogusFolder);
|
||||
|
||||
return !!anyIsFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be called when a specific tag/folder is chosen to "drill down".
|
||||
* @param {*} source The jQuery element clicked when choosing the folder
|
||||
* @param {string} tagId The tag id that is behind the chosen folder
|
||||
* @param {boolean} remove Whether the given tag should be removed (otherwise it is added/chosen)
|
||||
*/
|
||||
function chooseBogusFolder(source, tagId, remove = false) {
|
||||
// If we are here via the 'back' action, we implicitly take the last filtered folder as one to remove
|
||||
const isBack = tagId === 'back';
|
||||
if (isBack) {
|
||||
const drilldown = $(source).closest('#rm_characters_block').find('.rm_tag_bogus_drilldown');
|
||||
const lastTag = drilldown.find('.tag:last').last();
|
||||
tagId = lastTag.attr('id');
|
||||
remove = true;
|
||||
}
|
||||
|
||||
// Instead of manually updating the filter conditions, we just "click" on the filter tag
|
||||
// We search inside which filter block we are located in and use that one
|
||||
const FILTER_SELECTOR = ($(source).closest('#rm_characters_block') ?? $(source).closest('#rm_group_chats_block')).find('.rm_tag_filter');
|
||||
if (remove) {
|
||||
// Click twice to skip over the 'excluded' state
|
||||
$(FILTER_SELECTOR).find(`.tag[id=${tagId}]`).trigger('click').trigger('click');
|
||||
} else {
|
||||
$(FILTER_SELECTOR).find(`.tag[id=${tagId}]`).trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
function getTagBlock(item, entities) {
|
||||
let count = entities.length;
|
||||
|
||||
const tagFolder = TAG_FOLDER_TYPES[item.folder_type];
|
||||
|
||||
const template = $('#bogus_folder_template .bogus_folder_select').clone();
|
||||
template.addClass(tagFolder.class);
|
||||
template.attr({ 'tagid': item.id, 'id': `BogusFolder${item.id}` });
|
||||
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);
|
||||
template.find('.bogus_folder_icon').addClass(tagFolder.fa_icon);
|
||||
if (count == 1) {
|
||||
template.find('.character_unit_name').text('character');
|
||||
}
|
||||
|
||||
// Fill inline character images
|
||||
buildTagInlineAvatars(template, 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user