@netless/window-manager 1.0.0-canary.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +21 -0
- package/README.md +90 -64
- package/README.zh-cn.md +224 -0
- package/dist/index.d.ts +1133 -40
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/{index.es.js → index.mjs} +9480 -6984
- package/dist/index.mjs.map +1 -0
- package/dist/style.css +1 -1
- package/docs/advanced.md +55 -55
- package/docs/api.md +124 -113
- package/docs/app-context.md +248 -209
- package/docs/basic.md +25 -26
- package/docs/camera.md +19 -20
- package/docs/cn/advanced.md +137 -0
- package/docs/cn/api.md +309 -0
- package/docs/cn/app-context.md +369 -0
- package/docs/cn/basic.md +64 -0
- package/docs/cn/camera.md +53 -0
- package/docs/cn/concept.md +9 -0
- package/docs/cn/custom-max-bar.md +31 -0
- package/docs/cn/develop-app.md +94 -0
- package/docs/cn/export-pdf.md +48 -0
- package/docs/cn/migrate.md +60 -0
- package/docs/cn/replay.md +40 -0
- package/docs/concept.md +6 -5
- package/docs/custom-max-bar.md +31 -0
- package/docs/develop-app.md +22 -19
- package/docs/export-pdf.md +48 -0
- package/docs/migrate.md +25 -27
- package/docs/quickstart.md +50 -0
- package/docs/replay.md +20 -20
- package/package.json +32 -22
- package/src/App/AppContext.ts +105 -73
- package/src/App/AppPageStateImpl.ts +6 -25
- package/src/App/AppProxy.ts +41 -166
- package/src/App/MagixEvent/index.ts +38 -38
- package/src/App/Storage/StorageEvent.ts +13 -13
- package/src/App/Storage/index.ts +269 -245
- package/src/App/Storage/typings.ts +4 -2
- package/src/App/Storage/utils.ts +3 -3
- package/src/App/index.ts +0 -1
- package/src/AppListener.ts +8 -8
- package/src/AppManager.ts +88 -77
- package/src/AttributesDelegate.ts +42 -22
- package/src/BoxEmitter.ts +12 -6
- package/src/BoxManager.ts +128 -108
- package/src/ContainerResizeObserver.ts +75 -0
- package/src/Cursor/Cursor.svelte +16 -5
- package/src/Cursor/Cursor.svelte.d.ts +21 -0
- package/src/Cursor/Cursor.ts +77 -13
- package/src/Cursor/icons.ts +6 -0
- package/src/Cursor/icons2.ts +66 -0
- package/src/Cursor/index.ts +127 -26
- package/src/Helper.ts +94 -14
- package/src/InternalEmitter.ts +2 -7
- package/src/Page/index.ts +1 -1
- package/src/PageState.ts +6 -5
- package/src/ReconnectRefresher.ts +9 -4
- package/src/RedoUndo.ts +3 -3
- package/src/Register/index.ts +22 -17
- package/src/Register/loader.ts +26 -22
- package/src/Register/storage.ts +13 -13
- package/src/Utils/Common.ts +18 -14
- package/src/Utils/Reactive.ts +26 -25
- package/src/Utils/RoomHacker.ts +4 -4
- package/src/Utils/error.ts +0 -1
- package/src/View/IframeBridge.ts +680 -0
- package/src/View/MainView.ts +127 -53
- package/src/callback.ts +21 -1
- package/src/constants.ts +0 -2
- package/src/image/pencil-eraser-1.svg +3 -0
- package/src/image/pencil-eraser-2.svg +3 -0
- package/src/image/pencil-eraser-3.svg +3 -0
- package/src/index.ts +220 -83
- package/src/style.css +27 -10
- package/src/typings.ts +20 -10
- package/.prettierignore +0 -7
- package/.prettierrc.json +0 -9
- package/CHANGELOG.md +0 -196
- package/__mocks__/white-web-sdk.ts +0 -50
- package/dist/App/AppContext.d.ts +0 -76
- package/dist/App/AppPageStateImpl.d.ts +0 -21
- package/dist/App/AppProxy.d.ts +0 -86
- package/dist/App/AppViewSync.d.ts +0 -11
- package/dist/App/MagixEvent/index.d.ts +0 -29
- package/dist/App/Storage/StorageEvent.d.ts +0 -8
- package/dist/App/Storage/index.d.ts +0 -39
- package/dist/App/Storage/typings.d.ts +0 -22
- package/dist/App/Storage/utils.d.ts +0 -5
- package/dist/App/WhiteboardView.d.ts +0 -22
- package/dist/App/index.d.ts +0 -3
- package/dist/AppListener.d.ts +0 -21
- package/dist/AppManager.d.ts +0 -107
- package/dist/AttributesDelegate.d.ts +0 -80
- package/dist/BoxEmitter.d.ts +0 -34
- package/dist/BoxManager.d.ts +0 -99
- package/dist/BuiltinApps.d.ts +0 -5
- package/dist/Cursor/Cursor.d.ts +0 -39
- package/dist/Cursor/icons.d.ts +0 -3
- package/dist/Cursor/index.d.ts +0 -46
- package/dist/Helper.d.ts +0 -17
- package/dist/InternalEmitter.d.ts +0 -39
- package/dist/Page/PageController.d.ts +0 -21
- package/dist/Page/index.d.ts +0 -3
- package/dist/PageState.d.ts +0 -9
- package/dist/ReconnectRefresher.d.ts +0 -24
- package/dist/RedoUndo.d.ts +0 -18
- package/dist/Register/index.d.ts +0 -28
- package/dist/Register/loader.d.ts +0 -4
- package/dist/Register/storage.d.ts +0 -8
- package/dist/Utils/AppCreateQueue.d.ts +0 -15
- package/dist/Utils/Common.d.ts +0 -23
- package/dist/Utils/Reactive.d.ts +0 -6
- package/dist/Utils/RoomHacker.d.ts +0 -3
- package/dist/Utils/error.d.ts +0 -27
- package/dist/Utils/log.d.ts +0 -1
- package/dist/View/CameraSynchronizer.d.ts +0 -16
- package/dist/View/MainView.d.ts +0 -47
- package/dist/View/ViewManager.d.ts +0 -13
- package/dist/callback.d.ts +0 -24
- package/dist/constants.d.ts +0 -49
- package/dist/index.cjs.js +0 -46
- package/dist/index.umd.js +0 -46
- package/dist/typings.d.ts +0 -82
- package/jest.config.js +0 -27
- package/pnpm-lock.yaml +0 -6302
- package/src/App/AppViewSync.ts +0 -68
- package/src/App/WhiteboardView.ts +0 -83
- package/src/View/CameraSynchronizer.ts +0 -56
- package/vite.config.js +0 -51
- /package/docs/{qickstart.md → cn/quickstart.md} +0 -0
package/src/App/Storage/index.ts
CHANGED
@@ -1,295 +1,319 @@
|
|
1
1
|
import type { AkkoObjectUpdatedProperty } from "white-web-sdk";
|
2
|
-
import { get, has, mapValues, isObject, size, noop } from "lodash";
|
3
|
-
import { SideEffectManager } from "side-effect-manager";
|
4
2
|
import type { AppContext } from "../AppContext";
|
3
|
+
import type {
|
4
|
+
Diff,
|
5
|
+
MaybeRefValue,
|
6
|
+
RefValue,
|
7
|
+
StorageStateChangedEvent,
|
8
|
+
StorageStateChangedListener,
|
9
|
+
StorageStateChangedListenerDisposer,
|
10
|
+
} from "./typings";
|
11
|
+
|
12
|
+
import { get, has, isObject, mapValues, noop, size } from "lodash";
|
13
|
+
import { SideEffectManager } from "side-effect-manager";
|
5
14
|
import { safeListenPropsUpdated } from "../../Utils/Reactive";
|
6
|
-
import { isRef, makeRef, plainObjectKeys } from "./utils";
|
7
|
-
import type { Diff, MaybeRefValue, RefValue, StorageStateChangedEvent, StorageStateChangedListener, StorageStateChangedListenerDisposer } from "./typings";
|
8
15
|
import { StorageEvent } from "./StorageEvent";
|
16
|
+
import { isRef, makeRef, plainObjectKeys } from "./utils";
|
9
17
|
|
10
|
-
export * from
|
18
|
+
export * from "./typings";
|
11
19
|
|
12
20
|
export const STORAGE_NS = "_WM-STORAGE_";
|
13
21
|
|
14
22
|
export class Storage<TState extends Record<string, any> = any> implements Storage<TState> {
|
15
|
-
|
23
|
+
readonly id: string | null;
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
25
|
+
private readonly _context: AppContext;
|
26
|
+
private readonly _sideEffect = new SideEffectManager();
|
27
|
+
private _state: TState;
|
28
|
+
private _destroyed = false;
|
21
29
|
|
22
|
-
|
30
|
+
private _refMap = new WeakMap<any, RefValue>();
|
23
31
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
32
|
+
/**
|
33
|
+
* `setState` alters local state immediately before sending to server. This will cache the old value for onStateChanged diffing.
|
34
|
+
*/
|
35
|
+
private _lastValue = new Map<string | number | symbol, TState[Extract<keyof TState, string>]>();
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
37
|
+
constructor(context: AppContext, id?: string, defaultState?: TState) {
|
38
|
+
if (defaultState && !isObject(defaultState)) {
|
39
|
+
throw new Error(`Default state for Storage ${id} is not an object.`);
|
40
|
+
}
|
33
41
|
|
34
|
-
|
35
|
-
|
42
|
+
this._context = context;
|
43
|
+
this.id = id || null;
|
36
44
|
|
37
|
-
|
38
|
-
|
45
|
+
this._state = {} as TState;
|
46
|
+
const rawState = this._getRawState(this._state);
|
39
47
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
if (this._context.getIsWritable()) {
|
49
|
+
if (this.id === null) {
|
50
|
+
if (context.isAddApp && defaultState) {
|
51
|
+
this.setState(defaultState);
|
52
|
+
}
|
53
|
+
} else {
|
54
|
+
if (rawState === this._state || !isObject(rawState)) {
|
55
|
+
if (!get(this._context.getAttributes(), [STORAGE_NS])) {
|
56
|
+
this._context.updateAttributes([STORAGE_NS], {});
|
57
|
+
}
|
58
|
+
this._context.updateAttributes([STORAGE_NS, this.id], this._state);
|
59
|
+
if (defaultState) {
|
60
|
+
this.setState(defaultState);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
54
64
|
}
|
55
|
-
|
65
|
+
|
66
|
+
// strip mobx
|
67
|
+
plainObjectKeys(rawState).forEach(key => {
|
68
|
+
if (this.id === null && key === STORAGE_NS) {
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
try {
|
72
|
+
const rawValue = isObject(rawState[key])
|
73
|
+
? JSON.parse(JSON.stringify(rawState[key]))
|
74
|
+
: rawState[key];
|
75
|
+
if (isRef<TState[Extract<keyof TState, string>]>(rawValue)) {
|
76
|
+
this._state[key] = rawValue.v;
|
77
|
+
if (isObject(rawValue.v)) {
|
78
|
+
this._refMap.set(rawValue.v, rawValue);
|
79
|
+
}
|
80
|
+
} else {
|
81
|
+
this._state[key] = rawValue;
|
82
|
+
}
|
83
|
+
} catch (e) {
|
84
|
+
console.error(e);
|
85
|
+
}
|
86
|
+
});
|
87
|
+
|
88
|
+
this._sideEffect.addDisposer(
|
89
|
+
safeListenPropsUpdated(
|
90
|
+
() =>
|
91
|
+
this.id === null
|
92
|
+
? context.getAttributes()
|
93
|
+
: get(context.getAttributes(), [STORAGE_NS, this.id]),
|
94
|
+
this._updateProperties.bind(this),
|
95
|
+
this.destroy.bind(this)
|
96
|
+
)
|
97
|
+
);
|
56
98
|
}
|
57
99
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
return;
|
62
|
-
}
|
63
|
-
try {
|
64
|
-
const rawValue = isObject(rawState[key]) ? JSON.parse(JSON.stringify(rawState[key])) : rawState[key];
|
65
|
-
if (isRef<TState[Extract<keyof TState, string>]>(rawValue)) {
|
66
|
-
this._state[key] = rawValue.v;
|
67
|
-
if (isObject(rawValue.v)) {
|
68
|
-
this._refMap.set(rawValue.v, rawValue);
|
69
|
-
}
|
70
|
-
} else {
|
71
|
-
this._state[key] = rawValue;
|
100
|
+
get state(): Readonly<TState> {
|
101
|
+
if (this._destroyed) {
|
102
|
+
console.warn(`Accessing state on destroyed Storage "${this.id}"`);
|
72
103
|
}
|
73
|
-
|
74
|
-
console.error(e);
|
75
|
-
}
|
76
|
-
});
|
77
|
-
|
78
|
-
this._sideEffect.addDisposer(
|
79
|
-
safeListenPropsUpdated(
|
80
|
-
() => this.id === null ? context.getAttributes() : get(context.getAttributes(), [STORAGE_NS, this.id]),
|
81
|
-
this._updateProperties.bind(this),
|
82
|
-
this.destroy.bind(this)
|
83
|
-
)
|
84
|
-
);
|
85
|
-
}
|
86
|
-
|
87
|
-
get state(): Readonly<TState> {
|
88
|
-
if (this._destroyed) {
|
89
|
-
console.warn(`Accessing state on destroyed Storage "${this.id}"`)
|
104
|
+
return this._state;
|
90
105
|
}
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
}
|
100
|
-
|
101
|
-
ensureState(state: Partial<TState>): void {
|
102
|
-
return this.setState(
|
103
|
-
plainObjectKeys(state).reduce((payload, key) => {
|
104
|
-
if (!has(this._state, key)) {
|
105
|
-
payload[key] = state[key];
|
106
|
-
}
|
107
|
-
return payload;
|
108
|
-
}, {} as Partial<TState>)
|
109
|
-
);
|
110
|
-
}
|
111
|
-
|
112
|
-
setState(state: Partial<TState>): void {
|
113
|
-
if (this._destroyed) {
|
114
|
-
console.error(new Error(`Cannot call setState on destroyed Storage "${this.id}".`));
|
115
|
-
return;
|
106
|
+
|
107
|
+
readonly onStateChanged = new StorageEvent<StorageStateChangedEvent<TState>>();
|
108
|
+
|
109
|
+
addStateChangedListener(
|
110
|
+
handler: StorageStateChangedListener<TState>
|
111
|
+
): StorageStateChangedListenerDisposer {
|
112
|
+
this.onStateChanged.addListener(handler);
|
113
|
+
return () => this.onStateChanged.removeListener(handler);
|
116
114
|
}
|
117
115
|
|
118
|
-
|
119
|
-
|
120
|
-
|
116
|
+
ensureState(state: Partial<TState>): void {
|
117
|
+
return this.setState(
|
118
|
+
plainObjectKeys(state).reduce((payload, key) => {
|
119
|
+
if (!has(this._state, key)) {
|
120
|
+
payload[key] = state[key];
|
121
|
+
}
|
122
|
+
return payload;
|
123
|
+
}, {} as Partial<TState>)
|
124
|
+
);
|
121
125
|
}
|
122
126
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
if (value === this._state[key]) {
|
128
|
-
return;
|
127
|
+
setState(state: Partial<TState>): void {
|
128
|
+
if (this._destroyed) {
|
129
|
+
console.error(new Error(`Cannot call setState on destroyed Storage "${this.id}".`));
|
130
|
+
return;
|
129
131
|
}
|
130
132
|
|
131
|
-
if (
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
payload = refValue;
|
147
|
-
}
|
133
|
+
if (!this._context.getIsWritable()) {
|
134
|
+
console.error(
|
135
|
+
new Error(`Cannot setState on Storage "${this.id}" without writable access`),
|
136
|
+
state
|
137
|
+
);
|
138
|
+
return;
|
139
|
+
}
|
140
|
+
|
141
|
+
const keys = plainObjectKeys(state);
|
142
|
+
if (keys.length > 0) {
|
143
|
+
keys.forEach(key => {
|
144
|
+
const value = state[key];
|
145
|
+
if (value === this._state[key]) {
|
146
|
+
return;
|
147
|
+
}
|
148
148
|
|
149
|
-
|
149
|
+
if (value === void 0) {
|
150
|
+
this._lastValue.set(key, this._state[key]);
|
151
|
+
delete this._state[key];
|
152
|
+
this._setRawState(key, value);
|
153
|
+
} else {
|
154
|
+
this._lastValue.set(key, this._state[key]);
|
155
|
+
this._state[key] = value as TState[Extract<keyof TState, string>];
|
156
|
+
|
157
|
+
let payload: MaybeRefValue<typeof value> = value;
|
158
|
+
if (isObject(value)) {
|
159
|
+
let refValue = this._refMap.get(value);
|
160
|
+
if (!refValue) {
|
161
|
+
refValue = makeRef(value);
|
162
|
+
this._refMap.set(value, refValue);
|
163
|
+
}
|
164
|
+
payload = refValue;
|
165
|
+
}
|
166
|
+
|
167
|
+
this._setRawState(key, payload);
|
168
|
+
}
|
169
|
+
});
|
150
170
|
}
|
151
|
-
});
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
155
|
-
/**
|
156
|
-
* Empty storage data.
|
157
|
-
*/
|
158
|
-
emptyStorage(): void {
|
159
|
-
if (size(this._state) <= 0) {
|
160
|
-
return;
|
161
171
|
}
|
162
172
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
173
|
+
/**
|
174
|
+
* Empty storage data.
|
175
|
+
*/
|
176
|
+
emptyStorage(): void {
|
177
|
+
if (size(this._state) <= 0) {
|
178
|
+
return;
|
179
|
+
}
|
167
180
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
181
|
+
if (this._destroyed) {
|
182
|
+
console.error(new Error(`Cannot empty destroyed Storage "${this.id}".`));
|
183
|
+
return;
|
184
|
+
}
|
172
185
|
|
173
|
-
|
174
|
-
|
186
|
+
if (!this._context.getIsWritable()) {
|
187
|
+
console.error(new Error(`Cannot empty Storage "${this.id}" without writable access.`));
|
188
|
+
return;
|
189
|
+
}
|
175
190
|
|
176
|
-
|
177
|
-
* Delete storage index with all of its data and destroy the Storage instance.
|
178
|
-
*/
|
179
|
-
deleteStorage(): void {
|
180
|
-
if (this.id === null) {
|
181
|
-
throw new Error(`Cannot delete main Storage`);
|
191
|
+
this.setState(mapValues(this._state, noop as () => undefined));
|
182
192
|
}
|
183
193
|
|
184
|
-
|
185
|
-
|
186
|
-
|
194
|
+
/**
|
195
|
+
* Delete storage index with all of its data and destroy the Storage instance.
|
196
|
+
*/
|
197
|
+
deleteStorage(): void {
|
198
|
+
if (this.id === null) {
|
199
|
+
throw new Error(`Cannot delete main Storage`);
|
200
|
+
}
|
201
|
+
|
202
|
+
if (!this._context.getIsWritable()) {
|
203
|
+
console.error(new Error(`Cannot delete Storage "${this.id}" without writable access.`));
|
204
|
+
return;
|
205
|
+
}
|
206
|
+
|
207
|
+
this.destroy();
|
208
|
+
|
209
|
+
this._context.updateAttributes([STORAGE_NS, this.id], void 0);
|
187
210
|
}
|
188
211
|
|
189
|
-
|
190
|
-
|
191
|
-
this._context.updateAttributes([STORAGE_NS, this.id], void 0);
|
192
|
-
}
|
193
|
-
|
194
|
-
get destroyed(): boolean {
|
195
|
-
return this._destroyed;
|
196
|
-
}
|
197
|
-
|
198
|
-
/**
|
199
|
-
* Destroy the Storage instance. The data will be kept.
|
200
|
-
*/
|
201
|
-
destroy() {
|
202
|
-
this._destroyed = true;
|
203
|
-
this._sideEffect.flushAll();
|
204
|
-
}
|
205
|
-
|
206
|
-
private _getRawState(): TState | undefined
|
207
|
-
private _getRawState(defaultValue: TState): TState
|
208
|
-
private _getRawState(defaultValue?: TState): TState | undefined {
|
209
|
-
if (this.id === null) {
|
210
|
-
return this._context.getAttributes() ?? defaultValue;
|
211
|
-
} else {
|
212
|
-
return get(this._context.getAttributes(), [STORAGE_NS, this.id], defaultValue);
|
212
|
+
get destroyed(): boolean {
|
213
|
+
return this._destroyed;
|
213
214
|
}
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
return this._context.updateAttributes([key], value);
|
222
|
-
} else {
|
223
|
-
return this._context.updateAttributes([STORAGE_NS, this.id, key], value);
|
215
|
+
|
216
|
+
/**
|
217
|
+
* Destroy the Storage instance. The data will be kept.
|
218
|
+
*/
|
219
|
+
destroy() {
|
220
|
+
this._destroyed = true;
|
221
|
+
this._sideEffect.flushAll();
|
224
222
|
}
|
225
|
-
}
|
226
223
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
224
|
+
private _getRawState(): TState | undefined;
|
225
|
+
private _getRawState(defaultValue: TState): TState;
|
226
|
+
private _getRawState(defaultValue?: TState): TState | undefined {
|
227
|
+
if (this.id === null) {
|
228
|
+
return this._context.getAttributes() ?? defaultValue;
|
229
|
+
} else {
|
230
|
+
return get(this._context.getAttributes(), [STORAGE_NS, this.id], defaultValue);
|
231
|
+
}
|
231
232
|
}
|
232
233
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
try {
|
238
|
-
const action = actions[i]
|
239
|
-
const key = action.key as Extract<keyof TState, string>;
|
240
|
-
|
241
|
-
if (this.id === null && key === STORAGE_NS) {
|
242
|
-
continue
|
243
|
-
}
|
244
|
-
|
245
|
-
const value = isObject(action.value) ? JSON.parse(JSON.stringify(action.value)) : action.value;
|
246
|
-
let oldValue: TState[Extract<keyof TState, string>] | undefined;
|
247
|
-
if (this._lastValue.has(key)) {
|
248
|
-
oldValue = this._lastValue.get(key);
|
249
|
-
this._lastValue.delete(key);
|
250
|
-
}
|
251
|
-
|
252
|
-
switch (action.kind) {
|
253
|
-
case 2: {
|
254
|
-
// Removed
|
255
|
-
if (has(this._state, key)) {
|
256
|
-
oldValue = this._state[key];
|
257
|
-
delete this._state[key];
|
258
|
-
}
|
259
|
-
diffs[key] = { oldValue };
|
260
|
-
break;
|
234
|
+
private _setRawState(key: string, value: any): void {
|
235
|
+
if (this.id === null) {
|
236
|
+
if (key === STORAGE_NS) {
|
237
|
+
throw new Error(`Cannot set attribute internal filed "${STORAGE_NS}"`);
|
261
238
|
}
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
const curValue = this._state[key];
|
268
|
-
if (isObject(curValue) && this._refMap.get(curValue)?.k === k) {
|
269
|
-
newValue = curValue;
|
270
|
-
} else {
|
271
|
-
newValue = v;
|
272
|
-
if (isObject(v)) {
|
273
|
-
this._refMap.set(v, value);
|
274
|
-
}
|
275
|
-
}
|
276
|
-
}
|
239
|
+
return this._context.updateAttributes([key], value);
|
240
|
+
} else {
|
241
|
+
return this._context.updateAttributes([STORAGE_NS, this.id, key], value);
|
242
|
+
}
|
243
|
+
}
|
277
244
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
245
|
+
private _updateProperties(
|
246
|
+
actions: ReadonlyArray<AkkoObjectUpdatedProperty<TState, string>>
|
247
|
+
): void {
|
248
|
+
if (this._destroyed) {
|
249
|
+
console.error(
|
250
|
+
new Error(`Cannot call _updateProperties on destroyed Storage "${this.id}".`)
|
251
|
+
);
|
252
|
+
return;
|
253
|
+
}
|
282
254
|
|
283
|
-
|
284
|
-
|
255
|
+
if (actions.length > 0) {
|
256
|
+
const diffs: Diff<TState> = {};
|
257
|
+
|
258
|
+
for (let i = 0; i < actions.length; i++) {
|
259
|
+
try {
|
260
|
+
const action = actions[i];
|
261
|
+
const key = action.key as Extract<keyof TState, string>;
|
262
|
+
|
263
|
+
if (this.id === null && key === STORAGE_NS) {
|
264
|
+
continue;
|
265
|
+
}
|
266
|
+
|
267
|
+
const value = isObject(action.value)
|
268
|
+
? JSON.parse(JSON.stringify(action.value))
|
269
|
+
: action.value;
|
270
|
+
let oldValue: TState[Extract<keyof TState, string>] | undefined;
|
271
|
+
if (this._lastValue.has(key)) {
|
272
|
+
oldValue = this._lastValue.get(key);
|
273
|
+
this._lastValue.delete(key);
|
274
|
+
}
|
275
|
+
|
276
|
+
switch (action.kind) {
|
277
|
+
case 2: {
|
278
|
+
// Removed
|
279
|
+
if (has(this._state, key)) {
|
280
|
+
oldValue = this._state[key];
|
281
|
+
delete this._state[key];
|
282
|
+
}
|
283
|
+
diffs[key] = { oldValue };
|
284
|
+
break;
|
285
|
+
}
|
286
|
+
default: {
|
287
|
+
let newValue = value;
|
288
|
+
|
289
|
+
if (isRef<TState[Extract<keyof TState, string>]>(value)) {
|
290
|
+
const { k, v } = value;
|
291
|
+
const curValue = this._state[key];
|
292
|
+
if (isObject(curValue) && this._refMap.get(curValue)?.k === k) {
|
293
|
+
newValue = curValue;
|
294
|
+
} else {
|
295
|
+
newValue = v;
|
296
|
+
if (isObject(v)) {
|
297
|
+
this._refMap.set(v, value);
|
298
|
+
}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
if (newValue !== this._state[key]) {
|
303
|
+
oldValue = this._state[key];
|
304
|
+
this._state[key] = newValue;
|
305
|
+
}
|
306
|
+
|
307
|
+
diffs[key] = { newValue, oldValue };
|
308
|
+
break;
|
309
|
+
}
|
310
|
+
}
|
311
|
+
} catch (e) {
|
312
|
+
console.error(e);
|
313
|
+
}
|
285
314
|
}
|
286
|
-
}
|
287
|
-
} catch (e) {
|
288
|
-
console.error(e)
|
289
|
-
}
|
290
|
-
}
|
291
315
|
|
292
|
-
|
316
|
+
this.onStateChanged.dispatch(diffs);
|
317
|
+
}
|
293
318
|
}
|
294
|
-
}
|
295
319
|
}
|
@@ -13,11 +13,13 @@ export type DiffOne<T> = { oldValue?: T; newValue?: T };
|
|
13
13
|
export type Diff<T> = { [K in keyof T]?: DiffOne<T[K]> };
|
14
14
|
|
15
15
|
export type StorageOnSetStatePayload<TState = unknown> = {
|
16
|
-
|
16
|
+
[K in keyof TState]?: MaybeRefValue<TState[K]>;
|
17
17
|
};
|
18
18
|
|
19
19
|
export type StorageStateChangedEvent<TState = any> = Diff<TState>;
|
20
20
|
|
21
|
-
export type StorageStateChangedListener<TState = any> = StorageEventListener<
|
21
|
+
export type StorageStateChangedListener<TState = any> = StorageEventListener<
|
22
|
+
StorageStateChangedEvent<TState>
|
23
|
+
>;
|
22
24
|
|
23
25
|
export type StorageStateChangedListenerDisposer = () => void;
|
package/src/App/Storage/utils.ts
CHANGED
@@ -5,13 +5,13 @@ import type { AutoRefValue, ExtractRawValue, RefValue } from "./typings";
|
|
5
5
|
export const plainObjectKeys = Object.keys as <T>(o: T) => Array<Extract<keyof T, string>>;
|
6
6
|
|
7
7
|
export function isRef<TValue = unknown>(e: unknown): e is RefValue<TValue> {
|
8
|
-
|
8
|
+
return Boolean(has(e, "__isRef"));
|
9
9
|
}
|
10
10
|
|
11
11
|
export function makeRef<TValue>(v: TValue): RefValue<TValue> {
|
12
|
-
|
12
|
+
return { k: genUID(), v, __isRef: true };
|
13
13
|
}
|
14
14
|
|
15
15
|
export function makeAutoRef<TValue>(v: TValue): AutoRefValue<TValue> {
|
16
|
-
|
16
|
+
return isRef<ExtractRawValue<TValue>>(v) ? v : makeRef(v as ExtractRawValue<TValue>);
|
17
17
|
}
|
package/src/App/index.ts
CHANGED
package/src/AppListener.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { callbacks } from "./callback";
|
2
|
-
import {
|
2
|
+
import { internalEmitter } from "./InternalEmitter";
|
3
3
|
import { Events, MagixEventName } from "./constants";
|
4
4
|
import { isEqual, omit } from "lodash";
|
5
5
|
import { setViewFocusScenePath } from "./Utils/Common";
|
@@ -11,7 +11,7 @@ type SetAppFocusIndex = {
|
|
11
11
|
type: "main" | "app";
|
12
12
|
appID?: string;
|
13
13
|
index: number;
|
14
|
-
}
|
14
|
+
};
|
15
15
|
|
16
16
|
export class AppListeners {
|
17
17
|
private displayer = this.manager.displayer;
|
@@ -114,22 +114,22 @@ export class AppListeners {
|
|
114
114
|
};
|
115
115
|
|
116
116
|
private cursorMoveHandler = (payload: any) => {
|
117
|
-
|
117
|
+
internalEmitter.emit("cursorMove", payload);
|
118
118
|
};
|
119
119
|
|
120
120
|
private rootDirRemovedHandler = () => {
|
121
121
|
this.manager.createRootDirScenesCallback();
|
122
122
|
this.manager.mainViewProxy.rebind();
|
123
|
-
|
124
|
-
}
|
123
|
+
internalEmitter.emit("rootDirRemoved");
|
124
|
+
};
|
125
125
|
|
126
126
|
private refreshHandler = () => {
|
127
127
|
this.manager.windowManger._refresh();
|
128
|
-
}
|
128
|
+
};
|
129
129
|
|
130
130
|
private initMainViewCameraHandler = () => {
|
131
131
|
this.manager.mainViewProxy.addCameraReaction();
|
132
|
-
}
|
132
|
+
};
|
133
133
|
|
134
134
|
private setAppFocusViewIndexHandler = (payload: SetAppFocusIndex) => {
|
135
135
|
if (payload.type === "main") {
|
@@ -140,5 +140,5 @@ export class AppListeners {
|
|
140
140
|
app.setSceneIndexWithoutSync(payload.index);
|
141
141
|
}
|
142
142
|
}
|
143
|
-
}
|
143
|
+
};
|
144
144
|
}
|