@@ -21,64 +21,76 @@ import SettingsHandler from "./SettingsHandler";
2121 * by caching the values and listening for localStorage updates from other tabs.
2222 */
2323export default abstract class AbstractLocalStorageSettingsHandler extends SettingsHandler {
24- private itemCache = new Map < string , any > ( ) ;
25- private objectCache = new Map < string , object > ( ) ;
24+ // Shared cache between all subclass instances
25+ private static itemCache = new Map < string , any > ( ) ;
26+ private static objectCache = new Map < string , object > ( ) ;
27+ private static storageListenerBound = false ;
28+
29+ private static onStorageEvent = ( e : StorageEvent ) => {
30+ if ( e . key === null ) {
31+ AbstractLocalStorageSettingsHandler . clear ( ) ;
32+ } else {
33+ AbstractLocalStorageSettingsHandler . itemCache . delete ( e . key ) ;
34+ AbstractLocalStorageSettingsHandler . objectCache . delete ( e . key ) ;
35+ }
36+ } ;
37+
38+ // Expose the clear event for Lifecycle to call, the storage listener only fires for changes from other tabs
39+ public static clear ( ) {
40+ AbstractLocalStorageSettingsHandler . itemCache . clear ( ) ;
41+ AbstractLocalStorageSettingsHandler . objectCache . clear ( ) ;
42+ }
2643
2744 protected constructor ( ) {
2845 super ( ) ;
2946
30- // Listen for storage changes from other tabs to bust the cache
31- window . addEventListener ( "storage" , ( e : StorageEvent ) => {
32- if ( e . key === null ) {
33- this . itemCache . clear ( ) ;
34- this . objectCache . clear ( ) ;
35- } else {
36- this . itemCache . delete ( e . key ) ;
37- this . objectCache . delete ( e . key ) ;
38- }
39- } ) ;
47+ if ( ! AbstractLocalStorageSettingsHandler . storageListenerBound ) {
48+ AbstractLocalStorageSettingsHandler . storageListenerBound = true ;
49+ // Listen for storage changes from other tabs to bust the cache
50+ window . addEventListener ( "storage" , AbstractLocalStorageSettingsHandler . onStorageEvent ) ;
51+ }
4052 }
4153
4254 protected getItem ( key : string ) : any {
43- if ( ! this . itemCache . has ( key ) ) {
55+ if ( ! AbstractLocalStorageSettingsHandler . itemCache . has ( key ) ) {
4456 const value = localStorage . getItem ( key ) ;
45- this . itemCache . set ( key , value ) ;
57+ AbstractLocalStorageSettingsHandler . itemCache . set ( key , value ) ;
4658 return value ;
4759 }
4860
49- return this . itemCache . get ( key ) ;
61+ return AbstractLocalStorageSettingsHandler . itemCache . get ( key ) ;
5062 }
5163
5264 protected getObject < T extends object > ( key : string ) : T | null {
53- if ( ! this . objectCache . has ( key ) ) {
65+ if ( ! AbstractLocalStorageSettingsHandler . objectCache . has ( key ) ) {
5466 try {
5567 const value = JSON . parse ( localStorage . getItem ( key ) ) ;
56- this . objectCache . set ( key , value ) ;
68+ AbstractLocalStorageSettingsHandler . objectCache . set ( key , value ) ;
5769 return value ;
5870 } catch ( err ) {
5971 console . error ( "Failed to parse localStorage object" , err ) ;
6072 return null ;
6173 }
6274 }
6375
64- return this . objectCache . get ( key ) as T ;
76+ return AbstractLocalStorageSettingsHandler . objectCache . get ( key ) as T ;
6577 }
6678
6779 protected setItem ( key : string , value : any ) : void {
68- this . itemCache . set ( key , value ) ;
80+ AbstractLocalStorageSettingsHandler . itemCache . set ( key , value ) ;
6981 localStorage . setItem ( key , value ) ;
7082 }
7183
7284 protected setObject ( key : string , value : object ) : void {
73- this . objectCache . set ( key , value ) ;
85+ AbstractLocalStorageSettingsHandler . objectCache . set ( key , value ) ;
7486 localStorage . setItem ( key , JSON . stringify ( value ) ) ;
7587 }
7688
7789 // handles both items and objects
7890 protected removeItem ( key : string ) : void {
7991 localStorage . removeItem ( key ) ;
80- this . itemCache . delete ( key ) ;
81- this . objectCache . delete ( key ) ;
92+ AbstractLocalStorageSettingsHandler . itemCache . delete ( key ) ;
93+ AbstractLocalStorageSettingsHandler . objectCache . delete ( key ) ;
8294 }
8395
8496 public isSupported ( ) : boolean {
0 commit comments