@netless/window-manager 1.0.0-canary.6 → 1.0.0-canary.61

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 (111) hide show
  1. package/README.md +30 -6
  2. package/dist/index.js +13539 -0
  3. package/dist/index.mjs +13536 -0
  4. package/dist/index.umd.js +13534 -46
  5. package/dist/{App → src/App}/AppContext.d.ts +16 -14
  6. package/dist/{App → src/App}/AppPageStateImpl.d.ts +0 -0
  7. package/dist/{App → src/App}/AppProxy.d.ts +30 -11
  8. package/dist/{App → src/App}/MagixEvent/index.d.ts +0 -0
  9. package/dist/src/App/WhiteboardView.d.ts +27 -0
  10. package/dist/{App → src/App}/index.d.ts +1 -0
  11. package/dist/src/App/type.d.ts +21 -0
  12. package/dist/{AppListener.d.ts → src/AppListener.d.ts} +2 -2
  13. package/dist/{AppManager.d.ts → src/AppManager.d.ts} +11 -6
  14. package/dist/{AttributesDelegate.d.ts → src/AttributesDelegate.d.ts} +5 -2
  15. package/dist/{BoxEmitter.d.ts → src/BoxEmitter.d.ts} +0 -0
  16. package/dist/{BoxManager.d.ts → src/BoxManager.d.ts} +12 -6
  17. package/dist/{BuiltinApps.d.ts → src/BuiltinApps.d.ts} +3 -0
  18. package/dist/{Cursor → src/Cursor}/Cursor.d.ts +0 -0
  19. package/dist/{Cursor → src/Cursor}/icons.d.ts +0 -0
  20. package/dist/{Cursor → src/Cursor}/index.d.ts +4 -3
  21. package/dist/{Helper.d.ts → src/Helper.d.ts} +4 -8
  22. package/dist/{InternalEmitter.d.ts → src/InternalEmitter.d.ts} +1 -4
  23. package/dist/{Page → src/Page}/PageController.d.ts +2 -1
  24. package/dist/{Page → src/Page}/index.d.ts +0 -0
  25. package/dist/{PageState.d.ts → src/PageState.d.ts} +0 -0
  26. package/dist/{ReconnectRefresher.d.ts → src/ReconnectRefresher.d.ts} +0 -0
  27. package/dist/{RedoUndo.d.ts → src/RedoUndo.d.ts} +0 -0
  28. package/dist/{Register → src/Register}/index.d.ts +4 -2
  29. package/dist/{Register → src/Register}/loader.d.ts +1 -1
  30. package/dist/src/Register/storage.d.ts +11 -0
  31. package/dist/{Utils → src/Utils}/AppCreateQueue.d.ts +0 -0
  32. package/dist/{Utils → src/Utils}/Common.d.ts +0 -0
  33. package/dist/{Utils → src/Utils}/Reactive.d.ts +1 -1
  34. package/dist/{Utils → src/Utils}/RoomHacker.d.ts +0 -0
  35. package/dist/{Utils → src/Utils}/error.d.ts +1 -1
  36. package/dist/{Utils → src/Utils}/log.d.ts +0 -0
  37. package/dist/src/View/CameraSynchronizer.d.ts +20 -0
  38. package/dist/{View → src/View}/MainView.d.ts +18 -7
  39. package/dist/src/View/ScrollMode.d.ts +32 -0
  40. package/dist/{View → src/View}/ViewManager.d.ts +0 -0
  41. package/dist/src/View/ViewSync.d.ts +32 -0
  42. package/dist/{callback.d.ts → src/callback.d.ts} +13 -1
  43. package/dist/{constants.d.ts → src/constants.d.ts} +12 -5
  44. package/dist/src/image.d.ts +19 -0
  45. package/dist/{index.d.ts → src/index.d.ts} +66 -17
  46. package/dist/src/shim.d.ts +11 -0
  47. package/dist/src/storage.d.ts +7 -0
  48. package/dist/{typings.d.ts → src/typings.d.ts} +18 -8
  49. package/dist/style.css +810 -1
  50. package/docs/api.md +10 -0
  51. package/docs/app-context.md +155 -27
  52. package/docs/mirgrate-to-1.0.md +68 -0
  53. package/package.json +27 -22
  54. package/playwright.config.ts +29 -0
  55. package/pnpm-lock.yaml +3141 -4483
  56. package/src/App/AppContext.ts +81 -46
  57. package/src/App/AppProxy.ts +249 -139
  58. package/src/App/WhiteboardView.ts +38 -14
  59. package/src/App/index.ts +1 -0
  60. package/src/App/type.ts +22 -0
  61. package/src/AppListener.ts +21 -21
  62. package/src/AppManager.ts +84 -43
  63. package/src/AttributesDelegate.ts +6 -3
  64. package/src/BoxManager.ts +76 -38
  65. package/src/BuiltinApps.ts +9 -8
  66. package/src/Cursor/Cursor.svelte +6 -2
  67. package/src/Cursor/Cursor.ts +16 -5
  68. package/src/Cursor/icons.ts +6 -0
  69. package/src/Cursor/index.ts +13 -10
  70. package/src/Helper.ts +25 -7
  71. package/src/InternalEmitter.ts +1 -4
  72. package/src/Page/PageController.ts +2 -1
  73. package/src/PageState.ts +1 -1
  74. package/src/ReconnectRefresher.ts +6 -2
  75. package/src/Register/index.ts +36 -14
  76. package/src/Register/loader.ts +20 -9
  77. package/src/Register/storage.ts +26 -5
  78. package/src/Utils/Common.ts +3 -0
  79. package/src/Utils/Reactive.ts +29 -27
  80. package/src/Utils/RoomHacker.ts +3 -0
  81. package/src/Utils/error.ts +2 -2
  82. package/src/View/CameraSynchronizer.ts +52 -37
  83. package/src/View/MainView.ts +118 -76
  84. package/src/View/ScrollMode.ts +239 -0
  85. package/src/View/ViewSync.ts +139 -6
  86. package/src/callback.ts +9 -1
  87. package/src/constants.ts +11 -3
  88. package/src/image/pencil-eraser-1.svg +3 -0
  89. package/src/image/pencil-eraser-2.svg +3 -0
  90. package/src/image/pencil-eraser-3.svg +3 -0
  91. package/src/index.ts +202 -58
  92. package/src/storage.ts +15 -0
  93. package/src/style.css +18 -47
  94. package/src/typings.ts +21 -7
  95. package/vite.config.js +12 -7
  96. package/dist/App/AppViewSync.d.ts +0 -11
  97. package/dist/App/Storage/StorageEvent.d.ts +0 -8
  98. package/dist/App/Storage/index.d.ts +0 -39
  99. package/dist/App/Storage/typings.d.ts +0 -22
  100. package/dist/App/Storage/utils.d.ts +0 -5
  101. package/dist/App/WhiteboardView.d.ts +0 -21
  102. package/dist/Register/storage.d.ts +0 -8
  103. package/dist/View/CameraSynchronizer.d.ts +0 -17
  104. package/dist/View/ViewSync.d.ts +0 -7
  105. package/dist/index.cjs.js +0 -46
  106. package/dist/index.es.js +0 -16159
  107. package/src/App/AppViewSync.ts +0 -68
  108. package/src/App/Storage/StorageEvent.ts +0 -21
  109. package/src/App/Storage/index.ts +0 -295
  110. package/src/App/Storage/typings.ts +0 -23
  111. package/src/App/Storage/utils.ts +0 -17
