@netless/window-manager 1.0.0-canary.8 → 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.
Files changed (135) 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 -39
  5. package/dist/index.js +62 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/{index.es.js → index.mjs} +8393 -5913
  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 +124 -113
  12. package/docs/app-context.md +248 -209
  13. package/docs/basic.md +25 -26
  14. package/docs/camera.md +19 -20
  15. package/docs/cn/advanced.md +137 -0
  16. package/docs/cn/api.md +309 -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 +104 -71
  35. package/src/App/AppPageStateImpl.ts +6 -25
  36. package/src/App/AppProxy.ts +42 -147
  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 +84 -75
  45. package/src/AttributesDelegate.ts +42 -22
  46. package/src/BoxEmitter.ts +12 -6
  47. package/src/BoxManager.ts +122 -106
  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/PageController.ts +1 -0
  58. package/src/Page/index.ts +1 -1
  59. package/src/PageState.ts +6 -5
  60. package/src/ReconnectRefresher.ts +9 -4
  61. package/src/RedoUndo.ts +3 -3
  62. package/src/Register/index.ts +22 -17
  63. package/src/Register/loader.ts +26 -22
  64. package/src/Register/storage.ts +13 -13
  65. package/src/Utils/Common.ts +18 -14
  66. package/src/Utils/Reactive.ts +26 -25
  67. package/src/Utils/RoomHacker.ts +4 -4
  68. package/src/Utils/error.ts +0 -1
  69. package/src/View/IframeBridge.ts +680 -0
  70. package/src/View/MainView.ts +114 -53
  71. package/src/callback.ts +21 -1
  72. package/src/constants.ts +0 -2
  73. package/src/image/pencil-eraser-1.svg +3 -0
  74. package/src/image/pencil-eraser-2.svg +3 -0
  75. package/src/image/pencil-eraser-3.svg +3 -0
  76. package/src/index.ts +224 -74
  77. package/src/style.css +27 -10
  78. package/src/typings.ts +20 -10
  79. package/.prettierignore +0 -7
  80. package/.prettierrc.json +0 -9
  81. package/CHANGELOG.md +0 -196
  82. package/__mocks__/white-web-sdk.ts +0 -50
  83. package/dist/App/AppContext.d.ts +0 -76
  84. package/dist/App/AppPageStateImpl.d.ts +0 -21
  85. package/dist/App/AppProxy.d.ts +0 -81
  86. package/dist/App/AppViewSync.d.ts +0 -11
  87. package/dist/App/MagixEvent/index.d.ts +0 -29
  88. package/dist/App/Storage/StorageEvent.d.ts +0 -8
  89. package/dist/App/Storage/index.d.ts +0 -39
  90. package/dist/App/Storage/typings.d.ts +0 -22
  91. package/dist/App/Storage/utils.d.ts +0 -5
  92. package/dist/App/WhiteboardView.d.ts +0 -22
  93. package/dist/App/index.d.ts +0 -3
  94. package/dist/AppListener.d.ts +0 -21
  95. package/dist/AppManager.d.ts +0 -107
  96. package/dist/AttributesDelegate.d.ts +0 -80
  97. package/dist/BoxEmitter.d.ts +0 -34
  98. package/dist/BoxManager.d.ts +0 -100
  99. package/dist/BuiltinApps.d.ts +0 -5
  100. package/dist/Cursor/Cursor.d.ts +0 -39
  101. package/dist/Cursor/icons.d.ts +0 -3
  102. package/dist/Cursor/index.d.ts +0 -46
  103. package/dist/Helper.d.ts +0 -17
  104. package/dist/InternalEmitter.d.ts +0 -39
  105. package/dist/Page/PageController.d.ts +0 -20
  106. package/dist/Page/index.d.ts +0 -3
  107. package/dist/PageState.d.ts +0 -9
  108. package/dist/ReconnectRefresher.d.ts +0 -24
  109. package/dist/RedoUndo.d.ts +0 -18
  110. package/dist/Register/index.d.ts +0 -28
  111. package/dist/Register/loader.d.ts +0 -4
  112. package/dist/Register/storage.d.ts +0 -8
  113. package/dist/Utils/AppCreateQueue.d.ts +0 -15
  114. package/dist/Utils/Common.d.ts +0 -23
  115. package/dist/Utils/Reactive.d.ts +0 -6
  116. package/dist/Utils/RoomHacker.d.ts +0 -3
  117. package/dist/Utils/error.d.ts +0 -27
  118. package/dist/Utils/log.d.ts +0 -1
  119. package/dist/View/CameraSynchronizer.d.ts +0 -17
  120. package/dist/View/MainView.d.ts +0 -48
  121. package/dist/View/ViewManager.d.ts +0 -13
  122. package/dist/View/ViewSync.d.ts +0 -7
  123. package/dist/callback.d.ts +0 -24
  124. package/dist/constants.d.ts +0 -49
  125. package/dist/index.cjs.js +0 -46
  126. package/dist/index.umd.js +0 -46
  127. package/dist/typings.d.ts +0 -82
  128. package/jest.config.js +0 -27
  129. package/pnpm-lock.yaml +0 -6302
  130. package/src/App/AppViewSync.ts +0 -68
  131. package/src/App/WhiteboardView.ts +0 -83
  132. package/src/View/CameraSynchronizer.ts +0 -73
  133. package/src/View/ViewSync.ts +0 -10
  134. package/vite.config.js +0 -51
  135. /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,57 +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
