diff --git a/src/lib/stores/ae_idaa_stores__idaa_loc.svelte.ts b/src/lib/stores/ae_idaa_stores__idaa_loc.svelte.ts new file mode 100644 index 00000000..655de81a --- /dev/null +++ b/src/lib/stores/ae_idaa_stores__idaa_loc.svelte.ts @@ -0,0 +1,149 @@ +import { PersistedState } from 'runed'; + +// ---- Types ------------------------------------------------------------------- + +interface IdaaArchivesLoc { + enabled: string; // 'all' | 'disabled' | 'enabled' + hidden: string; // 'all' | 'hidden' | 'not_hidden' + limit: number; + offset: number; + edit_kv: Record; // Tracks which archive objects are being edited. + edit__archive_obj: any; + edit__archive_content_obj: any; +} + +interface IdaaBbLoc { + enabled: string; // 'all' | 'disabled' | 'enabled' + hidden: string; // 'all' | 'hidden' | 'not_hidden' + limit: number; + offset: number; + edit_kv: Record; // Tracks which post objects are being edited. + edit__post_obj: any; + edit__post_comment_obj: any; + show_list__post_obj_li: boolean; + qry__enabled: string; + qry__hidden: string; + qry__limit: number; + qry__offset: number; + qry__order_by: string; // For the IDB index query + qry__order_by_li: Record; // For the SQL query +} + +interface IdaaRecoveryMeetingsLoc { + edit_kv: Record; // Tracks which meeting objects are being edited. + edit__event_obj: any; + qry__enabled: string; + qry__hidden: string; + qry__limit: number; + qry__order_by: string; // For the IDB index query; name, updated_on/created_on + qry__order_by_li: Record; // For the SQL query + qry__offset: number; + qry__fulltext_str: string | null; + qry__physical: string | null; + qry__type: string | null; + qry__virtual: string | null; + // When true, only show meetings the member has starred. Favorites are stored + // server-side in event.mod_meetings_json.favorite (array of Novi UUIDs), so + // they persist across browsers without requiring a Novi API write capability. + qry__favorites_only: boolean; + // Collapse the "Meeting Info" data store panel. Persisted so preference survives reloads. + ds_info_collapsed: boolean; +} + +export interface IdaaLocState { + novi_uuid: string | null; + novi_email: string | null; + novi_full_name: string | null; + // True after a successful Novi API verification (UUID confirmed to be a real Novi member). + // False on load, on verification failure, or for non-Novi sign-in paths. + novi_verified: boolean; + // Timestamp (ms since epoch) when the last successful verification occurred. + // Used to cache verification results and avoid repeated Novi API calls. + novi_verified_ts: number | null; + // Populated from $ae_loc.site_cfg_json at IDAA layout mount — not managed here. + // See routes/idaa/(idaa)/+layout.svelte for the override logic. + novi_admin_li: string[]; + novi_trusted_li: string[]; + novi_jitsi_mod_li: string[]; + + archives: IdaaArchivesLoc; + bb: IdaaBbLoc; + recovery_meetings: IdaaRecoveryMeetingsLoc; +} + +// ---- Defaults ---------------------------------------------------------------- + +export const idaa_loc_defaults: IdaaLocState = { + novi_uuid: null, + novi_email: null, + novi_full_name: null, + novi_verified: false, + novi_verified_ts: null, + novi_admin_li: [], + novi_trusted_li: [], + novi_jitsi_mod_li: [], + + archives: { + enabled: 'enabled', + hidden: 'not_hidden', + limit: 150, + offset: 0, + edit_kv: {}, + edit__archive_obj: null, + edit__archive_content_obj: null + }, + + bb: { + enabled: 'enabled', + hidden: 'not_hidden', + limit: 50, + offset: 0, + edit_kv: {}, + edit__post_obj: null, + edit__post_comment_obj: null, + show_list__post_obj_li: true, + qry__enabled: 'enabled', + qry__hidden: 'not_hidden', + qry__limit: 25, + qry__offset: 0, + qry__order_by: 'updated_on', + qry__order_by_li: { updated_on: 'DESC', created_on: 'DESC' } + }, + + recovery_meetings: { + edit_kv: {}, + edit__event_obj: null, + qry__enabled: 'enabled', + qry__hidden: 'not_hidden', + qry__limit: 100, + qry__order_by: 'updated_on', + qry__order_by_li: { + priority: 'DESC', + sort: 'DESC', + updated_on: 'DESC', + created_on: 'DESC', + name: 'ASC' + }, + qry__offset: 0, + qry__fulltext_str: null, + qry__physical: null, + qry__type: null, + qry__virtual: null, + qry__favorites_only: false, + ds_info_collapsed: false + } +}; + +// ---- Store ------------------------------------------------------------------- + +// Note: the top-level spread in deserialize ensures new top-level fields get +// their defaults after a browser upgrade. Nested objects (archives, bb, +// recovery_meetings) are replaced wholesale from localStorage — if a new field +// is added to a nested object, it will not auto-populate until the user clears +// their storage. This is the same trade-off as the events sub-stores. +export const idaa_loc = new PersistedState('ae_idaa_loc', idaa_loc_defaults, { + serializer: { + serialize: JSON.stringify, + deserialize: (raw: string) => ({ ...idaa_loc_defaults, ...JSON.parse(raw) }) + } +});