Persist actionable tag states on reload (#4368) * Persist actionable tag states on reload Closes #3666 * Remove unneeded simulated clicks
Signed| @@ -6,6 +6,7 @@ | ||
| 6 | 6 | align-items: center; |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | +#rm_group_chats_block .tag.filterByFolder, | |
| 9 | 10 | #rm_group_chats_block .tag.filterByGroups { |
| 10 | 11 | display: none; |
| 11 | 12 | } |
| @@ -276,40 +276,36 @@ export async function RA_CountCharTokens() { | ||
| 276 | 276 | * The character or group is selected (clicked) if it is found. |
| 277 | 277 | */ |
| 278 | 278 | async 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); | |
| 290 | 290 | 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 | - } | |
| 294 | 292 | } |
| 293 | + } | |
| 295 | 294 | |
| 296 | 295 | if (active_group !== null && active_group !== undefined) { |
| 297 | 296 | if (active_character) { |
| 298 | 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 | 303 | setActiveGroup(null); |
| 300 | 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 | } |
| 310 | - | |
| 308 | + } | |
| 311 | - // if the character list hadn't been loaded yet, try again. | |
| 312 | - } else { setTimeout(RA_autoloadchat, 100); } | |
| 313 | 309 | } |
| 314 | 310 | |
| 315 | 311 | export async function favsToHotswap() { |
| @@ -28,6 +28,7 @@ import { INTERACTABLE_CONTROL_CLASS } from './keyboard.js'; | ||
| 28 | 28 | import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 29 | 29 | import { renderTemplateAsync } from './templates.js'; |
| 30 | 30 | import { t, translate } from './i18n.js'; |
| 31 | +import { accountStorage } from './util/AccountStorage.js'; | |
| 31 | 32 | |
| 32 | 33 | export { |
| 33 | 34 | TAG_FOLDER_TYPES, |
| @@ -64,6 +65,12 @@ function getFilterHelper(listSelector) { | ||
| 64 | 65 | return $(listSelector).is(GROUP_FILTER_SELECTOR) ? groupCandidatesFilter : entitiesFilter; |
| 65 | 66 | } |
| 66 | 67 | |
| 68 | +const ACTIONABLE_FILTER_STORAGE_KEYS = Object.freeze({ | |
| 69 | + GROUP: 'TagFilterState_GROUP', | |
| 70 | + FAV: 'TagFilterState_FAV', | |
| 71 | + FOLDER: 'TagFilterState_FOLDER', | |
| 72 | +}); | |
| 73 | + | |
| 67 | 74 | /** @enum {number} */ |
| 68 | 75 | export const tag_filter_type = { |
| 69 | 76 | character: 0, |
| @@ -331,12 +338,14 @@ function getTagBlock(tag, entities, hidden = 0, isUseless = false) { | ||
| 331 | 338 | |
| 332 | 339 | /** |
| 333 | 340 | * Applies the favorite filter to the character list. |
| 334 | 341 | * @param {FilterHelper} filterHelper_filterHelper Instance of FilterHelper class. Unused since it needs to be applied to both filters. |
| 335 | 342 | */ |
| 336 | 343 | function filterByFav(filterHelper_filterHelper) { |
| 337 | 344 | const state = toggleTagThreeState($(this)); |
| 338 | 345 | ACTIONABLE_TAGS.FAV.filter_state = state; |
| 339 | 346 | filterHelperaccountStorage.setFilterDatasetItem(FILTER_TYPESACTIONABLE_FILTER_STORAGE_KEYS.FAV, state); |
| 347 | + entitiesFilter.setFilterData(FILTER_TYPES.FAV, state); | |
| 348 | + groupCandidatesFilter.setFilterData(FILTER_TYPES.FAV, state); | |
| 340 | 349 | } |
| 341 | 350 | |
| 342 | 351 | /** |
| @@ -346,6 +355,7 @@ function filterByFav(filterHelper) { | ||
| 346 | 355 | function filterByGroups(filterHelper) { |
| 347 | 356 | const state = toggleTagThreeState($(this)); |
| 348 | 357 | ACTIONABLE_TAGS.GROUP.filter_state = state; |
| 358 | + accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.GROUP, state); | |
| 349 | 359 | filterHelper.setFilterData(FILTER_TYPES.GROUP, state); |
| 350 | 360 | } |
| 351 | 361 | |
| @@ -363,6 +373,7 @@ function filterByFolder(filterHelper) { | ||
| 363 | 373 | |
| 364 | 374 | const state = toggleTagThreeState($(this)); |
| 365 | 375 | ACTIONABLE_TAGS.FOLDER.filter_state = state; |
| 376 | + accountStorage.setItem(ACTIONABLE_FILTER_STORAGE_KEYS.FOLDER, state); | |
| 366 | 377 | filterHelper.setFilterData(FILTER_TYPES.FOLDER, state); |
| 367 | 378 | } |
| 368 | 379 | |
| @@ -2220,6 +2231,36 @@ function extractCharacterAvatar(avatarSrc) { | ||
| 2220 | 2231 | } |
| 2221 | 2232 | } |
| 2222 | 2233 | |
| 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 | + | |
| 2223 | 2264 | export function initTags() { |
| 2224 | 2265 | createTagInput('#tagInput', '#tagList', { tagOptions: { removable: true } }); |
| 2225 | 2266 | createTagInput('#groupTagInput', '#groupTagList', { tagOptions: { removable: true } }); |
| @@ -2281,4 +2322,5 @@ export function initTags() { | ||
| 2281 | 2322 | } |
| 2282 | 2323 | |
| 2283 | 2324 | registerTagsSlashCommands(); |
| 2325 | + restoreSavedTagFilters(); | |
| 2284 | 2326 | } |