- if (this.isAddApp) {
109
- this.ensurePageSize(size);
110
- }
111
- this.whiteBoardView = new WhiteBoardView(view, this, this.appProxy, removeViewWrapper, this.ensurePageSize);
112
- return this.whiteBoardView;
113
- }
114
-
115
- private ensurePageSize = (size?: number) => {
116
- if (!isNumber(size)) return;
117
- if (!this.appProxy.scenePath) return;
118
- if (this.appProxy.pageState.length >= size) return;
119
- if (size <= 0 || size >= MAX_PAGE_SIZE) {
120
- throw Error(`[WindowManager]: size ${size} muse be in range [1, ${MAX_PAGE_SIZE}]`);
121
- }
122
- const needInsert = size - this.appProxy.pageState.length;
123
- const scenes = new Array(needInsert).fill({});
124
- this.room?.putScenes(this.appProxy.scenePath, scenes);
125
- }
97
+ };
126
98
 
127
99
  public getInitScenePath = () => {
128
100
  return this.manager.getAppInitPath(this.appId);
129
101
  };
130
102
 
131
103
  /** Get App writable status. */
132
- public get isWritable(): boolean {
104
+ public getIsWritable = (): boolean => {
133
105
  return this.manager.canOperate;
134
106
  };
135
107
 
136
108
  /** Get the App Window UI box. */
137
- public get box(): ReadonlyTeleBox {
109
+ public getBox = (): ReadonlyTeleBox => {
138
110
  const box = this.boxManager.getBox(this.appId);
139
111
  if (box) {
140
112
  return box;
@@ -143,25 +115,10 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
143
115
  }
144
116
  };
145
117
 
146
- public get room(): Room | undefined {
118
+ public getRoom = (): Room | undefined => {
147
119
  return this.manager.room;
148
120
  };
149
121
 
150
- public get members() {
151
- return this.manager.members;
152
- }
153
-
154
- public get memberState(): Member {
155
- const self = findMemberByUid(this.room, this.manager.uid);
156
- if (!self) {
157
- throw new Error(`Member ${this.manager.uid} not found.`);
158
- }
159
- return {
160
- uid: this.manager.uid,
161
- ...self,
162
- }
163
- }
164
-
165
122
  /** @deprecated Use context.storage.setState instead. */
166
123
  public setAttributes = (attributes: TAttributes) => {
167
124
  this.manager.safeSetAttributes({ [this.appId]: attributes });
@@ -174,12 +131,11 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
174
131
  }
175
132
  };
176
133
 
177
- /** @deprecated Use Pages api instead. */
178
134
  public setScenePath = async (scenePath: string): Promise<void> => {
179
135
  if (!this.appProxy.box) return;
180
136
  this.appProxy.setFullPath(scenePath);
181
137
  // 兼容 15 版本 SDK 的切页
182
- this.room?.setScenePath(scenePath);
138
+ this.getRoom()?.setScenePath(scenePath);
183
139
  };
184
140
 
185
141
  /** Get the local App options. */
@@ -205,7 +161,10 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
205
161
  * @param defaultState Default state for initial storage creation.
206
162
  * @returns
207
163
  */
208
- public createStorage = <TState>(storeId: string, defaultState?: TState): Storage<TState> => {
164
+ public createStorage = <TState extends {}>(
165
+ storeId: string,
166
+ defaultState?: TState
167
+ ): Storage<TState> => {
209
168
  const storage = new Storage(this, storeId, defaultState);
210
169
  this.emitter.on("destroy", () => {
211
170
  storage.destroy();
@@ -243,4 +202,78 @@ export class AppContext<TAttributes = any, TMagixEventPayloads = any, TAppOption
243
202
  public removeMagixEventListener = this.manager.displayer.removeMagixEventListener.bind(
244
203
  this.manager.displayer
245
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
+ }
246
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
  }