@@ -1,5 +1,4 @@
1
1
  import { BoxNotCreatedError } from "../Utils/error";
2
- import { Storage } from "./Storage";
3
2
  import {
4
3
  autorun,
5
4
  listenDisposed,
@@ -7,17 +6,18 @@ import {
7
6
  reaction,
8
7
  unlistenDisposed,
9
8
  unlistenUpdated,
10
- toJS,
9
+ toJS
11
10
  } from "white-web-sdk";
11
+ import { Storage } from "@netless/synced-store";
12
12
  import type {
13
13
  Room,
14
14
  SceneDefinition,
15
15
  View,
16
- EventListener as WhiteEventListener
16
+ EventListener as WhiteEventListener,
17
+ Player
17
18
  } from "white-web-sdk";
18
19
  import type { ReadonlyTeleBox } from "@netless/telebox-insider";
19
20
  import type Emittery from "emittery";
20
- import type { BoxManager } from "../BoxManager";
21
21
  import type { AppEmitterEvent, Member } from "../index";
22
22
  import type { AppManager } from "../AppManager";
23
23
  import type { AppProxy } from "./AppProxy";
@@ -29,10 +29,15 @@ import type {
29
29
  import { WhiteBoardView } from "./WhiteboardView";
30
30
  import { findMemberByUid } from "../Helper";
31
31
  import { MAX_PAGE_SIZE } from "../constants";
32
- import { putScenes } from "../Utils/Common";
33
- import { isNumber } from "lodash";
32
+ import { isBoolean, isNumber } from "lodash";
33
+ import { Val } from "value-enhancer";
34
34
 
35
- export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any> {
35
+ export type CreateWhiteBoardViewParams = {
36
+ size?: number;
37
+ syncCamera?: boolean;
38
+ }
39
+
40
+ export class AppContext<TAttributes extends Record<string, any> = any, TMagixEventPayloads = any, TAppOptions = any> {
36
41
  public readonly emitter: Emittery<AppEmitterEvent<TAttributes>>;
37
42
  public readonly mobxUtils = {
38
43
  autorun,
@@ -49,12 +54,11 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
49
54
  private store = this.manager.store;
50
55
  public readonly isAddApp: boolean;
51
56
  public readonly isReplay = this.manager.isReplay;
52
- private whiteBoardView?: WhiteBoardView;
57
+ public whiteBoardView?: WhiteBoardView;
53
58
  public _viewWrapper?: HTMLElement;
54
59
 
55
60
  constructor(
56
61
  private manager: AppManager,
57
- private boxManager: BoxManager,
58
62
  public appId: string,
59
63
  private appProxy: AppProxy,
60
64
  private appOptions?: TAppOptions | (() => TAppOptions)
@@ -63,9 +67,17 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
63
67
  this.isAddApp = appProxy.isAddApp;
64
68
  }
65
69
 
66
- public get displayer(){
70
+ public get displayer() {
67
71
  return this.manager.displayer;
68
- };
72
+ }
73
+
74
+ public get destroyed() {
75
+ return this.appProxy.status === "destroyed";
76
+ }
77
+
78
+ public get attributes(): TAttributes {
79
+ return this.appProxy.attributes;
80
+ }
69
81
 
70
82
  /** @deprecated Use context.storage.state instead. */
71
83
  public getAttributes = (): TAttributes | undefined => {
@@ -85,7 +97,16 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
85
97
  return this.appProxy.view;
86
98
  };
87
99
 
88
- public createWhiteBoardView = (size?: number): WhiteBoardView => {
100
+ public get now(): number {
101
+ if (this.isReplay) {
102
+ const player = this.displayer as Player;
103
+ return player.beginTimestamp + player.progressTime;
104
+ } else {
105
+ return (this.displayer as Room).calibrationTimestamp;
106
+ }
107
+ }
108
+
109
+ public createWhiteBoardView = (params?: CreateWhiteBoardViewParams): WhiteBoardView => {
89
110
  if (this.whiteBoardView) {
90
111
  return this.whiteBoardView;
91
112
  }
@@ -93,23 +114,39 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
93
114
  if (!view) {
94
115
  view = this.appProxy.createAppDir();
95
116
  }
117
+ if (params) {
118
+ if (isBoolean(params.syncCamera)) {
119
+ this.appProxy.syncCamera$.setValue(params.syncCamera);
120
+ }
121
+ }
96
122
  const viewWrapper = document.createElement("div");
97
123
  this._viewWrapper = viewWrapper;
98
124
  viewWrapper.className = "window-manager-view-wrapper";
99
- this.box.$content.parentElement?.appendChild(viewWrapper);
100
- const removeViewWrapper = () => {
101
- this.box.$content.parentElement?.removeChild(viewWrapper);
102
- this._viewWrapper = undefined;
103
- }
125
+ this.box.$main.appendChild(viewWrapper);
104
126
  view.divElement = viewWrapper;
127
+ this.appProxy.fireMemberStateChange();
105
128
  if (this.isAddApp) {
106
- this.initPageSize(size);
129
+ this.ensurePageSize(params?.size);
107
130
  }
108
- this.whiteBoardView = new WhiteBoardView(this, this.appProxy, removeViewWrapper);
131
+ this.whiteBoardView = new WhiteBoardView(view, this, this.appProxy, this.ensurePageSize);
132
+ this.appProxy.sideEffectManager.add(() => [
133
+ this.box._stageRect$.subscribe(rect => {
134
+ viewWrapper.style.left = `${rect.x}px`;
135
+ viewWrapper.style.top = `${rect.y}px`;
136
+ viewWrapper.style.width = `${rect.width}px`;
137
+ viewWrapper.style.height = `${rect.height}px`;
138
+ }),
139
+ () => {
140
+ return () => {
141
+ this.whiteBoardView = undefined;
142
+ }
143
+ }
144
+ ]);
145
+ this.appProxy.whiteBoardViewCreated$.setValue(true);
109
146
  return this.whiteBoardView;
110
147
  }
111
148
 
112
- private initPageSize = (size?: number) => {
149
+ private ensurePageSize = (size?: number) => {
113
150
  if (!isNumber(size)) return;
114
151
  if (!this.appProxy.scenePath) return;
115
152
  if (this.appProxy.pageState.length >= size) return;
@@ -117,25 +154,22 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
117
154
  throw Error(`[WindowManager]: size ${size} muse be in range [1, ${MAX_PAGE_SIZE}]`);
118
155
  }
119
156
  const needInsert = size - this.appProxy.pageState.length;
120
- const startPageNumber = this.appProxy.pageState.length;
121
- const scenes = new Array(needInsert).fill({}).map((_, index) => {
122
- return { name: `${startPageNumber + index + 1}` };
123
- });
124
- putScenes(this.room, this.appProxy.scenePath, scenes);
157
+ const scenes = new Array(needInsert).fill({});
158
+ this.room?.putScenes(this.appProxy.scenePath, scenes);
125
159
  }
126
160
 
127
161
  public getInitScenePath = () => {
128
- return this.manager.getAppInitPath(this.appId);
162
+ return this.appProxy.scenePath;
129
163
  };
130
164
 
131
165
  /** Get App writable status. */
132
166
  public get isWritable(): boolean {
133
- return this.manager.canOperate;
167
+ return this.manager.canOperate && !this.destroyed;
134
168
  };
135
169
 
136
170
  /** Get the App Window UI box. */
137
171
  public get box(): ReadonlyTeleBox {
138
- const box = this.boxManager.getBox(this.appId);
172
+ const box = this.appProxy.box$.value;
139
173
  if (box) {
140
174
  return box;
141
175
  } else {
@@ -147,14 +181,15 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
147
181
  return this.manager.room;
148
182
  };
149
183
 
150
- public get members() {
151
- return this.manager.members;
184
+ public get members(): Member[] {
185
+ return this.manager.members$.value;
152
186
  }
153
187
 
154
- public get memberState(): Member {
188
+ //** currentMember is undefined in read-only and replay mode. */
189
+ public get currentMember(): Member | undefined {
155
190
  const self = findMemberByUid(this.room, this.manager.uid);
156
191
  if (!self) {
157
- throw new Error(`Member ${this.manager.uid} not found.`);
192
+ return undefined;
158
193
  }
159
194
  return {
160
195
  uid: this.manager.uid,
@@ -189,26 +224,26 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
189
224
  : this.appOptions;
190
225
  };
191
226
 
192
- private _storage?: Storage<TAttributes>;
193
-
194
- /** Main Storage for attributes. */
195
- public get storage(): Storage<TAttributes> {
196
- if (!this._storage) {
197
- this._storage = new Storage(this);
198
- }
199
- return this._storage;
200
- }
201
-
202
227
  /**
203
228
  * Create separated storages for flexible state management.
204
- * @param storeId Namespace for the storage. Storages of the same namespace share the same data.
229
+ * @param namespace Namespace for the storage. Storages of the same namespace share the same data.
205
230
  * @param defaultState Default state for initial storage creation.
206
231
  * @returns
207
232
  */
208
- public createStorage = <TState>(storeId: string, defaultState?: TState): Storage<TState> => {
209
- const storage = new Storage(this, storeId, defaultState);
233
+ public createStorage = <TState extends Record<string, any>>(namespace: string, defaultState?: TState): Storage<TState> => {
234
+ const isWritable$ = new Val(this.isWritable);
235
+ const plugin$ = new Val(this.manager.windowManger);
236
+ const storage = new Storage({
237
+ plugin$,
238
+ isWritable$,
239
+ namespace,
240
+ defaultState: defaultState
241
+ });
242
+ this.emitter.on("writableChange", writable => {
243
+ isWritable$.setValue(writable);
244
+ })
210
245
  this.emitter.on("destroy", () => {
211
- storage.destroy();
246
+ storage.disconnect();
212
247
  });
213
248
  return storage;
214
249
  };