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 @@
66 align-items: center;
77}
88
9+#rm_group_chats_block .tag.filterByFolder,
910#rm_group_chats_block .tag.filterByGroups {
1011 display: none;
1112}
public/scripts/RossAscends-mods.js+24 -28
@@ -276,40 +276,36 @@ export async function RA_CountCharTokens() {
276276 * The character or group is selected (clicked) if it is found.
277277 */
278278async 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 id
280+ 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+
285-
285+ // Do a little tomfoolery to spoof the tag selector
286- // Do a little tomfoolery to spoof the tag selector
286+ 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);
290290 setActiveCharacter saveSettingsDebounced(null);
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- }
294292 }
293+ }
295294
296295 if (active_group !== null && active_group !== undefined) {
297296 if (active_character) {
298297 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) {
299303 setActiveGroup(null);
300304 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- }
308306 }
309307 }
310-
308+ }
311- // if the character list hadn't been loaded yet, try again.
312- } else { setTimeout(RA_autoloadchat, 100); }
313309}
314310
315311export async function favsToHotswap() {
public/scripts/tags.js+45 -3
@@ -28,6 +28,7 @@ import { INTERACTABLE_CONTROL_CLASS } from './keyboard.js';
2828import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';
2929import { renderTemplateAsync } from './templates.js';
3030import { t, translate } from './i18n.js';
31+import { accountStorage } from './util/AccountStorage.js';
3132
3233export {
3334 TAG_FOLDER_TYPES,
@@ -64,6 +65,12 @@ function getFilterHelper(listSelector) {
6465 return $(listSelector).is(GROUP_FILTER_SELECTOR) ? groupCandidatesFilter : entitiesFilter;
6566}
6667
68+const ACTIONABLE_FILTER_STORAGE_KEYS = Object.freeze({
69+ GROUP: 'TagFilterState_GROUP',
70+ FAV: 'TagFilterState_FAV',
71+ FOLDER: 'TagFilterState_FOLDER',
72+});
73+
6774/** @enum {number} */
6875export const tag_filter_type = {
6976 character: 0,
@@ -331,12 +338,14 @@ function getTagBlock(tag, entities, hidden = 0, isUseless = false) {
331338
332339/**
333340 * Applies the favorite filter to the character list.
334341 * @param {FilterHelper} filterHelper_filterHelper Instance of FilterHelper class. Unused since it needs to be applied to both filters.
335342 */
336343function filterByFav(filterHelper_filterHelper) {
337344 const state = toggleTagThreeState($(this));
338345 ACTIONABLE_TAGS.FAV.filter_state = state;
339346 filterHelperaccountStorage.setFilterDatasetItem(FILTER_TYPESACTIONABLE_FILTER_STORAGE_KEYS.FAV, state);
347+ entitiesFilter.setFilterData(FILTER_TYPES.FAV, state);
348+ groupCandidatesFilter.setFilterData(FILTER_TYPES.FAV, state);
340349}
341350
342351/**
@@ -346,6 +355,7 @@ function filterByFav(filterHelper) {
346355function filterByGroups(filterHelper) {
347356 const state = toggleTagThreeState($(this));
348357 ACTIONABLE_TAGS.GROUP.filter_state = state;
358+ accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.GROUP, state);
349359 filterHelper.setFilterData(FILTER_TYPES.GROUP, state);
350360}
351361
@@ -363,6 +373,7 @@ function filterByFolder(filterHelper) {
363373
364374 const state = toggleTagThreeState($(this));
365375 ACTIONABLE_TAGS.FOLDER.filter_state = state;
376+ accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.FOLDER, state);
366377 filterHelper.setFilterData(FILTER_TYPES.FOLDER, state);
367378}
368379
@@ -2220,6 +2231,36 @@ function extractCharacterAvatar(avatarSrc) {
22202231 }
22212232}
22222233
2234+function 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+
22232264export function initTags() {
22242265 createTagInput('#tagInput', '#tagList', { tagOptions: { removable: true } });
22252266 createTagInput('#groupTagInput', '#groupTagList', { tagOptions: { removable: true } });
@@ -2281,4 +2322,5 @@ export function initTags() {
22812322 }
22822323
22832324 registerTagsSlashCommands();
2325+ restoreSavedTagFilters();
22842326}