Persist actionable tag states on reload (#4368) * Persist actionable tag states on reload Closes #3666 * Remove unneeded simulated clicks

659930d5ba3dfa407f45fd0485a4f9187b74b97c

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +70 -31Ignore whitespace
public/css/rm-groups.css+1 -0
@@ -6,6 +6,7 @@
6 align-items: center;6 align-items: center;
7}7}
88
9#rm_group_chats_block .tag.filterByFolder,
9#rm_group_chats_block .tag.filterByGroups {10#rm_group_chats_block .tag.filterByGroups {
10 display: none;11 display: none;
11}12}
public/scripts/RossAscends-mods.js+24 -28
@@ -276,40 +276,36 @@ export async function RA_CountCharTokens() {
276 * The character or group is selected (clicked) if it is found.276 * The character or group is selected (clicked) if it is found.
277 */277 */
278async function RA_autoloadchat() {278async function RA_autoloadchat() {
279 if (document.querySelector('#rm_print_characters_block .character_select') !== null) {279 // active character is the name, we should look it up in the character list and get the id
280 // active character is the name, we should look it up in the character list and get the id280 if (active_character !== null && active_character !== undefined) {
281 if (active_character !== null && active_character !== undefined) {281 const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character);
282 const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character);282 if (active_character_id !== -1) {
283 if (active_character_id !== -1) {283 await selectCharacterById(active_character_id);
284 await selectCharacterById(active_character_id);284
285285 // Do a little tomfoolery to spoof the tag selector
286 // Do a little tomfoolery to spoof the tag selector286 const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`);
287 const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`);287 applyTagsOnCharacterSelect.call(selectedCharElement);
288 applyTagsOnCharacterSelect.call(selectedCharElement);288 } else {
289 } else {289 setActiveCharacter(null);
290 setActiveCharacter(null);290 saveSettingsDebounced();
291 saveSettingsDebounced();291 console.warn(`Currently active character with ID ${active_character} not found. Resetting to no active character.`);
292 console.warn(`Currently active character with ID ${active_character} not found. Resetting to no active character.`);
293 }
294 }292 }
293 }
295294
296 if (active_group !== null && active_group !== undefined) {295 if (active_group !== null && active_group !== undefined) {
297 if (active_character) {296 if (active_character) {
298 console.warn('Active character and active group are both set. Only active character will be loaded. Resetting active group.');297 console.warn('Active character and active group are both set. Only active character will be loaded. Resetting active group.');
298 setActiveGroup(null);
299 saveSettingsDebounced();
300 } else {
301 const result = await openGroupById(String(active_group));
302 if (!result) {
299 setActiveGroup(null);303 setActiveGroup(null);
300 saveSettingsDebounced();304 saveSettingsDebounced();
301 } else {305 console.warn(`Currently active group with ID ${active_group} not found. Resetting to no active group.`);
302 const result = await openGroupById(String(active_group));
303 if (!result) {
304 setActiveGroup(null);
305 saveSettingsDebounced();
306 console.warn(`Currently active group with ID ${active_group} not found. Resetting to no active group.`);
307 }
308 }306 }
309 }307 }
310308 }
311 // if the character list hadn't been loaded yet, try again.
312 } else { setTimeout(RA_autoloadchat, 100); }
313}309}
314310
315export async function favsToHotswap() {311export async function favsToHotswap() {
public/scripts/tags.js+45 -3
@@ -28,6 +28,7 @@ import { INTERACTABLE_CONTROL_CLASS } from './keyboard.js';
28import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';28import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';
29import { renderTemplateAsync } from './templates.js';29import { renderTemplateAsync } from './templates.js';
30import { t, translate } from './i18n.js';30import { t, translate } from './i18n.js';
31import { accountStorage } from './util/AccountStorage.js';
3132
32export {33export {
33 TAG_FOLDER_TYPES,34 TAG_FOLDER_TYPES,
@@ -64,6 +65,12 @@ function getFilterHelper(listSelector) {
64 return $(listSelector).is(GROUP_FILTER_SELECTOR) ? groupCandidatesFilter : entitiesFilter;65 return $(listSelector).is(GROUP_FILTER_SELECTOR) ? groupCandidatesFilter : entitiesFilter;
65}66}
6667
68const ACTIONABLE_FILTER_STORAGE_KEYS = Object.freeze({
69 GROUP: 'TagFilterState_GROUP',
70 FAV: 'TagFilterState_FAV',
71 FOLDER: 'TagFilterState_FOLDER',
72});
73
67/** @enum {number} */74/** @enum {number} */
68export const tag_filter_type = {75export const tag_filter_type = {
69 character: 0,76 character: 0,
@@ -331,12 +338,14 @@ function getTagBlock(tag, entities, hidden = 0, isUseless = false) {
331338
332/**339/**
333 * Applies the favorite filter to the character list.340 * Applies the favorite filter to the character list.
334 * @param {FilterHelper} filterHelper Instance of FilterHelper class.341 * @param {FilterHelper} _filterHelper Instance of FilterHelper class. Unused since it needs to be applied to both filters.
335 */342 */
336function filterByFav(filterHelper) {343function filterByFav(_filterHelper) {
337 const state = toggleTagThreeState($(this));344 const state = toggleTagThreeState($(this));
338 ACTIONABLE_TAGS.FAV.filter_state = state;345 ACTIONABLE_TAGS.FAV.filter_state = state;
339 filterHelper.setFilterData(FILTER_TYPES.FAV, state);346 accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.FAV, state);
347 entitiesFilter.setFilterData(FILTER_TYPES.FAV, state);
348 groupCandidatesFilter.setFilterData(FILTER_TYPES.FAV, state);
340}349}
341350
342/**351/**
@@ -346,6 +355,7 @@ function filterByFav(filterHelper) {
346function filterByGroups(filterHelper) {355function filterByGroups(filterHelper) {
347 const state = toggleTagThreeState($(this));356 const state = toggleTagThreeState($(this));
348 ACTIONABLE_TAGS.GROUP.filter_state = state;357 ACTIONABLE_TAGS.GROUP.filter_state = state;
358 accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.GROUP, state);
349 filterHelper.setFilterData(FILTER_TYPES.GROUP, state);359 filterHelper.setFilterData(FILTER_TYPES.GROUP, state);
350}360}
351361
@@ -363,6 +373,7 @@ function filterByFolder(filterHelper) {
363373
364 const state = toggleTagThreeState($(this));374 const state = toggleTagThreeState($(this));
365 ACTIONABLE_TAGS.FOLDER.filter_state = state;375 ACTIONABLE_TAGS.FOLDER.filter_state = state;
376 accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.FOLDER, state);
366 filterHelper.setFilterData(FILTER_TYPES.FOLDER, state);377 filterHelper.setFilterData(FILTER_TYPES.FOLDER, state);
367}378}
368379
@@ -2220,6 +2231,36 @@ function extractCharacterAvatar(avatarSrc) {
2220 }2231 }
2221}2232}
22222233
2234function restoreSavedTagFilters() {
2235 try {
2236 const validStates = new Set(Object.keys(FILTER_STATES));
2237 const readState = (/** @type {string} */ storageKey) => {
2238 const v = accountStorage.getItem(storageKey);
2239 return v && validStates.has(v) ? v : null;
2240 };
2241
2242 const favState = readState(ACTIONABLE_FILTER_STORAGE_KEYS.FAV);
2243 const groupState = readState(ACTIONABLE_FILTER_STORAGE_KEYS.GROUP);
2244 const folderState = readState(ACTIONABLE_FILTER_STORAGE_KEYS.FOLDER);
2245
2246 if (favState) {
2247 ACTIONABLE_TAGS.FAV.filter_state = favState;
2248 entitiesFilter.setFilterData(FILTER_TYPES.FAV, favState, true);
2249 groupCandidatesFilter.setFilterData(FILTER_TYPES.FAV, favState, true);
2250 }
2251 if (groupState) {
2252 ACTIONABLE_TAGS.GROUP.filter_state = groupState;
2253 entitiesFilter.setFilterData(FILTER_TYPES.GROUP, groupState, true);
2254 }
2255 if (folderState) {
2256 ACTIONABLE_TAGS.FOLDER.filter_state = folderState;
2257 entitiesFilter.setFilterData(FILTER_TYPES.FOLDER, folderState, true);
2258 }
2259 } catch (e) {
2260 console.warn('Failed to restore actionable filter states from account storage', e);
2261 }
2262}
2263
2223export function initTags() {2264export function initTags() {
2224 createTagInput('#tagInput', '#tagList', { tagOptions: { removable: true } });2265 createTagInput('#tagInput', '#tagList', { tagOptions: { removable: true } });
2225 createTagInput('#groupTagInput', '#groupTagList', { tagOptions: { removable: true } });2266 createTagInput('#groupTagInput', '#groupTagList', { tagOptions: { removable: true } });
@@ -2281,4 +2322,5 @@ export function initTags() {
2281 }2322 }
22822323
2283 registerTagsSlashCommands();2324 registerTagsSlashCommands();
2325 restoreSavedTagFilters();
2284}2326}