forked from cerebral/overmind
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTrackStateTree.ts
More file actions
112 lines (99 loc) · 2.38 KB
/
TrackStateTree.ts
File metadata and controls
112 lines (99 loc) · 2.38 KB
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import {
IProxyStateTree,
ITrackStateTree,
ITrackCallback,
IProxifier,
ITrackScopedCallback,
} from './types'
export class TrackStateTree<T extends object> implements ITrackStateTree<T> {
master: IProxyStateTree<T>
pathDependencies: Set<string> = new Set()
callback: ITrackCallback
shouldTrack: boolean = false
state: T
proxifier: IProxifier<T>
trackPathListeners: Array<(path: string) => void> = []
constructor(master: IProxyStateTree<T>) {
this.master = master
this.proxifier = master.proxifier
this.state = master.state
}
trackPaths() {
const paths = new Set<string>()
const listener = (path) => {
paths.add(path)
}
this.trackPathListeners.push(listener)
return () => {
this.trackPathListeners.splice(
this.trackPathListeners.indexOf(listener),
1
)
return paths
}
}
canMutate() {
return false
}
canTrack() {
return true
}
addTrackingPath(path: string) {
if (!this.shouldTrack) {
return
}
this.pathDependencies.add(path)
if (this.callback) {
this.master.addPathDependency(path, this.callback)
}
}
track(cb?: ITrackCallback) {
this.master.changeTrackStateTree(this)
this.shouldTrack = true
this.clearTracking()
if (cb) {
this.callback = (...args) => {
if (!this.callback) {
return
}
cb(...args)
}
}
return this
}
clearTracking() {
if (this.callback) {
for (let path of this.pathDependencies) {
this.master.removePathDependency(path, this.callback)
}
}
this.pathDependencies.clear()
}
stopTracking() {
this.shouldTrack = false
}
trackScope(scope: ITrackScopedCallback<T>, cb?: ITrackCallback) {
const previousPreviousTree = this.master.previousTree
const previousCurrentTree = this.master.currentTree
this.master.currentTree = this
this.track(cb)
const result = scope(this)
this.master.currentTree = previousCurrentTree
this.master.previousTree = previousPreviousTree
this.stopTracking()
return result
}
dispose() {
if (!this.callback) {
this.pathDependencies.clear()
return this
}
this.clearTracking()
this.callback = null
this.proxifier = this.master.proxifier
if (this.master.currentTree === this) {
this.master.currentTree = null
}
return this
}
}