@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,4 +1,5 @@
1
1
  import { BoxNotCreatedError } from "../Utils/error";
2
+ import { putScenes } from "../Utils/Common";
2
3
  import { Storage } from "./Storage";
3
4
  import {
4
5
  autorun,
@@ -13,12 +14,12 @@ import type {
13
14
  Room,
14
15
  SceneDefinition,
15
16
  View,
16
- EventListener as WhiteEventListener
17
+ EventListener as WhiteEventListener,
17
18
  } from "white-web-sdk";
18
19
  import type { ReadonlyTeleBox } from "@netless/telebox-insider";
19
20
  import type Emittery from "emittery";
20
21
  import type { BoxManager } from "../BoxManager";
21
- import type { AppEmitterEvent, Member } from "../index";
22
+ import type { AppEmitterEvent } from "../index";
22
23
  import type { AppManager } from "../AppManager";
23
24
  import type { AppProxy } from "./AppProxy";
24
25
  import type {
@@ -26,12 +27,13 @@ import type {
26
27
  MagixEventDispatcher,
27
28
  MagixEventRemoveListener,
28
29
  } from "./MagixEvent";
29
- import { WhiteBoardView } from "./WhiteboardView";
30
- import { findMemberByUid } from "../Helper";
31
- import { MAX_PAGE_SIZE } from "../constants";
32
- import { isNumber } from "lodash";
30
+ import type { AddPageParams, PageController, PageState } from "../Page";
31
+ import { internalEmitter } from "../InternalEmitter";
32
+ import { callbacks } from "../callback";
33
33
 
34
- export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOptions = any> {
34
+ export class AppContext<TAttributes extends {} = any, TMagixEventPayloads = any, TAppOptions = any>
35
+ implements PageController
36
+ {
35
37
  public readonly emitter: Emittery<AppEmitterEvent<TAttributes>>;
36
38
  public readonly mobxUtils = {
37
39
  autorun,
@@ -48,8 +50,6 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
48
50
  private store = this.manager.store;
49
51
  public readonly isAddApp: boolean;
50
52
  public readonly isReplay = this.manager.isReplay;
51
- private whiteBoardView?: WhiteBoardView;
52
- public _viewWrapper?: HTMLElement;
53
53
 
54
54
  constructor(
55
55
  private manager: AppManager,
@@ -62,13 +62,9 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
62
62
  this.isAddApp = appProxy.isAddApp;
63
63
  }
64
64
 
65
- public get displayer() {
65
+ public getDisplayer = () => {
66
66
  return this.manager.displayer;
67
- }
68
-
69
- public get destroyed() {
70
- return this.appProxy.status === "destroyed";
71
- }
67
+ };
72
68
 
73
69
  /** @deprecated Use context.storage.state instead. */
74
70
  public getAttributes = (): TAttributes | undefined => {
@@ -84,58 +80,33 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
84
80
  }
85
81
  };
86
82
 
87
- public get view(): View | undefined {
83
+ public getView = (): View | undefined => {
88
84
  return this.appProxy.view;
89
85
  };
90
86
 
91
- public createWhiteBoardView = (size?: number): WhiteBoardView => {
92
- if (this.whiteBoardView) {
93
- return this.whiteBoardView;
94
- }
95
- let view = this.view;
96
- if (!view) {
97
- view = this.appProxy.createAppDir();
98
- }
99
- const viewWrapper = document.createElement("div");
100
- this._viewWrapper = viewWrapper;
101
- viewWrapper.className = "window-manager-view-wrapper";
102
- this.box.$content.parentElement?.appendChild(viewWrapper);
103
- const removeViewWrapper = () => {
104
- this.box.$content.parentElement?.removeChild(viewWrapper);
105
- this._viewWrapper = undefined;
87
+ public mountView = (dom: HTMLElement): void => {
88
+ const view = this.getView();
89
+ if (view) {
90
+ view.divElement = dom as HTMLDivElement;
91
+ setTimeout(() => {
92
+ // 渲染需要时间,延迟 refresh
93
+ this.getRoom()?.refreshViewSize();
94
+ callbacks.emit("onAppViewMounted", { appId: this.appId, view });
95
+ }, 1000);
106
96
  }
107
- view.divElement = viewWrapper;
108
- this.appProxy.fireMemberStateChange();
109
- if (this.isAddApp) {
110
- this.ensurePageSize(size);
111
- }
112
- this.whiteBoardView = new WhiteBoardView(view, this, this.appProxy, removeViewWrapper, this.ensurePageSize);
113
- return this.whiteBoardView;
114
- }
115
-
116
- private ensurePageSize = (size?: number) => {
117
- if (!isNumber(size)) return;
118
- if (!this.appProxy.scenePath) return;
119
- if (this.appProxy.pageState.length >= size) return;
120
- if (size <= 0 || size >= MAX_PAGE_SIZE) {
121
- throw Error(`[WindowManager]: size ${size} muse be in range [1, ${MAX_PAGE_SIZE}]`);
122
- }
123
- const needInsert = size - this.appProxy.pageState.length;
124
- const scenes = new Array(needInsert).fill({});
125
- this.room?.putScenes(this.appProxy.scenePath, scenes);
126
- }
97
+ };
127
98
 
128
99
  public getInitScenePath = () => {
129
100
  return this.manager.getAppInitPath(this.appId);
130
101
  };
131
102
 
132
103
  /** Get App writable status. */
133
- public get isWritable(): boolean {
134
- return this.manager.canOperate && !this.destroyed;
104
+ public getIsWritable = (): boolean => {
105
+ return this.manager.canOperate;
135
106
  };
136
107
 
137
108
  /** Get the App Window UI box. */
138
- public get box(): ReadonlyTeleBox {
109
+ public getBox = (): ReadonlyTeleBox => {
139
110
  const box = this.boxManager.getBox(this.appId);
140
111
  if (box) {
141
112
  return box;
@@ -144,25 +115,10 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
144
115
  }
145
116
  };
146
117
 
147
- public get room(): Room | undefined {
118
+ public getRoom = (): Room | undefined => {
148
119
  return this.manager.room;
149
120
  };
150
121
 
151
- public get members() {
152
- return this.manager.members;
153
- }
154
-
155
- public get memberState(): Member {
156
- const self = findMemberByUid(this.room, this.manager.uid);
157
- if (!self) {
158
- throw new Error(`Member ${this.manager.uid} not found.`);
159
- }
160
- return {
161
- uid: this.manager.uid,
162
- ...self,
163
- }
164
- }
165
-
166
122
  /** @deprecated Use context.storage.setState instead. */
167
123
  public setAttributes = (attributes: TAttributes) => {
168
124
  this.manager.safeSetAttributes({ [this.appId]: attributes });
@@ -175,12 +131,11 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
175
131
  }
176
132
  };
177
133
 
178
- /** @deprecated Use Pages api instead. */
179
134
  public setScenePath = async (scenePath: string): Promise<void> => {
180
135
  if (!this.appProxy.box) return;
181
136
  this.appProxy.setFullPath(scenePath);
182
137
  // 兼容 15 版本 SDK 的切页
183
- this.room?.setScenePath(scenePath);
138
+ this.getRoom()?.setScenePath(scenePath);
184
139
  };
185
140
 
186
141
  /** Get the local App options. */
@@ -206,7 +161,10 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
206
161
  * @param defaultState Default state for initial storage creation.
207
162
  * @returns
208
163
  */
209
- public createStorage = <TState>(storeId: string, defaultState?: TState): Storage<TState> => {
164
+ public createStorage = <TState extends {}>(
165
+ storeId: string,
166
+ defaultState?: TState
167
+ ): Storage<TState> => {
210
168
  const storage = new Storage(this, storeId, defaultState);
211
169
  this.emitter.on("destroy", () => {
212
170
  storage.destroy();
@@ -244,4 +202,78 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
244
202
  public removeMagixEventListener = this.manager.displayer.removeMagixEventListener.bind(
245
203
  this.manager.displayer
246
204
  ) as MagixEventRemoveListener<TMagixEventPayloads>;
205
+
206
+ /** PageController */
207
+ public nextPage = async (): Promise<boolean> => {
208
+ const nextIndex = this.pageState.index + 1;
209
+ if (nextIndex > this.pageState.length - 1) {
210
+ console.warn("[WindowManager] nextPage: index out of range");
211
+ return false;
212
+ }
213
+ this.appProxy.setSceneIndex(nextIndex);
214
+ return true;
215
+ };
216
+
217
+ public jumpPage = async (index: number): Promise<boolean> => {
218
+ if (!(0 <= index && index < this.pageState.length)) {
219
+ console.warn("[WindowManager] nextPage: index out of range");
220
+ return false;
221
+ }
222
+ this.appProxy.setSceneIndex(index);
223
+ return true;
224
+ };
225
+
226
+ public prevPage = async (): Promise<boolean> => {
227
+ const nextIndex = this.pageState.index - 1;
228
+ if (nextIndex < 0) {
229
+ console.warn("[WindowManager] prevPage: index out of range");
230
+ return false;
231
+ }
232
+ this.appProxy.setSceneIndex(nextIndex);
233
+ return true;
234
+ };
235
+
236
+ public addPage = async (params?: AddPageParams) => {
237
+ const after = params?.after;
238
+ const scene = params?.scene;
239
+ const scenePath = this.appProxy.scenePath;
240
+ if (!scenePath) return;
241
+ if (after) {
242
+ const nextIndex = this.pageState.index + 1;
243
+ putScenes(this.manager.room, scenePath, [scene || {}], nextIndex);
244
+ } else {
245
+ putScenes(this.manager.room, scenePath, [scene || {}]);
246
+ }
247
+ };
248
+
249
+ public removePage = async (index?: number): Promise<boolean> => {
250
+ const needRemoveIndex = index === undefined ? this.pageState.index : index;
251
+ if (this.pageState.length === 1) {
252
+ console.warn(`[WindowManager]: can not remove the last page`);
253
+ return false;
254
+ }
255
+ if (needRemoveIndex < 0 || needRemoveIndex >= this.pageState.length) {
256
+ console.warn(`[WindowManager]: page index ${index} out of range`);
257
+ return false;
258
+ }
259
+ return this.appProxy.removeSceneByIndex(needRemoveIndex);
260
+ };
261
+
262
+ public get pageState(): PageState {
263
+ return this.appProxy.pageState;
264
+ }
265
+
266
+ public get kind(): string {
267
+ return this.appProxy.kind;
268
+ }
269
+
270
+ /** Dispatch a local event to `manager.onAppEvent()`. */
271
+ public dispatchAppEvent(type: string, value?: any): void {
272
+ internalEmitter.emit(`custom-${this.kind}` as any, {
273
+ kind: this.kind,
274
+ appId: this.appId,
275
+ type,
276
+ value,
277
+ });
278
+ }
247
279
  }
@@ -9,15 +9,11 @@ export type AppPageStateParams = {
9
9
  };
10
10
 
11
11
  export class AppPageStateImpl {
12
- public sceneNode: ScenesCallbacksNode | null = null;
13
- private scenePath?: string;
14
- private view?: View;
12
+ private sceneNode: ScenesCallbacksNode | null = null;
15
13
 
16
14
  constructor(private params: AppPageStateParams) {
17
15
  const { displayer, scenePath } = this.params;
18
- this.view = this.params.view;
19
16
  if (scenePath) {
20
- this.scenePath = scenePath;
21
17
  this.sceneNode = displayer.createScenesCallback(scenePath, {
22
18
  onAddScene: this.onSceneChange,
23
19
  onRemoveScene: this.onSceneChange,
@@ -25,39 +21,24 @@ export class AppPageStateImpl {
25
21
  }
26
22
  }
27
23
 
28
- public createSceneNode = (scenePath: string) => {
29
- this.scenePath = scenePath;
30
- if (this.sceneNode) {
31
- this.sceneNode.dispose();
32
- }
33
- this.sceneNode = this.params.displayer.createScenesCallback(scenePath, {
34
- onAddScene: this.onSceneChange,
35
- onRemoveScene: this.onSceneChange,
36
- });
37
- return this.sceneNode;
38
- }
39
-
40
- public setView(view: View) {
41
- this.view = view;
42
- }
43
-
44
- private onSceneChange = () => {
24
+ private onSceneChange = (node: ScenesCallbacksNode) => {
25
+ this.sceneNode = node;
45
26
  this.params.notifyPageStateChange();
46
27
  };
47
28
 
48
29
  public getFullPath(index: number) {
49
30
  const scenes = this.sceneNode?.scenes;
50
- if (this.scenePath && scenes) {
31
+ if (this.params.scenePath && scenes) {
51
32
  const name = scenes[index];
52
33
  if (name) {
53
- return `${this.scenePath}/${name}`;
34
+ return `${this.params.scenePath}/${name}`;
54
35
  }
55
36
  }
56
37
  }
57
38
 
58
39
  public toObject(): PageState {
59
40
  return {
60
- index: this.view?.focusSceneIndex || 0,
41
+ index: this.params.view?.focusSceneIndex || 0,
61
42
  length: this.sceneNode?.scenes.length || 0,
62
43
  };
63
44
  }