mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add pagination for characters list view
This commit is contained in:
@ -42,6 +42,7 @@
|
|||||||
<script src="scripts/droll.js"></script>
|
<script src="scripts/droll.js"></script>
|
||||||
<script src="scripts/localforage.min.js"></script>
|
<script src="scripts/localforage.min.js"></script>
|
||||||
<script src="scripts/handlebars.js"></script>
|
<script src="scripts/handlebars.js"></script>
|
||||||
|
<script src="scripts/pagination.js"></script>
|
||||||
<script type="module" src="scripts/eventemitter.js"></script>
|
<script type="module" src="scripts/eventemitter.js"></script>
|
||||||
<script type="module" src="scripts/power-user.js"></script>
|
<script type="module" src="scripts/power-user.js"></script>
|
||||||
<script type="module" src="scripts/swiped-events.js"></script>
|
<script type="module" src="scripts/swiped-events.js"></script>
|
||||||
@ -98,6 +99,7 @@
|
|||||||
<script type="module" src="scripts/extensions.js"></script>
|
<script type="module" src="scripts/extensions.js"></script>
|
||||||
<script type="module" src="scripts/authors-note.js"></script>
|
<script type="module" src="scripts/authors-note.js"></script>
|
||||||
<script type="module" src="scripts/preset-manager.js"></script>
|
<script type="module" src="scripts/preset-manager.js"></script>
|
||||||
|
<script type="module" src="scripts/filters.js"></script>
|
||||||
<script type="text/javascript" src="scripts/toolcool-color-picker.js"></script>
|
<script type="text/javascript" src="scripts/toolcool-color-picker.js"></script>
|
||||||
|
|
||||||
<title>SillyTavern</title>
|
<title>SillyTavern</title>
|
||||||
@ -2988,7 +2990,7 @@
|
|||||||
<div id="rm_button_selected_ch">
|
<div id="rm_button_selected_ch">
|
||||||
<h2></h2>
|
<h2></h2>
|
||||||
</div>
|
</div>
|
||||||
<i id="hideCharPanelAvatarButton" class="fa-solid fa-eye menu_button"></i>
|
<i id="hideCharPanelAvatarButton" class="fa-solid fa-eye right_menu_button"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- end group peeking cope structure-->
|
<!-- end group peeking cope structure-->
|
||||||
@ -3255,14 +3257,12 @@
|
|||||||
<div class="rm_tag_controls">
|
<div class="rm_tag_controls">
|
||||||
<div class="tags rm_tag_filter"></div>
|
<div class="tags rm_tag_filter"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- a div containing a dynamically updated count of characters currently displayed -->
|
|
||||||
<div class="flex-container alignitemscenter">
|
|
||||||
<div id="rm_character_count"></div>
|
|
||||||
<i id="charListGridToggle" class="fa-solid fa-table-cells-large menu_button" title="Toggle character grid view"></i>
|
|
||||||
</div>
|
|
||||||
<hr>
|
<hr>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="rm_print_characters_pagination">
|
||||||
|
<i id="charListGridToggle" class="fa-solid fa-table-cells-large menu_button" title="Toggle character grid view"></i>
|
||||||
|
</div>
|
||||||
<div id="rm_print_characters_block" class="flexFlowColumn"></div>
|
<div id="rm_print_characters_block" class="flexFlowColumn"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
235
public/script.js
235
public/script.js
@ -40,7 +40,6 @@ import {
|
|||||||
generateGroupWrapper,
|
generateGroupWrapper,
|
||||||
deleteGroup,
|
deleteGroup,
|
||||||
is_group_generating,
|
is_group_generating,
|
||||||
printGroups,
|
|
||||||
resetSelectedGroup,
|
resetSelectedGroup,
|
||||||
select_group_chats,
|
select_group_chats,
|
||||||
regenerateGroup,
|
regenerateGroup,
|
||||||
@ -55,13 +54,13 @@ import {
|
|||||||
deleteGroupChat,
|
deleteGroupChat,
|
||||||
renameGroupChat,
|
renameGroupChat,
|
||||||
importGroupChat,
|
importGroupChat,
|
||||||
|
getGroupBlock,
|
||||||
} from "./scripts/group-chats.js";
|
} from "./scripts/group-chats.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
collapseNewlines,
|
collapseNewlines,
|
||||||
loadPowerUserSettings,
|
loadPowerUserSettings,
|
||||||
playMessageSound,
|
playMessageSound,
|
||||||
sortCharactersList,
|
|
||||||
fixMarkdown,
|
fixMarkdown,
|
||||||
power_user,
|
power_user,
|
||||||
pygmalion_options,
|
pygmalion_options,
|
||||||
@ -72,10 +71,9 @@ import {
|
|||||||
persona_description_positions,
|
persona_description_positions,
|
||||||
loadMovingUIState,
|
loadMovingUIState,
|
||||||
getCustomStoppingStrings,
|
getCustomStoppingStrings,
|
||||||
fuzzySearchCharacters,
|
|
||||||
MAX_CONTEXT_DEFAULT,
|
MAX_CONTEXT_DEFAULT,
|
||||||
fuzzySearchGroups,
|
|
||||||
renderStoryString,
|
renderStoryString,
|
||||||
|
sortEntitiesList,
|
||||||
} from "./scripts/power-user.js";
|
} from "./scripts/power-user.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -165,6 +163,7 @@ import { NOTE_MODULE_NAME, metadata_keys, setFloatingPrompt, shouldWIAddPrompt }
|
|||||||
import { deviceInfo } from "./scripts/RossAscends-mods.js";
|
import { deviceInfo } from "./scripts/RossAscends-mods.js";
|
||||||
import { registerPromptManagerMigration } from "./scripts/PromptManager.js";
|
import { registerPromptManagerMigration } from "./scripts/PromptManager.js";
|
||||||
import { getRegexedString, regex_placement } from "./scripts/extensions/regex/engine.js";
|
import { getRegexedString, regex_placement } from "./scripts/extensions/regex/engine.js";
|
||||||
|
import { FILTER_TYPES, FilterHelper } from "./scripts/filters.js";
|
||||||
|
|
||||||
//exporting functions and vars for mods
|
//exporting functions and vars for mods
|
||||||
export {
|
export {
|
||||||
@ -233,7 +232,6 @@ export {
|
|||||||
talkativeness_default,
|
talkativeness_default,
|
||||||
default_ch_mes,
|
default_ch_mes,
|
||||||
extension_prompt_types,
|
extension_prompt_types,
|
||||||
updateVisibleDivs,
|
|
||||||
mesForShowdownParse,
|
mesForShowdownParse,
|
||||||
printCharacters,
|
printCharacters,
|
||||||
}
|
}
|
||||||
@ -817,8 +815,9 @@ let token;
|
|||||||
|
|
||||||
var PromptArrayItemForRawPromptDisplay;
|
var PromptArrayItemForRawPromptDisplay;
|
||||||
|
|
||||||
export let active_character = ""
|
export let active_character = "";
|
||||||
export let active_group = ""
|
export let active_group = "";
|
||||||
|
export const entitiesFilter = new FilterHelper(debounce(printCharacters, 100));
|
||||||
|
|
||||||
export function getRequestHeaders() {
|
export function getRequestHeaders() {
|
||||||
return {
|
return {
|
||||||
@ -965,16 +964,43 @@ function resultCheckStatus() {
|
|||||||
$("#api_button_textgenerationwebui").css("display", "inline-block");
|
$("#api_button_textgenerationwebui").css("display", "inline-block");
|
||||||
}
|
}
|
||||||
|
|
||||||
async function printCharacters() {
|
export function selectCharacterById(id) {
|
||||||
$("#rm_print_characters_block").empty();
|
if (characters[id] == undefined) {
|
||||||
characters.forEach(function (item, i, arr) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected_group && is_group_generating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected_group || this_chid !== id) {
|
||||||
|
//if clicked on a different character from what was currently selected
|
||||||
|
if (!is_send_press) {
|
||||||
|
cancelTtsPlay();
|
||||||
|
resetSelectedGroup();
|
||||||
|
this_edit_mes_id = undefined;
|
||||||
|
selected_button = "character_edit";
|
||||||
|
this_chid = id;
|
||||||
|
clearChat();
|
||||||
|
chat.length = 0;
|
||||||
|
chat_metadata = {};
|
||||||
|
getChat();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//if clicked on character that was already selected
|
||||||
|
selected_button = "character_edit";
|
||||||
|
select_selected_character(this_chid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCharacterBlock(item, id) {
|
||||||
let this_avatar = default_avatar;
|
let this_avatar = default_avatar;
|
||||||
if (item.avatar != "none") {
|
if (item.avatar != "none") {
|
||||||
this_avatar = getThumbnailUrl('avatar', item.avatar);
|
this_avatar = getThumbnailUrl('avatar', item.avatar);
|
||||||
}
|
}
|
||||||
// Populate the template
|
// Populate the template
|
||||||
const template = $('#character_template .character_select').clone();
|
const template = $('#character_template .character_select').clone();
|
||||||
template.attr({ 'chid': i, 'id': `CharID${i}` });
|
template.attr({ 'chid': id, 'id': `CharID${id}` });
|
||||||
template.find('img').attr('src', this_avatar);
|
template.find('img').attr('src', this_avatar);
|
||||||
template.find('.avatar').attr('title', item.avatar);
|
template.find('.avatar').attr('title', item.avatar);
|
||||||
template.find('.ch_name').text(item.name);
|
template.find('.ch_name').text(item.name);
|
||||||
@ -1007,18 +1033,60 @@ async function printCharacters() {
|
|||||||
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
||||||
|
|
||||||
// Add to the list
|
// Add to the list
|
||||||
$("#rm_print_characters_block").append(template);
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function printCharacters(fullRefresh = false) {
|
||||||
|
const storageKey = 'Characters_PerPage';
|
||||||
|
$("#rm_print_characters_pagination").pagination({
|
||||||
|
dataSource: getEntitiesList({ doFilter: true }),
|
||||||
|
pageSize: Number(localStorage.getItem(storageKey)) || 50,
|
||||||
|
sizeChangerOptions: [25, 50, 100, 250, 500, 1000],
|
||||||
|
pageRange: 1,
|
||||||
|
position: 'top',
|
||||||
|
showPageNumbers: false,
|
||||||
|
showSizeChanger: true,
|
||||||
|
prevText: '<',
|
||||||
|
nextText: '>',
|
||||||
|
showNavigator: true,
|
||||||
|
callback: function (data) {
|
||||||
|
$("#rm_print_characters_block").empty();
|
||||||
|
for (const i of data) {
|
||||||
|
if (i.type === 'character') {
|
||||||
|
$("#rm_print_characters_block").append(getCharacterBlock(i.item, i.id));
|
||||||
|
}
|
||||||
|
if (i.type === 'group') {
|
||||||
|
$("#rm_print_characters_block").append(getGroupBlock(i.item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
afterSizeSelectorChange: function (e) {
|
||||||
|
localStorage.setItem(storageKey, e.target.value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
favsToHotswap();
|
||||||
|
|
||||||
|
if (fullRefresh) {
|
||||||
printTagFilters(tag_filter_types.character);
|
printTagFilters(tag_filter_types.character);
|
||||||
printTagFilters(tag_filter_types.group_member);
|
printTagFilters(tag_filter_types.group_member);
|
||||||
printGroups();
|
|
||||||
sortCharactersList();
|
|
||||||
favsToHotswap();
|
|
||||||
await delay(300);
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
displayOverrideWarnings();
|
|
||||||
|
|
||||||
|
await delay(300);
|
||||||
|
displayOverrideWarnings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEntitiesList({ doFilter } = {}) {
|
||||||
|
let entities = [];
|
||||||
|
entities.push(...characters.map((item, index) => ({ item, id: index, type: 'character' })));
|
||||||
|
entities.push(...groups.map((item) => ({ item, id: item.id, type: 'group' })));
|
||||||
|
|
||||||
|
if (doFilter) {
|
||||||
|
entities = entitiesFilter.applyFilters(entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
sortEntitiesList(entities);
|
||||||
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCharacters() {
|
async function getCharacters() {
|
||||||
@ -1050,10 +1118,7 @@ async function getCharacters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await getGroups();
|
await getGroups();
|
||||||
await printCharacters();
|
await printCharacters(true);
|
||||||
|
|
||||||
|
|
||||||
updateCharacterCount('#rm_print_characters_block > div');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4209,7 +4274,7 @@ async function renameCharacter() {
|
|||||||
if (newChId !== -1) {
|
if (newChId !== -1) {
|
||||||
// Select the character after the renaming
|
// Select the character after the renaming
|
||||||
this_chid = -1;
|
this_chid = -1;
|
||||||
$(`.character_select[chid="${newChId}"]`).click();
|
selectCharacterById(String(newChId));
|
||||||
|
|
||||||
// Async delay to update UI
|
// Async delay to update UI
|
||||||
await delay(1);
|
await delay(1);
|
||||||
@ -4303,7 +4368,6 @@ async function saveChat(chat_name, withMetadata, mesId) {
|
|||||||
const metadata = { ...chat_metadata, ...(withMetadata || {}) };
|
const metadata = { ...chat_metadata, ...(withMetadata || {}) };
|
||||||
let file_name = chat_name ?? characters[this_chid].chat;
|
let file_name = chat_name ?? characters[this_chid].chat;
|
||||||
characters[this_chid]['date_last_chat'] = Date.now();
|
characters[this_chid]['date_last_chat'] = Date.now();
|
||||||
sortCharactersList();
|
|
||||||
chat.forEach(function (item, i) {
|
chat.forEach(function (item, i) {
|
||||||
if (item["is_group"]) {
|
if (item["is_group"]) {
|
||||||
toastr.error('Trying to save group chat with regular saveChat function. Aborting to prevent corruption.');
|
toastr.error('Trying to save group chat with regular saveChat function. Aborting to prevent corruption.');
|
||||||
@ -5852,7 +5916,6 @@ function select_rm_characters() {
|
|||||||
menu_type = "characters";
|
menu_type = "characters";
|
||||||
selectRightMenuWithAnimation('rm_characters_block');
|
selectRightMenuWithAnimation('rm_characters_block');
|
||||||
setRightTabSelectedClass('rm_button_characters');
|
setRightTabSelectedClass('rm_button_characters');
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setExtensionPrompt(key, value, position, depth) {
|
function setExtensionPrompt(key, value, position, depth) {
|
||||||
@ -6199,7 +6262,6 @@ async function deleteMessageImage() {
|
|||||||
mesBlock.find('.mes_img_container').removeClass('img_extra');
|
mesBlock.find('.mes_img_container').removeClass('img_extra');
|
||||||
mesBlock.find('.mes_img').attr('src', '');
|
mesBlock.find('.mes_img').attr('src', '');
|
||||||
saveChatConditional();
|
saveChatConditional();
|
||||||
/*updateVisibleDivs('#chat', false);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function enlargeMessageImage() {
|
function enlargeMessageImage() {
|
||||||
@ -6932,51 +6994,6 @@ const swipe_right = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCharacterCount(characterSelector) {
|
|
||||||
const visibleCharacters = $(characterSelector)
|
|
||||||
.not(".hiddenBySearch")
|
|
||||||
.not(".hiddenByTag")
|
|
||||||
.not(".hiddenByGroup")
|
|
||||||
.not(".hiddenByGroupMember")
|
|
||||||
.not(".hiddenByFav");
|
|
||||||
const visibleCharacterCount = visibleCharacters.length;
|
|
||||||
const totalCharacterCount = $(characterSelector).length;
|
|
||||||
|
|
||||||
$("#rm_character_count").text(
|
|
||||||
`(${visibleCharacterCount} / ${totalCharacterCount}) Characters`
|
|
||||||
);
|
|
||||||
console.log("visibleCharacters.length: " + visibleCharacters.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateVisibleDivs(containerSelector, resizecontainer) {
|
|
||||||
var $container = $(containerSelector);
|
|
||||||
var $children = $container.children();
|
|
||||||
var totalHeight = 0;
|
|
||||||
$children.each(function () {
|
|
||||||
totalHeight += $(this).outerHeight();
|
|
||||||
});
|
|
||||||
if (resizecontainer) {
|
|
||||||
$container.css({
|
|
||||||
height: totalHeight,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var containerTop = $container.offset() ? $container.offset().top : 0;
|
|
||||||
var firstVisibleIndex = null;
|
|
||||||
var lastVisibleIndex = null;
|
|
||||||
$children.each(function (index) {
|
|
||||||
var $child = $(this);
|
|
||||||
var childTop = $child.offset().top - containerTop;
|
|
||||||
var childBottom = childTop + $child.outerHeight();
|
|
||||||
if (childTop <= $container.height() && childBottom >= 0) {
|
|
||||||
if (firstVisibleIndex === null) {
|
|
||||||
firstVisibleIndex = index;
|
|
||||||
}
|
|
||||||
lastVisibleIndex = index;
|
|
||||||
}
|
|
||||||
$child.toggleClass('hiddenByScroll', childTop > $container.height() || childBottom < 0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayOverrideWarnings() {
|
function displayOverrideWarnings() {
|
||||||
if (!this_chid || !selected_group) {
|
if (!this_chid || !selected_group) {
|
||||||
$('.prompt_overridden').hide();
|
$('.prompt_overridden').hide();
|
||||||
@ -7161,8 +7178,7 @@ function doCharListDisplaySwitch() {
|
|||||||
console.debug('toggling body charListGrid state')
|
console.debug('toggling body charListGrid state')
|
||||||
$("body").toggleClass('charListGrid')
|
$("body").toggleClass('charListGrid')
|
||||||
power_user.charListGrid = $("body").hasClass("charListGrid") ? true : false;
|
power_user.charListGrid = $("body").hasClass("charListGrid") ? true : false;
|
||||||
saveSettingsDebounced()
|
saveSettingsDebounced();
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doCloseChat() {
|
function doCloseChat() {
|
||||||
@ -7256,18 +7272,11 @@ $(document).ready(function () {
|
|||||||
registerSlashCommand('closechat', doCloseChat, [], "- closes the current chat", true, true);
|
registerSlashCommand('closechat', doCloseChat, [], "- closes the current chat", true, true);
|
||||||
registerSlashCommand('panels', doTogglePanels, ['togglepanels'], "- toggle UI panels on/off", true, true);
|
registerSlashCommand('panels', doTogglePanels, ['togglepanels'], "- toggle UI panels on/off", true, true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
$("#groupControlsToggle").trigger('click');
|
$("#groupControlsToggle").trigger('click');
|
||||||
$("#groupCurrentMemberListToggle .inline-drawer-icon").trigger('click');
|
$("#groupCurrentMemberListToggle .inline-drawer-icon").trigger('click');
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
|
|
||||||
$("#rm_print_characters_block").on('scroll', debounce(() => {
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}, 5));
|
|
||||||
|
|
||||||
$('#chat').on('scroll', async () => {
|
$('#chat').on('scroll', async () => {
|
||||||
// if on the start of the chat and has hidden messages
|
// if on the start of the chat and has hidden messages
|
||||||
if ($('#chat').scrollTop() === 0 && $('#chat').children('.mes').not(':visible').length > 0) {
|
if ($('#chat').scrollTop() === 0 && $('#chat').children('.mes').not(':visible').length > 0) {
|
||||||
@ -7330,43 +7339,8 @@ $(document).ready(function () {
|
|||||||
$(document).on('click', '.swipe_left', swipe_left);
|
$(document).on('click', '.swipe_left', swipe_left);
|
||||||
|
|
||||||
$("#character_search_bar").on("input", function () {
|
$("#character_search_bar").on("input", function () {
|
||||||
const selector = ['#rm_print_characters_block .character_select', '#rm_print_characters_block .group_select'].join(',');
|
const searchValue = $(this).val().toLowerCase();
|
||||||
const searchValue = $(this).val().trim().toLowerCase();
|
entitiesFilter.setFilterData(FILTER_TYPES.SEARCH, searchValue);
|
||||||
const fuzzySearchCharactersResults = power_user.fuzzy_search ? fuzzySearchCharacters(searchValue) : [];
|
|
||||||
const fuzzySearchGroupsResults = power_user.fuzzy_search ? fuzzySearchGroups(searchValue) : [];
|
|
||||||
|
|
||||||
function getIsValidSearch(_this) {
|
|
||||||
const name = $(_this).find(".ch_name").text().toLowerCase();
|
|
||||||
const chid = $(_this).attr("chid");
|
|
||||||
const grid = $(_this).attr("grid");
|
|
||||||
|
|
||||||
if (power_user.fuzzy_search) {
|
|
||||||
if (chid !== undefined) {
|
|
||||||
return fuzzySearchCharactersResults.includes(parseInt(chid));
|
|
||||||
} else if (grid !== undefined) {
|
|
||||||
return fuzzySearchGroupsResults.includes(String(grid));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return name.includes(searchValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!searchValue) {
|
|
||||||
$(selector).removeClass('hiddenBySearch');
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
} else {
|
|
||||||
$(selector).each(function () {
|
|
||||||
const isValidSearch = getIsValidSearch(this);
|
|
||||||
$(this).toggleClass('hiddenBySearch', !isValidSearch);
|
|
||||||
});
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
|
||||||
updateCharacterCount(selector);
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#send_but").click(function () {
|
$("#send_but").click(function () {
|
||||||
@ -7406,32 +7380,11 @@ $(document).ready(function () {
|
|||||||
$("#character_search_bar").val("").trigger("input");
|
$("#character_search_bar").val("").trigger("input");
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("click", ".character_select", function () {
|
$(document).on("click", ".character_select", function() {
|
||||||
if (selected_group && is_group_generating) {
|
const id = $(this).attr("chid");
|
||||||
return;
|
selectCharacterById(id);
|
||||||
}
|
|
||||||
|
|
||||||
if (selected_group || this_chid !== $(this).attr("chid")) {
|
|
||||||
//if clicked on a different character from what was currently selected
|
|
||||||
if (!is_send_press) {
|
|
||||||
cancelTtsPlay();
|
|
||||||
resetSelectedGroup();
|
|
||||||
this_edit_mes_id = undefined;
|
|
||||||
selected_button = "character_edit";
|
|
||||||
this_chid = $(this).attr("chid");
|
|
||||||
clearChat();
|
|
||||||
chat.length = 0;
|
|
||||||
chat_metadata = {};
|
|
||||||
getChat();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//if clicked on character that was already selected
|
|
||||||
selected_button = "character_edit";
|
|
||||||
select_selected_character(this_chid);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$(document).on("input", ".edit_textarea", function () {
|
$(document).on("input", ".edit_textarea", function () {
|
||||||
scroll_holder = $("#chat").scrollTop();
|
scroll_holder = $("#chat").scrollTop();
|
||||||
$(this).height(0).height(this.scrollHeight);
|
$(this).height(0).height(this.scrollHeight);
|
||||||
|
@ -13,11 +13,13 @@ import {
|
|||||||
menu_type,
|
menu_type,
|
||||||
max_context,
|
max_context,
|
||||||
saveSettingsDebounced,
|
saveSettingsDebounced,
|
||||||
eventSource,
|
|
||||||
active_group,
|
active_group,
|
||||||
active_character,
|
active_character,
|
||||||
setActiveGroup,
|
setActiveGroup,
|
||||||
setActiveCharacter,
|
setActiveCharacter,
|
||||||
|
getEntitiesList,
|
||||||
|
getThumbnailUrl,
|
||||||
|
selectCharacterById,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -348,12 +350,13 @@ async function RA_autoloadchat() {
|
|||||||
// active character is the name, we should look it up in the character list and get the id
|
// active character is the name, we should look it up in the character list and get the id
|
||||||
let active_character_id = Object.keys(characters).find(key => characters[key].avatar === active_character);
|
let active_character_id = Object.keys(characters).find(key => characters[key].avatar === active_character);
|
||||||
|
|
||||||
var charToAutoLoad = document.getElementById('CharID' + active_character_id);
|
if (active_character_id !== null) {
|
||||||
let groupToAutoLoad = document.querySelector(`.group_select[grid="${active_group}"]`);
|
selectCharacterById(String(active_character_id));
|
||||||
if (charToAutoLoad != null) {
|
|
||||||
$(charToAutoLoad).click();
|
|
||||||
}
|
}
|
||||||
else if (groupToAutoLoad != null) {
|
|
||||||
|
let groupToAutoLoad = document.querySelector(`.group_select[grid="${active_group}"]`);
|
||||||
|
|
||||||
|
if (groupToAutoLoad != null) {
|
||||||
$(groupToAutoLoad).click();
|
$(groupToAutoLoad).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,53 +365,60 @@ async function RA_autoloadchat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function favsToHotswap() {
|
export async function favsToHotswap() {
|
||||||
const selector = ['#rm_print_characters_block .character_select', '#rm_print_characters_block .group_select'].join(',');
|
const entities = getEntitiesList({ doFilter: false });
|
||||||
const container = $('#right-nav-panel .hotswap');
|
const container = $('#right-nav-panel .hotswap');
|
||||||
const template = $('#hotswap_template .hotswapAvatar');
|
const template = $('#hotswap_template .hotswapAvatar');
|
||||||
container.empty();
|
container.empty();
|
||||||
const maxCount = 6;
|
const maxCount = 6;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
$(selector).sort(sortByCssOrder).each(function () {
|
for (const entity of entities) {
|
||||||
if ($(this).hasClass('is_fav') && count < maxCount) {
|
if (count >= maxCount) {
|
||||||
const isCharacter = $(this).hasClass('character_select');
|
break;
|
||||||
const isGroup = $(this).hasClass('group_select');
|
}
|
||||||
const grid = Number($(this).attr('grid'));
|
|
||||||
const chid = Number($(this).attr('chid'));
|
const isFavorite = entity.item.fav || entity.item.fav == 'true';
|
||||||
let thisHotSwapSlot = template.clone();
|
|
||||||
thisHotSwapSlot.toggleClass('character_select', isCharacter);
|
if (!isFavorite) {
|
||||||
thisHotSwapSlot.toggleClass('group_select', isGroup);
|
continue;
|
||||||
thisHotSwapSlot.attr('grid', isGroup ? grid : '');
|
}
|
||||||
thisHotSwapSlot.attr('chid', isCharacter ? chid : '');
|
|
||||||
thisHotSwapSlot.data('id', isGroup ? grid : chid);
|
const isCharacter = entity.type === 'character';
|
||||||
thisHotSwapSlot.attr('title', '');
|
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);
|
||||||
|
slot.attr('title', '');
|
||||||
|
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
const group = groups.find(x => x.id === grid);
|
const group = groups.find(x => x.id === grid);
|
||||||
const avatar = getGroupAvatar(group);
|
const avatar = getGroupAvatar(group);
|
||||||
$(thisHotSwapSlot).find('img').replaceWith(avatar);
|
$(slot).find('img').replaceWith(avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCharacter) {
|
if (isCharacter) {
|
||||||
const avatarUrl = $(this).find('img').attr('src');
|
const avatarUrl = getThumbnailUrl('avatar', entity.item.avatar);
|
||||||
$(thisHotSwapSlot).find('img').attr('src', avatarUrl);
|
$(slot).find('img').attr('src', avatarUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(thisHotSwapSlot).css('cursor', 'pointer');
|
$(slot).css('cursor', 'pointer');
|
||||||
container.append(thisHotSwapSlot);
|
container.append(slot);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
//console.log('about to check for leftover selectors...')
|
|
||||||
// there are 6 slots in total,
|
// there are 6 slots in total,
|
||||||
if (count < maxCount) { //if any are left over
|
if (count < maxCount) { //if any are left over
|
||||||
let leftOverSlots = maxCount - count;
|
let leftOverSlots = maxCount - count;
|
||||||
for (let i = 1; i <= leftOverSlots; i++) {
|
for (let i = 1; i <= leftOverSlots; i++) {
|
||||||
container.append(template.clone());
|
container.append(template.clone());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//console.log(`count was ${count} so no need to knock off any selectors!`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
129
public/scripts/filters.js
Normal file
129
public/scripts/filters.js
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import { fuzzySearchCharacters, fuzzySearchGroups, power_user } from "./power-user.js";
|
||||||
|
import { tag_map } from "./tags.js";
|
||||||
|
|
||||||
|
export const FILTER_TYPES = {
|
||||||
|
SEARCH: 'search',
|
||||||
|
TAG: 'tag',
|
||||||
|
FAV: 'fav',
|
||||||
|
GROUP: 'group',
|
||||||
|
};
|
||||||
|
|
||||||
|
export class FilterHelper {
|
||||||
|
constructor(onDataChanged) {
|
||||||
|
this.onDataChanged = onDataChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterFunctions = {
|
||||||
|
[FILTER_TYPES.SEARCH]: this.searchFilter.bind(this),
|
||||||
|
[FILTER_TYPES.GROUP]: this.groupFilter.bind(this),
|
||||||
|
[FILTER_TYPES.FAV]: this.favFilter.bind(this),
|
||||||
|
[FILTER_TYPES.TAG]: this.tagFilter.bind(this),
|
||||||
|
}
|
||||||
|
|
||||||
|
filterData = {
|
||||||
|
[FILTER_TYPES.SEARCH]: '',
|
||||||
|
[FILTER_TYPES.GROUP]: false,
|
||||||
|
[FILTER_TYPES.FAV]: false,
|
||||||
|
[FILTER_TYPES.TAG]: { excluded: [], selected: [] },
|
||||||
|
}
|
||||||
|
|
||||||
|
tagFilter(data) {
|
||||||
|
const TAG_LOGIC_AND = true; // switch to false to use OR logic for combining tags
|
||||||
|
const { selected, excluded } = this.filterData[FILTER_TYPES.TAG];
|
||||||
|
|
||||||
|
if (!selected.length && !excluded.length) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElementTagged(entity, tagId) {
|
||||||
|
const isCharacter = entity.type === 'character';
|
||||||
|
const lookupValue = isCharacter ? entity.item.avatar : String(entity.id);
|
||||||
|
const isTagged = Array.isArray(tag_map[lookupValue]) && tag_map[lookupValue].includes(tagId);
|
||||||
|
return isTagged;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIsTagged(entity) {
|
||||||
|
const tagFlags = selected.map(tagId => isElementTagged(entity, tagId));
|
||||||
|
const trueFlags = tagFlags.filter(x => x);
|
||||||
|
const isTagged = TAG_LOGIC_AND ? tagFlags.length === trueFlags.length : trueFlags.length > 0;
|
||||||
|
|
||||||
|
const excludedTagFlags = excluded.map(tagId => isElementTagged(entity, tagId));
|
||||||
|
const isExcluded = excludedTagFlags.includes(true);
|
||||||
|
|
||||||
|
if (isExcluded) {
|
||||||
|
return false;
|
||||||
|
} else if (selected.length > 0 && !isTagged) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.filter(entity => getIsTagged(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
favFilter(data) {
|
||||||
|
if (!this.filterData[FILTER_TYPES.FAV]) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.filter(entity => entity.item.fav || entity.item.fav == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
groupFilter(data) {
|
||||||
|
if (!this.filterData[FILTER_TYPES.GROUP]) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.filter(entity => entity.type === 'group');
|
||||||
|
}
|
||||||
|
|
||||||
|
searchFilter(data) {
|
||||||
|
if (!this.filterData[FILTER_TYPES.SEARCH]) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchValue = this.filterData[FILTER_TYPES.SEARCH].trim().toLowerCase();
|
||||||
|
const fuzzySearchCharactersResults = power_user.fuzzy_search ? fuzzySearchCharacters(searchValue) : [];
|
||||||
|
const fuzzySearchGroupsResults = power_user.fuzzy_search ? fuzzySearchGroups(searchValue) : [];
|
||||||
|
|
||||||
|
function getIsValidSearch(entity) {
|
||||||
|
const isGroup = entity.type === 'group';
|
||||||
|
const isCharacter = entity.type === 'character';
|
||||||
|
|
||||||
|
if (power_user.fuzzy_search) {
|
||||||
|
if (isCharacter) {
|
||||||
|
return fuzzySearchCharactersResults.includes(parseInt(entity.id));
|
||||||
|
} else if (isGroup) {
|
||||||
|
return fuzzySearchGroupsResults.includes(String(entity.id));
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return entity.item?.name?.toLowerCase()?.includes(searchValue) || false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.filter(entity => getIsValidSearch(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilterData(filterType, data) {
|
||||||
|
const oldData = this.filterData[filterType];
|
||||||
|
this.filterData[filterType] = data;
|
||||||
|
|
||||||
|
// only trigger a data change if the data actually changed
|
||||||
|
if (JSON.stringify(oldData) !== JSON.stringify(data)) {
|
||||||
|
this.onDataChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilterData(filterType) {
|
||||||
|
return this.filterData[filterType];
|
||||||
|
}
|
||||||
|
|
||||||
|
applyFilters(data) {
|
||||||
|
return Object.values(this.filterFunctions)
|
||||||
|
.reduce((data, fn) => fn(data), data);
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ import {
|
|||||||
extractAllWords,
|
extractAllWords,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
import { RA_CountCharTokens, humanizedDateTime, dragElement } from "./RossAscends-mods.js";
|
import { RA_CountCharTokens, humanizedDateTime, dragElement } from "./RossAscends-mods.js";
|
||||||
import { sortCharactersList, sortGroupMembers, loadMovingUIState } from './power-user.js';
|
import { sortGroupMembers, loadMovingUIState } from './power-user.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
chat,
|
chat,
|
||||||
@ -63,6 +63,7 @@ import {
|
|||||||
getCropPopup,
|
getCropPopup,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect, tag_map } from './tags.js';
|
import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect, tag_map } from './tags.js';
|
||||||
|
import { FilterHelper } from './filters.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
selected_group,
|
selected_group,
|
||||||
@ -75,7 +76,6 @@ export {
|
|||||||
deleteGroup,
|
deleteGroup,
|
||||||
getGroupAvatar,
|
getGroupAvatar,
|
||||||
getGroups,
|
getGroups,
|
||||||
printGroups,
|
|
||||||
regenerateGroup,
|
regenerateGroup,
|
||||||
resetSelectedGroup,
|
resetSelectedGroup,
|
||||||
select_group_chats,
|
select_group_chats,
|
||||||
@ -94,9 +94,15 @@ export const group_activation_strategy = {
|
|||||||
LIST: 1,
|
LIST: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const groupCandidatesFilter = new FilterHelper(debounce(printGroupCandidates, 100));
|
||||||
const groupAutoModeInterval = setInterval(groupChatAutoModeWorker, 5000);
|
const groupAutoModeInterval = setInterval(groupChatAutoModeWorker, 5000);
|
||||||
const saveGroupDebounced = debounce(async (group) => await _save(group), 500);
|
const saveGroupDebounced = debounce(async (group) => await _save(group), 500);
|
||||||
|
|
||||||
|
function printGroupCandidates(fullRefresh = false) {
|
||||||
|
toastr.info('Group candidates tags filter is temporarily unavailable.');
|
||||||
|
console.log('TODO: implement printGroupCandidates');
|
||||||
|
}
|
||||||
|
|
||||||
async function _save(group, reload = true) {
|
async function _save(group, reload = true) {
|
||||||
await fetch("/editgroup", {
|
await fetch("/editgroup", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -228,7 +234,6 @@ async function saveGroupChat(groupId, shouldSaveGroup) {
|
|||||||
if (shouldSaveGroup && response.ok) {
|
if (shouldSaveGroup && response.ok) {
|
||||||
await editGroup(groupId);
|
await editGroup(groupId);
|
||||||
}
|
}
|
||||||
sortCharactersList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renameGroupMember(oldAvatar, newAvatar, newName) {
|
export async function renameGroupMember(oldAvatar, newAvatar, newName) {
|
||||||
@ -330,8 +335,7 @@ async function getGroups() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function printGroups() {
|
export function getGroupBlock(group) {
|
||||||
for (let group of groups) {
|
|
||||||
const template = $("#group_list_template .group_select").clone();
|
const template = $("#group_list_template .group_select").clone();
|
||||||
template.data("id", group.id);
|
template.data("id", group.id);
|
||||||
template.attr("grid", group.id);
|
template.attr("grid", group.id);
|
||||||
@ -345,10 +349,14 @@ function printGroups() {
|
|||||||
const tagsElement = template.find('.tags');
|
const tagsElement = template.find('.tags');
|
||||||
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
||||||
|
|
||||||
$("#rm_print_characters_block").prepend(template);
|
const avatar = getGroupAvatar(group);
|
||||||
updateGroupAvatar(group);
|
if (avatar) {
|
||||||
|
$(template).find(".avatar").replaceWith(avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateGroupAvatar(group) {
|
function updateGroupAvatar(group) {
|
||||||
$("#rm_print_characters_block .group_select").each(function () {
|
$("#rm_print_characters_block .group_select").each(function () {
|
||||||
if ($(this).data("id") == group.id) {
|
if ($(this).data("id") == group.id) {
|
||||||
@ -1353,7 +1361,6 @@ export async function openGroupChat(groupId, chatId) {
|
|||||||
|
|
||||||
await editGroup(groupId, true);
|
await editGroup(groupId, true);
|
||||||
await getGroupChat(groupId);
|
await getGroupChat(groupId);
|
||||||
sortCharactersList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renameGroupChat(groupId, oldChatId, newChatId) {
|
export async function renameGroupChat(groupId, oldChatId, newChatId) {
|
||||||
|
1190
public/scripts/pagination.js
Normal file
1190
public/scripts/pagination.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,6 @@ import {
|
|||||||
reloadCurrentChat,
|
reloadCurrentChat,
|
||||||
getRequestHeaders,
|
getRequestHeaders,
|
||||||
substituteParams,
|
substituteParams,
|
||||||
updateVisibleDivs,
|
|
||||||
eventSource,
|
eventSource,
|
||||||
event_types,
|
event_types,
|
||||||
getCurrentChatId,
|
getCurrentChatId,
|
||||||
@ -18,7 +17,7 @@ import {
|
|||||||
setCharacterId,
|
setCharacterId,
|
||||||
setEditedMessageId
|
setEditedMessageId
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
import { favsToHotswap, isMobile, initMovingUI } from "./RossAscends-mods.js";
|
import { isMobile, initMovingUI } from "./RossAscends-mods.js";
|
||||||
import {
|
import {
|
||||||
groups,
|
groups,
|
||||||
resetSelectedGroup,
|
resetSelectedGroup,
|
||||||
@ -35,7 +34,7 @@ export {
|
|||||||
collapseNewlines,
|
collapseNewlines,
|
||||||
playMessageSound,
|
playMessageSound,
|
||||||
sortGroupMembers,
|
sortGroupMembers,
|
||||||
sortCharactersList,
|
sortEntitiesList,
|
||||||
fixMarkdown,
|
fixMarkdown,
|
||||||
power_user,
|
power_user,
|
||||||
pygmalion_options,
|
pygmalion_options,
|
||||||
@ -803,7 +802,6 @@ function loadPowerUserSettings(settings, data) {
|
|||||||
|
|
||||||
|
|
||||||
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
|
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
|
||||||
sortCharactersList();
|
|
||||||
reloadMarkdownProcessor(power_user.render_formulas);
|
reloadMarkdownProcessor(power_user.render_formulas);
|
||||||
loadInstructMode();
|
loadInstructMode();
|
||||||
loadContextSettings();
|
loadContextSettings();
|
||||||
@ -812,7 +810,6 @@ function loadPowerUserSettings(settings, data) {
|
|||||||
switchSpoilerMode();
|
switchSpoilerMode();
|
||||||
loadMovingUIState();
|
loadMovingUIState();
|
||||||
loadCharListState();
|
loadCharListState();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadCharListState() {
|
async function loadCharListState() {
|
||||||
@ -1129,32 +1126,12 @@ const compareFunc = (first, second) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function sortCharactersList() {
|
function sortEntitiesList(entities) {
|
||||||
const arr1 = groups.map(x => ({
|
if (power_user.sort_field == undefined || entities.length === 0) {
|
||||||
item: x,
|
|
||||||
id: x.id,
|
|
||||||
selector: '.group_select',
|
|
||||||
attribute: 'grid',
|
|
||||||
}))
|
|
||||||
const arr2 = characters.map((x, index) => ({
|
|
||||||
item: x,
|
|
||||||
id: index,
|
|
||||||
selector: '.character_select',
|
|
||||||
attribute: 'chid',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const array = [...arr1, ...arr2];
|
|
||||||
|
|
||||||
if (power_user.sort_field == undefined || array.length === 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let orderedList = array.slice().sort((a, b) => sortFunc(a.item, b.item));
|
entities.sort((a, b) => sortFunc(a.item, b.item));
|
||||||
|
|
||||||
for (const item of array) {
|
|
||||||
$(`${item.selector}[${item.attribute}="${item.id}"]`).css({ 'order': orderedList.indexOf(item) });
|
|
||||||
}
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortGroupMembers(selector) {
|
function sortGroupMembers(selector) {
|
||||||
@ -1900,6 +1877,7 @@ $(document).ready(() => {
|
|||||||
power_user.never_resize_avatars = !!$(this).prop('checked');
|
power_user.never_resize_avatars = !!$(this).prop('checked');
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#show_card_avatar_urls").on('input', function () {
|
$("#show_card_avatar_urls").on('input', function () {
|
||||||
power_user.show_card_avatar_urls = !!$(this).prop('checked');
|
power_user.show_card_avatar_urls = !!$(this).prop('checked');
|
||||||
printCharacters();
|
printCharacters();
|
||||||
@ -1925,8 +1903,7 @@ $(document).ready(() => {
|
|||||||
power_user.sort_field = $(this).find(":selected").data('field');
|
power_user.sort_field = $(this).find(":selected").data('field');
|
||||||
power_user.sort_order = $(this).find(":selected").data('order');
|
power_user.sort_order = $(this).find(":selected").data('order');
|
||||||
power_user.sort_rule = $(this).find(":selected").data('rule');
|
power_user.sort_rule = $(this).find(":selected").data('rule');
|
||||||
sortCharactersList();
|
printCharacters();
|
||||||
favsToHotswap();
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2038,12 +2015,6 @@ $(document).ready(() => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
/* $("#removeXML").on("input", function () {
|
|
||||||
power_user.removeXML = !!$(this).prop('checked');
|
|
||||||
reloadCurrentChat();
|
|
||||||
saveSettingsDebounced();
|
|
||||||
}); */
|
|
||||||
|
|
||||||
$("#token_padding").on("input", function () {
|
$("#token_padding").on("input", function () {
|
||||||
power_user.token_padding = Number($(this).val());
|
power_user.token_padding = Number($(this).val());
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
@ -4,12 +4,12 @@ import {
|
|||||||
this_chid,
|
this_chid,
|
||||||
callPopup,
|
callPopup,
|
||||||
menu_type,
|
menu_type,
|
||||||
updateVisibleDivs,
|
|
||||||
getCharacters,
|
getCharacters,
|
||||||
updateCharacterCount,
|
entitiesFilter,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
import { FILTER_TYPES } from "./filters.js";
|
||||||
|
|
||||||
import { selected_group } from "./group-chats.js";
|
import { groupCandidatesFilter, selected_group } from "./group-chats.js";
|
||||||
import { uuidv4 } from "./utils.js";
|
import { uuidv4 } from "./utils.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -17,7 +17,6 @@ export {
|
|||||||
tag_map,
|
tag_map,
|
||||||
loadTagsSettings,
|
loadTagsSettings,
|
||||||
printTagFilters,
|
printTagFilters,
|
||||||
isElementTagged,
|
|
||||||
getTagsList,
|
getTagsList,
|
||||||
appendTagToList,
|
appendTagToList,
|
||||||
createTagMapFromList,
|
createTagMapFromList,
|
||||||
@ -26,18 +25,11 @@ export {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const random_id = () => uuidv4();
|
const random_id = () => uuidv4();
|
||||||
const TAG_LOGIC_AND = true; // switch to false to use OR logic for combining tags
|
|
||||||
const CHARACTER_SELECTOR = '#rm_print_characters_block > div';
|
|
||||||
const GROUP_MEMBER_SELECTOR = '#rm_group_add_members > div';
|
|
||||||
const CHARACTER_FILTER_SELECTOR = '#rm_characters_block .rm_tag_filter';
|
const CHARACTER_FILTER_SELECTOR = '#rm_characters_block .rm_tag_filter';
|
||||||
const GROUP_FILTER_SELECTOR = '#rm_group_chats_block .rm_tag_filter';
|
const GROUP_FILTER_SELECTOR = '#rm_group_chats_block .rm_tag_filter';
|
||||||
|
|
||||||
function getCharacterSelector(listSelector) {
|
function getFilterHelper(listSelector) {
|
||||||
if ($(listSelector).is(GROUP_FILTER_SELECTOR)) {
|
return $(listSelector).is(GROUP_FILTER_SELECTOR) ? groupCandidatesFilter : entitiesFilter;
|
||||||
return GROUP_MEMBER_SELECTOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CHARACTER_SELECTOR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tag_filter_types = {
|
export const tag_filter_types = {
|
||||||
@ -68,37 +60,20 @@ const DEFAULT_TAGS = [
|
|||||||
let tags = [];
|
let tags = [];
|
||||||
let tag_map = {};
|
let tag_map = {};
|
||||||
|
|
||||||
function applyFavFilter(characterSelector) {
|
function applyFavFilter(filterHelper) {
|
||||||
const isSelected = $(this).hasClass('selected');
|
const isSelected = $(this).hasClass('selected');
|
||||||
const displayFavoritesOnly = !isSelected;
|
const displayFavoritesOnly = !isSelected;
|
||||||
|
|
||||||
$(this).toggleClass('selected', displayFavoritesOnly);
|
$(this).toggleClass('selected', displayFavoritesOnly);
|
||||||
$(characterSelector).removeClass('hiddenByFav');
|
|
||||||
|
|
||||||
$(characterSelector).each(function () {
|
filterHelper.setFilterData(FILTER_TYPES.FAV, displayFavoritesOnly);
|
||||||
if (displayFavoritesOnly) {
|
|
||||||
if ($(this).find(".ch_fav").length !== 0) {
|
|
||||||
const shouldBeDisplayed = $(this).find(".ch_fav").val().toLowerCase().includes(true);
|
|
||||||
$(this).toggleClass('hiddenByFav', !shouldBeDisplayed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
updateCharacterCount(characterSelector);
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterByGroups(characterSelector) {
|
function filterByGroups(filterHelper) {
|
||||||
const isSelected = $(this).hasClass('selected');
|
const isSelected = $(this).hasClass('selected');
|
||||||
const displayGroupsOnly = !isSelected;
|
const displayGroupsOnly = !isSelected;
|
||||||
$(this).toggleClass('selected', displayGroupsOnly);
|
$(this).toggleClass('selected', displayGroupsOnly);
|
||||||
$(characterSelector).removeClass('hiddenByGroup');
|
|
||||||
|
|
||||||
$(characterSelector).each((_, element) => {
|
filterHelper.setFilterData(FILTER_TYPES.GROUP, displayGroupsOnly);
|
||||||
$(element).toggleClass('hiddenByGroup', displayGroupsOnly && !$(element).hasClass('group_select'));
|
|
||||||
});
|
|
||||||
updateCharacterCount(characterSelector);
|
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTagsSettings(settings) {
|
function loadTagsSettings(settings) {
|
||||||
@ -291,7 +266,6 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const characterSelector = getCharacterSelector($(listElement));
|
|
||||||
|
|
||||||
let tagElement = $('#tag_template .tag').clone();
|
let tagElement = $('#tag_template .tag').clone();
|
||||||
tagElement.attr('id', tag.id);
|
tagElement.attr('id', tag.id);
|
||||||
@ -316,11 +290,12 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectable) {
|
if (selectable) {
|
||||||
tagElement.on('click', () => onTagFilterClick.bind(tagElement)(listElement, characterSelector));
|
tagElement.on('click', () => onTagFilterClick.bind(tagElement)(listElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action) {
|
if (action) {
|
||||||
tagElement.on('click', () => action.bind(tagElement)(characterSelector));
|
const filter = getFilterHelper($(listElement));
|
||||||
|
tagElement.on('click', () => action.bind(tagElement)(filter));
|
||||||
tagElement.addClass('actionable');
|
tagElement.addClass('actionable');
|
||||||
}
|
}
|
||||||
if (action && tag.id === 2) {
|
if (action && tag.id === 2) {
|
||||||
@ -330,7 +305,7 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
|
|||||||
$(listElement).append(tagElement);
|
$(listElement).append(tagElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTagFilterClick(listElement, characterSelector) {
|
function onTagFilterClick(listElement) {
|
||||||
let excludeTag;
|
let excludeTag;
|
||||||
if ($(this).hasClass('selected')) {
|
if ($(this).hasClass('selected')) {
|
||||||
$(this).removeClass('selected');
|
$(this).removeClass('selected');
|
||||||
@ -356,44 +331,10 @@ function onTagFilterClick(listElement, characterSelector) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Overhaul this somehow to use settings tag IDs instead
|
|
||||||
const tagIds = [...($(listElement).find(".tag.selected:not(.actionable)").map((_, el) => $(el).attr("id")))];
|
const tagIds = [...($(listElement).find(".tag.selected:not(.actionable)").map((_, el) => $(el).attr("id")))];
|
||||||
const excludedTagIds = [...($(listElement).find(".tag.excluded:not(.actionable)").map((_, el) => $(el).attr("id")))];
|
const excludedTagIds = [...($(listElement).find(".tag.excluded:not(.actionable)").map((_, el) => $(el).attr("id")))];
|
||||||
$(characterSelector).each((_, element) => applyFilterToElement(tagIds, excludedTagIds, element));
|
const filterHelper = getFilterHelper($(listElement));
|
||||||
updateCharacterCount(characterSelector);
|
filterHelper.setFilterData(FILTER_TYPES.TAG, { excluded: excludedTagIds, selected: tagIds });
|
||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyFilterToElement(tagIds, excludedTagIds, element) {
|
|
||||||
const tagFlags = tagIds.map(tagId => isElementTagged(element, tagId));
|
|
||||||
const trueFlags = tagFlags.filter(x => x);
|
|
||||||
const isTagged = TAG_LOGIC_AND ? tagFlags.length === trueFlags.length : trueFlags.length > 0;
|
|
||||||
|
|
||||||
const excludedTagFlags = excludedTagIds.map(tagId => isElementTagged(element, tagId));
|
|
||||||
const isExcluded = excludedTagFlags.includes(true);
|
|
||||||
|
|
||||||
if (isExcluded) {
|
|
||||||
$(element).addClass('hiddenByTag');
|
|
||||||
} else if (tagIds.length > 0 && !isTagged) {
|
|
||||||
$(element).addClass('hiddenByTag');
|
|
||||||
} else {
|
|
||||||
$(element).removeClass('hiddenByTag');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isElementTagged(element, tagId) {
|
|
||||||
const isGroup = $(element).hasClass('group_select');
|
|
||||||
const isCharacter = $(element).hasClass('character_select') || $(element).hasClass('group_member');
|
|
||||||
const idAttr = isGroup ? 'grid' : 'chid';
|
|
||||||
const elementId = $(element).attr(idAttr);
|
|
||||||
const lookupValue = isCharacter ? characters[elementId].avatar : elementId;
|
|
||||||
const isTagged = Array.isArray(tag_map[lookupValue]) && tag_map[lookupValue].includes(tagId);
|
|
||||||
return isTagged;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearTagsFilter(characterSelector) {
|
|
||||||
$('.rm_tag_filter .tag').removeClass('selected');
|
|
||||||
$(characterSelector).removeClass('hiddenByTag');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printTagFilters(type = tag_filter_types.character) {
|
function printTagFilters(type = tag_filter_types.character) {
|
||||||
|
@ -1270,18 +1270,18 @@ input[type="file"] {
|
|||||||
filter: brightness(150%);
|
filter: brightness(150%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#rm_character_count {
|
#rm_print_characters_pagination {
|
||||||
padding: 5px;
|
display: flex;
|
||||||
font-size: calc(var(--mainFontSize) * .8);
|
flex-direction: row;
|
||||||
font-weight: bold;
|
gap: 5px;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rm_print_characters_block {
|
#rm_print_characters_block {
|
||||||
/* padding: 5px 0; */
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
/* row-gap: 5px; */
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.charListGrid #rm_print_characters_block {
|
body.charListGrid #rm_print_characters_block {
|
||||||
@ -1501,6 +1501,7 @@ select option:not(:checked) {
|
|||||||
display: flex;
|
display: flex;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rm_characters_block .right_menu_button {
|
#rm_characters_block .right_menu_button {
|
||||||
@ -5616,3 +5617,64 @@ body.waifuMode .zoomed_avatar {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
/* To align with adjacent text */
|
/* To align with adjacent text */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paginationjs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pagination */
|
||||||
|
.paginationsjs-pages {
|
||||||
|
margin: 0.5em 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-pages ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0.25em;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-size-changer select {
|
||||||
|
width: unset;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-pages ul li a {
|
||||||
|
padding: 0.05em 0.5em;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--SmartThemeBodyColor);
|
||||||
|
border: 1px solid var(--white30a);
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
opacity: 0.8;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-pages ul li a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-pages ul li.active a {
|
||||||
|
color: var(--SmartThemeQuoteColor);
|
||||||
|
border-color: var(--SmartThemeQuoteColor);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-pages ul li.disabled a {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginationjs-nav {
|
||||||
|
padding: 5px;
|
||||||
|
font-size: calc(var(--mainFontSize) * .8);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user