@netless/window-manager 1.0.0-canary.9 → 1.0.1

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.
Files changed (132) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +90 -64
  3. package/README.zh-cn.md +224 -0
  4. package/dist/index.d.ts +1133 -40
  5. package/dist/index.js +62 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/{index.es.js → index.mjs} +7954 -5445
  8. package/dist/index.mjs.map +1 -0
  9. package/dist/style.css +1 -1
  10. package/docs/advanced.md +55 -55
  11. package/docs/api.md +126 -113
  12. package/docs/app-context.md +248 -209
  13. package/docs/basic.md +25 -26
  14. package/docs/camera.md +21 -21
  15. package/docs/cn/advanced.md +137 -0
  16. package/docs/cn/api.md +311 -0
  17. package/docs/cn/app-context.md +369 -0
  18. package/docs/cn/basic.md +64 -0
  19. package/docs/cn/camera.md +53 -0
  20. package/docs/cn/concept.md +9 -0
  21. package/docs/cn/custom-max-bar.md +31 -0
  22. package/docs/cn/develop-app.md +94 -0
  23. package/docs/cn/export-pdf.md +48 -0
  24. package/docs/cn/migrate.md +60 -0
  25. package/docs/cn/replay.md +40 -0
  26. package/docs/concept.md +6 -5
  27. package/docs/custom-max-bar.md +31 -0
  28. package/docs/develop-app.md +22 -19
  29. package/docs/export-pdf.md +48 -0
  30. package/docs/migrate.md +25 -27
  31. package/docs/quickstart.md +50 -0
  32. package/docs/replay.md +20 -20
  33. package/package.json +32 -22
  34. package/src/App/AppContext.ts +105 -73
  35. package/src/App/AppPageStateImpl.ts +6 -25
  36. package/src/App/AppProxy.ts +41 -166
  37. package/src/App/MagixEvent/index.ts +38 -38
  38. package/src/App/Storage/StorageEvent.ts +13 -13
  39. package/src/App/Storage/index.ts +269 -245
  40. package/src/App/Storage/typings.ts +4 -2
  41. package/src/App/Storage/utils.ts +3 -3
  42. package/src/App/index.ts +0 -1
  43. package/src/AppListener.ts +8 -8
  44. package/src/AppManager.ts +88 -77
  45. package/src/AttributesDelegate.ts +42 -22
  46. package/src/BoxEmitter.ts +12 -6
  47. package/src/BoxManager.ts +128 -108
  48. package/src/ContainerResizeObserver.ts +75 -0
  49. package/src/Cursor/Cursor.svelte +16 -5
  50. package/src/Cursor/Cursor.svelte.d.ts +21 -0
  51. package/src/Cursor/Cursor.ts +77 -13
  52. package/src/Cursor/icons.ts +6 -0
  53. package/src/Cursor/icons2.ts +66 -0
  54. package/src/Cursor/index.ts +127 -26
  55. package/src/Helper.ts +94 -14
  56. package/src/InternalEmitter.ts +2 -7
  57. package/src/Page/index.ts +1 -1
  58. package/src/PageState.ts +6 -5
  59. package/src/ReconnectRefresher.ts +9 -4
  60. package/src/RedoUndo.ts +3 -3
  61. package/src/Register/index.ts +22 -17
  62. package/src/Register/loader.ts +26 -22
  63. package/src/Register/storage.ts +13 -13
  64. package/src/Utils/Common.ts +18 -14
  65. package/src/Utils/Reactive.ts +26 -25
  66. package/src/Utils/RoomHacker.ts +4 -4
  67. package/src/Utils/error.ts +0 -1
  68. package/src/View/IframeBridge.ts +680 -0
  69. package/src/View/MainView.ts +127 -53
  70. package/src/callback.ts +21 -1
  71. package/src/constants.ts +0 -2
  72. package/src/image/pencil-eraser-1.svg +3 -0
  73. package/src/image/pencil-eraser-2.svg +3 -0
  74. package/src/image/pencil-eraser-3.svg +3 -0
  75. package/src/index.ts +220 -83
  76. package/src/style.css +27 -10
  77. package/src/typings.ts +20 -10
  78. package/.prettierignore +0 -7
  79. package/.prettierrc.json +0 -9
  80. package/CHANGELOG.md +0 -196
  81. package/__mocks__/white-web-sdk.ts +0 -50
  82. package/dist/App/AppContext.d.ts +0 -76
  83. package/dist/App/AppPageStateImpl.d.ts +0 -21
  84. package/dist/App/AppProxy.d.ts +0 -86
  85. package/dist/App/AppViewSync.d.ts +0 -11
  86. package/dist/App/MagixEvent/index.d.ts +0 -29
  87. package/dist/App/Storage/StorageEvent.d.ts +0 -8
  88. package/dist/App/Storage/index.d.ts +0 -39
  89. package/dist/App/Storage/typings.d.ts +0 -22
  90. package/dist/App/Storage/utils.d.ts +0 -5
  91. package/dist/App/WhiteboardView.d.ts +0 -22
  92. package/dist/App/index.d.ts +0 -3
  93. package/dist/AppListener.d.ts +0 -21
  94. package/dist/AppManager.d.ts +0 -107
  95. package/dist/AttributesDelegate.d.ts +0 -80
  96. package/dist/BoxEmitter.d.ts +0 -34
  97. package/dist/BoxManager.d.ts +0 -99
  98. package/dist/BuiltinApps.d.ts +0 -5
  99. package/dist/Cursor/Cursor.d.ts +0 -39
  100. package/dist/Cursor/icons.d.ts +0 -3
  101. package/dist/Cursor/index.d.ts +0 -46
  102. package/dist/Helper.d.ts +0 -17
  103. package/dist/InternalEmitter.d.ts +0 -39
  104. package/dist/Page/PageController.d.ts +0 -21
  105. package/dist/Page/index.d.ts +0 -3
  106. package/dist/PageState.d.ts +0 -9
  107. package/dist/ReconnectRefresher.d.ts +0 -24
  108. package/dist/RedoUndo.d.ts +0 -18
  109. package/dist/Register/index.d.ts +0 -28
  110. package/dist/Register/loader.d.ts +0 -4
  111. package/dist/Register/storage.d.ts +0 -8
  112. package/dist/Utils/AppCreateQueue.d.ts +0 -15
  113. package/dist/Utils/Common.d.ts +0 -23
  114. package/dist/Utils/Reactive.d.ts +0 -6
  115. package/dist/Utils/RoomHacker.d.ts +0 -3
  116. package/dist/Utils/error.d.ts +0 -27
  117. package/dist/Utils/log.d.ts +0 -1
  118. package/dist/View/CameraSynchronizer.d.ts +0 -16
  119. package/dist/View/MainView.d.ts +0 -47
  120. package/dist/View/ViewManager.d.ts +0 -13
  121. package/dist/callback.d.ts +0 -24
  122. package/dist/constants.d.ts +0 -49
  123. package/dist/index.cjs.js +0 -46
  124. package/dist/index.umd.js +0 -46
  125. package/dist/typings.d.ts +0 -82
  126. package/jest.config.js +0 -27
  127. package/pnpm-lock.yaml +0 -6302
  128. package/src/App/AppViewSync.ts +0 -68
  129. package/src/App/WhiteboardView.ts +0 -83
  130. package/src/View/CameraSynchronizer.ts +0 -56
  131. package/vite.config.js +0 -51
  132. /package/docs/{qickstart.md → cn/quickstart.md} +0 -0
