@@ -21,64 +21,76 @@ import SettingsHandler from "./SettingsHandler";
21
21
* by caching the values and listening for localStorage updates from other tabs.
22
22
*/
23
23
export 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
+ }
26
43
27
44
protected constructor ( ) {
28
45
super ( ) ;
29
46
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
+ }
40
52
}
41
53
42
54
protected getItem ( key : string ) : any {
43
- if ( ! this . itemCache . has ( key ) ) {
55
+ if ( ! AbstractLocalStorageSettingsHandler . itemCache . has ( key ) ) {
44
56
const value = localStorage . getItem ( key ) ;
45
- this . itemCache . set ( key , value ) ;
57
+ AbstractLocalStorageSettingsHandler . itemCache . set ( key , value ) ;
46
58
return value ;
47
59
}
48
60
49
- return this . itemCache . get ( key ) ;
61
+ return AbstractLocalStorageSettingsHandler . itemCache . get ( key ) ;
50
62
}
51
63
52
64
protected getObject < T extends object > ( key : string ) : T | null {
53
- if ( ! this . objectCache . has ( key ) ) {
65
+ if ( ! AbstractLocalStorageSettingsHandler . objectCache . has ( key ) ) {
54
66
try {
55
67
const value = JSON . parse ( localStorage . getItem ( key ) ) ;
56
- this . objectCache . set ( key , value ) ;
68
+ AbstractLocalStorageSettingsHandler . objectCache . set ( key , value ) ;
57
69
return value ;
58
70
} catch ( err ) {
59
71
console . error ( "Failed to parse localStorage object" , err ) ;
60
72
return null ;
61
73
}
62
74
}
63
75
64
- return this . objectCache . get ( key ) as T ;
76
+ return AbstractLocalStorageSettingsHandler . objectCache . get ( key ) as T ;
65
77
}
66
78
67
79
protected setItem ( key : string , value : any ) : void {
68
- this . itemCache . set ( key , value ) ;
80
+ AbstractLocalStorageSettingsHandler . itemCache . set ( key , value ) ;
69
81
localStorage . setItem ( key , value ) ;
70
82
}
71
83
72
84
protected setObject ( key : string , value : object ) : void {
73
- this . objectCache . set ( key , value ) ;
85
+ AbstractLocalStorageSettingsHandler . objectCache . set ( key , value ) ;
74
86
localStorage . setItem ( key , JSON . stringify ( value ) ) ;
75
87
}
76
88
77
89
// handles both items and objects
78
90
protected removeItem ( key : string ) : void {
79
91
localStorage . removeItem ( key ) ;
80
- this . itemCache . delete ( key ) ;
81
- this . objectCache . delete ( key ) ;
92
+ AbstractLocalStorageSettingsHandler . itemCache . delete ( key ) ;
93
+ AbstractLocalStorageSettingsHandler . objectCache . delete ( key ) ;
82
94
}
83
95
84
96
public isSupported ( ) : boolean {
0 commit comments