-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstate.js
98 lines (85 loc) · 3.01 KB
/
state.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
export class State extends EventTarget { // implements EventTarget (partially anyways) https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
static stateKey = 'state'
static statePrefix = 'state.'
constructor() {
super()
this.loadState()
window.addEventListener('storage', (e) => {
if (e.key.startsWith(State.statePrefix)) {
// console.log("storage event", e)
let key = e.key.substring(State.statePrefix.length)
let value = null
if (e.newValue) {
value = JSON.parse(e.newValue)
}
this.dispatchEvent(new CustomEvent(key, {
detail: {
action: value ? 'set' : 'delete',
key: key,
value: value,
},
}))
}
})
}
loadState() {
// NOTE: I may drop the 'state' object from local storage and just use individual keys, better for event handling.
const storedState = window.localStorage.getItem(State.stateKey)
if (!storedState) {
this.stateMap = new Map()
return null
}
// console.log("storedState:", storedState)
let state = null
try {
state = JSON.parse(storedState)
// console.log("storedState:", state)
} catch (err) {
console.error("error parsing stored state:", err)
}
this.stateMap = new Map(Object.entries(state))
// the alternative way using individual keys
for (let key in window.localStorage) {
if (key.startsWith(State.statePrefix)) {
let value = window.localStorage.getItem(key)
value = JSON.parse(value)
this.stateMap.set(key, value)
}
}
return state
}
saveState() {
// can probably ditch this whole state object now that we're using individual keys
window.localStorage.setItem(State.stateKey, JSON.stringify(Object.fromEntries(this.stateMap)))
}
set(key, value) {
let m = this.stateMap.set(key, value)
window.localStorage.setItem(`${State.statePrefix}${key}`, JSON.stringify(value))
this.saveState()
this.dispatchEvent(new CustomEvent(key, {
detail: {
action: 'set',
key,
value,
},
}))
return m
}
delete(key) {
let r = this.stateMap.delete(key)
window.localStorage.removeItem(`${State.statePrefix}${key}`)
this.saveState()
this.dispatchEvent(new CustomEvent(key, {
detail: {
action: 'delete',
key,
deleted: r, // true if element existed and was removed, or false if the element did not exist.
},
}))
}
get(key) {
return this.stateMap.get(key)
}
}
export const state = new State()
export default state