From 7fa5563054e53d3bfd69e62df808fcbf27346dc0 Mon Sep 17 00:00:00 2001 From: MareStare Date: Tue, 4 Mar 2025 03:52:32 +0000 Subject: [PATCH] Emit `'storage-update'` events on local storage update --- assets/js/utils/store.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/assets/js/utils/store.ts b/assets/js/utils/store.ts index d4b8579d..2abad439 100644 --- a/assets/js/utils/store.ts +++ b/assets/js/utils/store.ts @@ -4,10 +4,18 @@ export const lastUpdatedSuffix = '__lastUpdated'; +// We use this detached
element purely as an event bus to dispatch storage update +// events. It is needed because the default 'stroge' event dispatched on the window +// isn't triggered when the same page updates the storage. +const localUpdates = document.createElement('div'); + +type StorageUpdateEvent = CustomEvent; + export default { set(key: string, value: unknown) { try { localStorage.setItem(key, JSON.stringify(value)); + this.dispatchStorageUpdateEvent(key); return true; } catch { return false; @@ -27,12 +35,18 @@ export default { remove(key: string) { try { localStorage.removeItem(key); + this.dispatchStorageUpdateEvent(key); return true; } catch { return false; } }, + dispatchStorageUpdateEvent(key: string) { + const event: StorageUpdateEvent = new CustomEvent('storage-update', { detail: key }); + localUpdates.dispatchEvent(event); + }, + // Watch changes to a specified key - returns value on change watch(key: string, callback: (value: Value | null) => void) { const handler = (event: StorageEvent) => { @@ -42,6 +56,12 @@ export default { return () => window.removeEventListener('storage', handler); }, + // `null` key means the store was purged with `localStorage.clear()` + watchAll(callback: (key: null | string) => void) { + window.addEventListener('storage', event => callback(event.key)); + localUpdates.addEventListener('storage-update', event => callback((event as StorageUpdateEvent).detail)); + }, + // set() with an additional key containing the current time + expiration time setWithExpireTime(key: string, value: unknown, maxAge: number) { const lastUpdatedKey = key + lastUpdatedSuffix;