@@ -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 './typings';
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
- readonly id: string | null;
23
+ readonly id: string | null;
16
24
 
17
- private readonly _context: AppContext;
18
- private readonly _sideEffect = new SideEffectManager();
19
- private _state: TState;
20
- private _destroyed = false;
25
+ private readonly _context: AppContext;
26
+ private readonly _sideEffect = new SideEffectManager();
27
+ private _state: TState;
28
+ private _destroyed = false;
21
29
 
22
- private _refMap = new WeakMap<any, RefValue>();
30
+ private _refMap = new WeakMap<any, RefValue>();
23
31
 
24
- /**
25
- * `setState` alters local state immediately before sending to server. This will cache the old value for onStateChanged diffing.
26
- */
27
- private _lastValue = new Map<string | number | symbol, TState[Extract<keyof TState, string>]>();
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
- constructor(context: AppContext, id?: string, defaultState?: TState) {
30
- if (defaultState && !isObject(defaultState)) {
31
- throw new Error(`Default state for Storage ${id} is not an object.`);
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
- this._context = context;
35
- this.id = id || null;
42
+ this._context = context;
43
+ this.id = id || null;
36
44
 
37
- this._state = {} as TState;
38
- const rawState = this._getRawState(this._state);
45
+ this._state = {} as TState;
46
+ const rawState = this._getRawState(this._state);
39
47
 
40
- if (this._context.isWritable) {
41
- if (this.id === null) {
42
- if (context.isAddApp && defaultState) {
43
- this.setState(defaultState);
44
- }
45
- } else {
46
- if (rawState === this._state || !isObject(rawState)) {
47
- if (!get(this._context.getAttributes(), [STORAGE_NS])) {
48
- this._context.updateAttributes([STORAGE_NS], {});
49
- }
50
- this._context.updateAttributes([STORAGE_NS, this.id], this._state);
51
- if (defaultState) {
52
- this.setState(defaultState);
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
- // strip mobx
59
- plainObjectKeys(rawState).forEach(key => {
60
- if (this.id === null && key === STORAGE_NS) {
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
- } catch (e) {
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
- return this._state;
92
- }
93
-
94
- readonly onStateChanged = new StorageEvent<StorageStateChangedEvent<TState>>();
95
-
96
- addStateChangedListener(handler: StorageStateChangedListener<TState>): StorageStateChangedListenerDisposer {
97
- this.onStateChanged.addListener(handler);
98
- return () => this.onStateChanged.removeListener(handler);
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
- if (!this._context.isWritable) {
119
- console.error(new Error(`Cannot setState on Storage "${this.id}" without writable access`), state);
120
- return;
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
- const keys = plainObjectKeys(state);
124
- if (keys.length > 0) {
125
- keys.forEach(key => {
126
- const value = state[key];
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 (value === void 0) {
132
- this._lastValue.set(key, this._state[key]);
133
- delete this._state[key];
134
- this._setRawState(key, value);
135
- } else {
136
- this._lastValue.set(key, this._state[key]);
137
- this._state[key] = value as TState[Extract<keyof TState, string>];
138
-
139
- let payload: MaybeRefValue<typeof value> = value;
140
- if (isObject(value)) {
141
- let refValue = this._refMap.get(value);
142
- if (!refValue) {
143
- refValue = makeRef(value);
144
- this._refMap.set(value, refValue);
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
- this._setRawState(key, payload)
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
- if (this._destroyed) {
164
- console.error(new Error(`Cannot empty destroyed Storage "${this.id}".`));
165
- return;
166
- }
173
+ /**
174
+ * Empty storage data.
175
+ */
176
+ emptyStorage(): void {
177
+ if (size(this._state) <= 0) {
178
+ return;
179
+ }
167
180
 
168
- if (!this._context.isWritable) {
169
- console.error(new Error(`Cannot empty Storage "${this.id}" without writable access.`));
170
- return;
171
- }
181
+ if (this._destroyed) {
182
+ console.error(new Error(`Cannot empty destroyed Storage "${this.id}".`));
183
+ return;
184
+ }
172
185
 
173
- this.setState(mapValues(this._state, noop as () => undefined));
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
- if (!this._context.isWritable) {
185
- console.error(new Error(`Cannot delete Storage "${this.id}" without writable access.`));
186
- return;
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
- this.destroy();
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
- private _setRawState(key: string, value: any): void {
217
- if (this.id === null) {
218
- if (key === STORAGE_NS) {
219
- throw new Error(`Cannot set attribute internal filed "${STORAGE_NS}"`)
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
- private _updateProperties(actions: ReadonlyArray<AkkoObjectUpdatedProperty<TState, string>>): void {
228
- if (this._destroyed) {
229
- console.error(new Error(`Cannot call _updateProperties on destroyed Storage "${this.id}".`));
230
- return;
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
- if (actions.length > 0) {
234
- const diffs: Diff<TState> = {};
235
-
236
- for (let i = 0; i < actions.length; i++) {
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
- default: {
263
- let newValue = value;
264
-
265
- if (isRef<TState[Extract<keyof TState, string>]>(value)) {
266
- const { k, v } = value;
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
- if (newValue !== this._state[key]) {
279
- oldValue = this._state[key];
280
- this._state[key] = newValue;
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
- diffs[key] = { newValue, oldValue };
284
- break;
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
- this.onStateChanged.dispatch(diffs);
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
- [K in keyof TState]?: MaybeRefValue<TState[K]>;
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<StorageStateChangedEvent<TState>>;
21
+ export type StorageStateChangedListener<TState = any> = StorageEventListener<
22
+ StorageStateChangedEvent<TState>
23
+ >;
22
24
 
23
25
  export type StorageStateChangedListenerDisposer = () => void;
@@ -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
- return Boolean(has(e, '__isRef'));
8
+ return Boolean(has(e, "__isRef"));
9
9
  }
10
10
 
11
11
  export function makeRef<TValue>(v: TValue): RefValue<TValue> {
12
- return { k: genUID(), v, __isRef: true };
12
+ return { k: genUID(), v, __isRef: true };
13
13
  }
14
14
 
15
15
  export function makeAutoRef<TValue>(v: TValue): AutoRefValue<TValue> {
16
- return isRef<ExtractRawValue<TValue>>(v) ? v : makeRef(v as ExtractRawValue<TValue>);
16
+ return isRef<ExtractRawValue<TValue>>(v) ? v : makeRef(v as ExtractRawValue<TValue>);
17
17
  }
package/src/App/index.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  export * from "./AppProxy";
2
2
  export * from "./AppContext";
3
- export * from "./WhiteboardView";
@@ -1,5 +1,5 @@
1
1
  import { callbacks } from "./callback";
2
- import { emitter } from "./InternalEmitter";
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
- emitter.emit("cursorMove", payload);
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
- emitter.emit("rootDirRemoved");
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
  }