@netless/window-manager 0.4.0-canary.7 → 0.4.1-canary.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 (87) hide show
  1. package/.idea/inspectionProfiles/Project_Default.xml +7 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/.idea/window-manager.iml +12 -0
  5. package/.vscode/settings.json +1 -0
  6. package/CHANGELOG.md +39 -2
  7. package/README.md +3 -0
  8. package/dist/App/MagixEvent/index.d.ts +29 -0
  9. package/dist/{src/App → App}/Storage/StorageEvent.d.ts +0 -0
  10. package/dist/App/Storage/index.d.ts +39 -0
  11. package/dist/{src/App → App}/Storage/typings.d.ts +1 -0
  12. package/dist/{src/App → App}/Storage/utils.d.ts +0 -0
  13. package/dist/AppContext.d.ts +68 -0
  14. package/dist/{src/AppListener.d.ts → AppListener.d.ts} +2 -0
  15. package/dist/{src/AppManager.d.ts → AppManager.d.ts} +23 -8
  16. package/dist/{src/AppProxy.d.ts → AppProxy.d.ts} +5 -5
  17. package/dist/{src/AttributesDelegate.d.ts → AttributesDelegate.d.ts} +2 -2
  18. package/dist/{src/BoxManager.d.ts → BoxManager.d.ts} +6 -4
  19. package/dist/{src/BuiltinApps.d.ts → BuiltinApps.d.ts} +0 -1
  20. package/dist/{src/ContainerResizeObserver.d.ts → ContainerResizeObserver.d.ts} +0 -0
  21. package/dist/{src/Cursor → Cursor}/Cursor.d.ts +10 -12
  22. package/dist/{src/Cursor → Cursor}/icons.d.ts +0 -0
  23. package/dist/{src/Cursor → Cursor}/index.d.ts +6 -16
  24. package/dist/{src/Helper.d.ts → Helper.d.ts} +1 -0
  25. package/dist/{src/ReconnectRefresher.d.ts → ReconnectRefresher.d.ts} +0 -0
  26. package/dist/{src/Register → Register}/index.d.ts +5 -0
  27. package/dist/{src/Register → Register}/loader.d.ts +0 -0
  28. package/dist/{src/Register → Register}/storage.d.ts +5 -1
  29. package/dist/Utils/AppCreateQueue.d.ts +11 -0
  30. package/dist/{src/Utils → Utils}/Common.d.ts +4 -1
  31. package/dist/{src/Utils → Utils}/Reactive.d.ts +0 -0
  32. package/dist/Utils/RoomHacker.d.ts +3 -0
  33. package/dist/{src/Utils → Utils}/error.d.ts +0 -0
  34. package/dist/{src/Utils → Utils}/log.d.ts +0 -0
  35. package/dist/{src/View → View}/MainView.d.ts +4 -3
  36. package/dist/{src/View → View}/ViewManager.d.ts +0 -0
  37. package/dist/{src/constants.d.ts → constants.d.ts} +5 -2
  38. package/dist/{src/index.d.ts → index.d.ts} +34 -6
  39. package/dist/index.es.js +41 -1
  40. package/dist/index.es.js.map +1 -1
  41. package/dist/index.umd.js +41 -1
  42. package/dist/index.umd.js.map +1 -1
  43. package/dist/style.css +1 -1
  44. package/dist/{src/typings.d.ts → typings.d.ts} +2 -2
  45. package/docs/advanced.md +53 -0
  46. package/docs/api.md +79 -6
  47. package/docs/concept.md +9 -0
  48. package/docs/replay.md +40 -0
  49. package/package.json +7 -8
  50. package/src/App/MagixEvent/index.ts +68 -0
  51. package/src/App/Storage/index.ts +89 -43
  52. package/src/App/Storage/typings.ts +4 -2
  53. package/src/AppContext.ts +61 -24
  54. package/src/AppListener.ts +28 -8
  55. package/src/AppManager.ts +244 -71
  56. package/src/AppProxy.ts +40 -29
  57. package/src/AttributesDelegate.ts +2 -2
  58. package/src/BoxManager.ts +33 -19
  59. package/src/BuiltinApps.ts +0 -1
  60. package/src/ContainerResizeObserver.ts +3 -3
  61. package/src/Cursor/Cursor.svelte +25 -21
  62. package/src/Cursor/Cursor.ts +25 -38
  63. package/src/Cursor/icons.ts +2 -0
  64. package/src/Cursor/index.ts +45 -139
  65. package/src/Helper.ts +12 -1
  66. package/src/Register/index.ts +32 -17
  67. package/src/Register/loader.ts +28 -13
  68. package/src/Register/storage.ts +6 -1
  69. package/src/Utils/AppCreateQueue.ts +54 -0
  70. package/src/Utils/Common.ts +35 -2
  71. package/src/Utils/RoomHacker.ts +44 -14
  72. package/src/View/MainView.ts +19 -12
  73. package/src/View/ViewManager.ts +1 -2
  74. package/src/constants.ts +6 -2
  75. package/src/image/laser-pointer-cursor.svg +17 -0
  76. package/src/index.ts +153 -35
  77. package/src/shim.d.ts +5 -0
  78. package/src/style.css +6 -1
  79. package/src/typings.ts +2 -2
  80. package/vite.config.js +8 -2
  81. package/dist/src/App/Storage/index.d.ts +0 -26
  82. package/dist/src/AppContext.d.ts +0 -46
  83. package/dist/src/Base/Context.d.ts +0 -12
  84. package/dist/src/Base/index.d.ts +0 -7
  85. package/dist/src/Utils/RoomHacker.d.ts +0 -3
  86. package/src/Base/Context.ts +0 -45
  87. package/src/Base/index.ts +0 -10
@@ -1,5 +1,4 @@
1
1
  import { AnimationMode, reaction } from "white-web-sdk";
2
- import { Base } from "../Base";
3
2
  import { callbacks, emitter } from "../index";
4
3
  import { createView } from "./ViewManager";
5
4
  import { debounce, isEmpty, isEqual } from "lodash";
@@ -9,20 +8,20 @@ import { SideEffectManager } from "side-effect-manager";
9
8
  import type { Camera, Size, View } from "white-web-sdk";
10
9
  import type { AppManager } from "../AppManager";
11
10
 
12
- export class MainViewProxy extends Base {
11
+ export class MainViewProxy {
13
12
  private scale?: number;
14
13
  private started = false;
15
14
  private mainViewIsAddListener = false;
16
15
  private mainView: View;
17
- private viewId = "mainView";
16
+ private store = this.manager.store;
18
17
 
19
18
  private sideEffectManager = new SideEffectManager();
20
19
 
21
- constructor(manager: AppManager) {
22
- super(manager);
20
+ constructor(private manager: AppManager) {
23
21
  this.mainView = this.createMainView();
24
22
  this.moveCameraSizeByAttributes();
25
23
  emitter.once("mainViewMounted").then(() => {
24
+ this.addMainViewListener();
26
25
  setTimeout(() => {
27
26
  this.start();
28
27
  if (!this.mainViewCamera || !this.mainViewSize) {
@@ -61,15 +60,15 @@ export class MainViewProxy extends Base {
61
60
  }
62
61
 
63
62
  public setCameraAndSize(): void {
64
- this.store.setMainViewCamera({ ...this.mainView.camera, id: this.context.uid });
65
- this.store.setMainViewSize({ ...this.mainView.size, id: this.context.uid });
63
+ this.store.setMainViewCamera({ ...this.mainView.camera, id: this.manager.uid });
64
+ this.store.setMainViewSize({ ...this.mainView.size, id: this.manager.uid });
66
65
  }
67
66
 
68
67
  private cameraReaction = () => {
69
68
  return reaction(
70
69
  () => this.mainViewCamera,
71
70
  camera => {
72
- if (camera && camera.id !== this.context.uid) {
71
+ if (camera && camera.id !== this.manager.uid) {
73
72
  this.moveCameraToContian(this.mainViewSize);
74
73
  this.moveCamera(camera);
75
74
  }
@@ -104,9 +103,16 @@ export class MainViewProxy extends Base {
104
103
  return mainView;
105
104
  }
106
105
 
106
+ public onReconnect(): void {
107
+ const mainViewScenePath = this.store.getMainViewScenePath();
108
+ if (mainViewScenePath) {
109
+ setViewFocusScenePath(this.view, mainViewScenePath);
110
+ }
111
+ }
112
+
107
113
  private onCameraUpdatedByDevice = (camera: Camera) => {
108
- this.store.setMainViewCamera({ ...camera, id: this.context.uid });
109
- if (!isEqual(this.mainViewSize, { ...this.mainView.size, id: this.context.uid })) {
114
+ this.store.setMainViewCamera({ ...camera, id: this.manager.uid });
115
+ if (!isEqual(this.mainViewSize, { ...this.mainView.size, id: this.manager.uid })) {
110
116
  this.setMainViewSize(this.view.size);
111
117
  }
112
118
  };
@@ -134,11 +140,11 @@ export class MainViewProxy extends Base {
134
140
  public async mainViewClickHandler(): Promise<void> {
135
141
  if (!this.manager.canOperate) return;
136
142
  this.store.cleanFocus();
137
- this.context.blurFocusBox();
143
+ this.manager.boxManager?.blurAllBox();
138
144
  }
139
145
 
140
146
  public setMainViewSize = debounce(size => {
141
- this.store.setMainViewSize({ ...size, id: this.context.uid });
147
+ this.store.setMainViewSize({ ...size, id: this.manager.uid });
142
148
  }, 50);
143
149
 
144
150
  private addCameraListener() {
@@ -185,6 +191,7 @@ export class MainViewProxy extends Base {
185
191
  }
186
192
 
187
193
  public stop() {
194
+ this.removeMainViewListener();
188
195
  this.removeCameraListener();
189
196
  this.manager.refresher?.remove(Fields.MainViewCamera);
190
197
  this.manager.refresher?.remove(Fields.MainViewSize);
@@ -1,4 +1,4 @@
1
- import type { View , Displayer} from "white-web-sdk";
1
+ import type { View, Displayer } from "white-web-sdk";
2
2
 
3
3
  export class ViewManager {
4
4
  public views: Map<string, View> = new Map();
@@ -38,7 +38,6 @@ export class ViewManager {
38
38
  }
39
39
  }
40
40
 
41
-
42
41
  export const createView = (displayer: Displayer): View => {
43
42
  const view = displayer.views.createView();
44
43
  setDefaultCameraBound(view);
package/src/constants.ts CHANGED
@@ -10,7 +10,9 @@ export enum Events {
10
10
  SetMainViewScenePath = "SetMainViewScenePath",
11
11
  SetMainViewSceneIndex = "SetMainViewSceneIndex",
12
12
  SwitchViewsToFreedom = "SwitchViewsToFreedom",
13
- MoveCameraToContain = "MoveCameraToContain"
13
+ MoveCamera = "MoveCamera",
14
+ MoveCameraToContain = "MoveCameraToContain",
15
+ CursorMove = "CursorMove",
14
16
  }
15
17
 
16
18
  export const MagixEventName = "__WindowManger";
@@ -37,7 +39,7 @@ export enum CursorState {
37
39
  Normal = "normal",
38
40
  }
39
41
 
40
- export const REQUIRE_VERSION = "2.13.16";
42
+ export const REQUIRE_VERSION = "2.16.1";
41
43
 
42
44
  export const MIN_WIDTH = 340 / 720;
43
45
  export const MIN_HEIGHT = 340 / 720;
@@ -45,3 +47,5 @@ export const MIN_HEIGHT = 340 / 720;
45
47
  export const SET_SCENEPATH_DELAY = 100; // 设置 scenePath 的延迟事件
46
48
 
47
49
  export const DEFAULT_CONTAINER_RATIO = 9 / 16;
50
+
51
+ export const ROOT_DIR = "/";
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4
+ <title>编组 2</title>
5
+ <desc>Created with Sketch.</desc>
6
+ <defs>
7
+ <filter x="-120.0%" y="-120.0%" width="340.0%" height="340.0%" filterUnits="objectBoundingBox" id="filter-1">
8
+ <feGaussianBlur stdDeviation="4" in="SourceGraphic"></feGaussianBlur>
9
+ </filter>
10
+ </defs>
11
+ <g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
12
+ <g id="编组-2" transform="translate(9.000000, 9.000000)" fill="#FF0100">
13
+ <circle id="椭圆形" filter="url(#filter-1)" cx="5" cy="5" r="5"></circle>
14
+ <path d="M5,8 C6.65685425,8 8,6.65685425 8,5 C8,3.34314575 6.65685425,2 5,2 C3.34314575,2 2,3.34314575 2,5 C2,6.65685425 3.34314575,8 5,8 Z M5,6.28571429 C4.28991961,6.28571429 3.71428571,5.71008039 3.71428571,5 C3.71428571,4.28991961 4.28991961,3.71428571 5,3.71428571 C5.71008039,3.71428571 6.28571429,4.28991961 6.28571429,5 C6.28571429,5.71008039 5.71008039,6.28571429 5,6.28571429 Z" id="椭圆形" fill-rule="nonzero"></path>
15
+ </g>
16
+ </g>
17
+ </svg>
package/src/index.ts CHANGED
@@ -2,25 +2,26 @@ import Emittery from "emittery";
2
2
  import pRetry from "p-retry";
3
3
  import { AppManager } from "./AppManager";
4
4
  import { appRegister } from "./Register";
5
+ import { checkVersion, setupWrapper } from "./Helper";
5
6
  import { ContainerResizeObserver } from "./ContainerResizeObserver";
6
7
  import { createBoxManager } from "./BoxManager";
7
8
  import { CursorManager } from "./Cursor";
8
- import { DEFAULT_CONTAINER_RATIO, Events, REQUIRE_VERSION } from "./constants";
9
+ import { DEFAULT_CONTAINER_RATIO, Events } from "./constants";
9
10
  import { Fields } from "./AttributesDelegate";
10
11
  import { initDb } from "./Register/storage";
11
- import { isNull, isObject } from "lodash";
12
+ import { InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
13
+ import { isEqual, isNull, isObject, omit } from "lodash";
12
14
  import { log } from "./Utils/log";
13
15
  import { ReconnectRefresher } from "./ReconnectRefresher";
14
16
  import { replaceRoomFunction } from "./Utils/RoomHacker";
15
17
  import { setupBuiltin } from "./BuiltinApps";
16
- import { setupWrapper } from "./Helper";
17
- import { version } from "../package.json";
18
18
  import "./style.css";
19
19
  import "@netless/telebox-insider/dist/style.css";
20
+ import type { LoadAppEvent } from "./Register";
20
21
  import {
21
22
  addEmitterOnceListener,
22
23
  ensureValidScenePath,
23
- getVersionNumber,
24
+ entireScenes,
24
25
  isValidScenePath,
25
26
  wait,
26
27
  } from "./Utils/Common";
@@ -30,17 +31,8 @@ import {
30
31
  AppManagerNotInitError,
31
32
  InvalidScenePath,
32
33
  ParamsInvalidError,
33
- WhiteWebSDKInvalidError,
34
34
  } from "./Utils/error";
35
- import type { Apps } from "./AttributesDelegate";
36
- import {
37
- InvisiblePlugin,
38
- isPlayer,
39
- isRoom,
40
- RoomPhase,
41
- ViewMode,
42
- WhiteVersion,
43
- } from "white-web-sdk";
35
+ import type { Apps, Position } from "./AttributesDelegate";
44
36
  import type {
45
37
  Displayer,
46
38
  SceneDefinition,
@@ -54,6 +46,7 @@ import type {
54
46
  Rectangle,
55
47
  ViewVisionMode,
56
48
  CameraState,
49
+ Player,
57
50
  } from "white-web-sdk";
58
51
  import type { AppListeners } from "./AppListener";
59
52
  import type { NetlessApp, RegisterParams } from "./typings";
@@ -125,6 +118,8 @@ export type AppInitState = {
125
118
  zIndex?: number;
126
119
  };
127
120
 
121
+ export type CursorMovePayload = { uid: string; state?: "leave"; position: Position };
122
+
128
123
  export type EmitterEvent = {
129
124
  onCreated: undefined;
130
125
  InitReplay: AppInitState;
@@ -139,6 +134,8 @@ export type EmitterEvent = {
139
134
  boxStateChange: string;
140
135
  playgroundSizeChange: DOMRect;
141
136
  onReconnected: void;
137
+ removeScenes: string;
138
+ cursorMove: CursorMovePayload;
142
139
  };
143
140
 
144
141
  export type EmitterType = Emittery<EmitterEvent>;
@@ -150,10 +147,17 @@ export type PublicEvent = {
150
147
  darkModeChange: boolean;
151
148
  prefersColorSchemeChange: TeleBoxColorScheme;
152
149
  cameraStateChange: CameraState;
150
+ mainViewScenePathChange: string;
151
+ mainViewSceneIndexChange: number;
152
+ focusedChange: string | undefined;
153
+ mainViewScenesLengthChange: number;
154
+ canRedoStepsChange: number;
155
+ canUndoStepsChange: number;
156
+ loadApp: LoadAppEvent;
153
157
  };
154
158
 
155
159
  export type MountParams = {
156
- room: Room;
160
+ room: Room | Player;
157
161
  container?: HTMLElement;
158
162
  /** 白板高宽比例, 默认为 9 / 16 */
159
163
  containerSizeRatio?: number;
@@ -183,7 +187,8 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
183
187
  public static containerSizeRatio = DEFAULT_CONTAINER_RATIO;
184
188
  private static isCreated = false;
185
189
 
186
- public version = version;
190
+ public version = __APP_VERSION__;
191
+ public dependencies = __APP_DEPENDENCIES__;
187
192
 
188
193
  public appListeners?: AppListeners;
189
194
 
@@ -202,6 +207,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
202
207
  constructor(context: InvisiblePluginContext) {
203
208
  super(context);
204
209
  WindowManager.displayer = context.displayer;
210
+ (window as any).NETLESS_DEPS = __APP_DEPENDENCIES__;
205
211
  }
206
212
 
207
213
  public static async mount(params: MountParams): Promise<WindowManager> {
@@ -213,16 +219,22 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
213
219
  const cursor = params.cursor;
214
220
  WindowManager.params = params;
215
221
 
216
- this.checkVersion();
222
+ checkVersion();
223
+ let manager: WindowManager | undefined = undefined;
217
224
  if (isRoom(room)) {
218
225
  if (room.phase !== RoomPhase.Connected) {
219
226
  throw new Error("[WindowManager]: Room only Connected can be mount");
220
227
  }
228
+ if (room.phase === RoomPhase.Connected && room.isWritable) {
229
+ // redo undo 需要设置这个属性
230
+ room.disableSerialization = false;
231
+ }
232
+ manager = await this.initManager(room);
221
233
  }
222
234
  if (WindowManager.isCreated) {
223
235
  throw new Error("[WindowManager]: Already created cannot be created again");
224
236
  }
225
- let manager = await this.initManager(room);
237
+
226
238
  this.debug = Boolean(debug);
227
239
  log("Already insert room", manager);
228
240
 
@@ -233,7 +245,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
233
245
  } else {
234
246
  await pRetry(
235
247
  async count => {
236
- manager = await this.initManager(room);
248
+ manager = (await room.getInvisiblePlugin(WindowManager.kind)) as WindowManager;
237
249
  if (!manager) {
238
250
  log(`manager is empty. retrying ${count}`);
239
251
  throw new Error();
@@ -243,16 +255,17 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
243
255
  );
244
256
  }
245
257
 
258
+ if (!manager) {
259
+ throw new Error("[WindowManager]: create manager failed");
260
+ }
261
+
246
262
  if (containerSizeRatio) {
247
263
  WindowManager.containerSizeRatio = containerSizeRatio;
248
264
  }
249
265
  await manager.ensureAttributes();
250
266
 
251
267
  manager.appManager = new AppManager(manager);
252
-
253
- if (cursor) {
254
- manager.cursorManager = new CursorManager(manager.appManager);
255
- }
268
+ manager.cursorManager = new CursorManager(manager.appManager, Boolean(cursor));
256
269
 
257
270
  if (params.container) {
258
271
  manager.bindContainer(params.container);
@@ -358,6 +371,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
358
371
  this.appManager?.refresh();
359
372
  this.appManager?.resetMaximized();
360
373
  this.appManager?.resetMinimized();
374
+ this.appManager?.displayerWritableListener(!this.room.isWritable);
361
375
  WindowManager.container = container;
362
376
  }
363
377
 
@@ -421,6 +435,12 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
421
435
  const appScenePath = appManager.store.getAppScenePath(appId);
422
436
  if (appScenePath && appScenePath === scenePath) {
423
437
  console.warn(`[WindowManager]: ScenePath ${scenePath} Already opened`);
438
+ if (this.boxManager) {
439
+ const topBox = this.boxManager.getTopBox();
440
+ if (topBox) {
441
+ this.boxManager.setZIndex(appId, topBox.zIndex + 1, false);
442
+ }
443
+ }
424
444
  return;
425
445
  }
426
446
  }
@@ -428,11 +448,11 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
428
448
  if (scenePath && scenes && scenes.length > 0) {
429
449
  if (this.isDynamicPPT(scenes)) {
430
450
  isDynamicPPT = true;
431
- if (!this.displayer.entireScenes()[scenePath]) {
451
+ if (!entireScenes(this.displayer)[scenePath]) {
432
452
  this.room?.putScenes(scenePath, scenes);
433
453
  }
434
454
  } else {
435
- if (!this.displayer.entireScenes()[scenePath]) {
455
+ if (!entireScenes(this.displayer)[scenePath]) {
436
456
  this.room?.putScenes(scenePath, [{ name: scenes[0].name }]);
437
457
  }
438
458
  }
@@ -465,7 +485,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
465
485
  /**
466
486
  * 返回 mainView 的 ScenePath
467
487
  */
468
- public getMainViewScenePath(): string {
488
+ public getMainViewScenePath(): string | undefined {
469
489
  return this.appManager?.store.getMainViewScenePath();
470
490
  }
471
491
 
@@ -513,6 +533,35 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
513
533
  this.viewMode = mode;
514
534
  }
515
535
 
536
+ public setBoxState(boxState: TeleBoxState): void {
537
+ if (!this.canOperate) return;
538
+ switch (boxState) {
539
+ case "normal":
540
+ this.setMaximized(false);
541
+ this.setMinimized(false);
542
+ break;
543
+ case "maximized":
544
+ this.setMaximized(true);
545
+ this.setMinimized(false);
546
+ break;
547
+ case "minimized":
548
+ this.setMinimized(true);
549
+ break;
550
+ default:
551
+ break;
552
+ }
553
+ }
554
+
555
+ public setMaximized(maximized: boolean): void {
556
+ if (!this.canOperate) return;
557
+ this.boxManager?.setMaximized(maximized, false);
558
+ }
559
+
560
+ public setMinimized(minimized: boolean): void {
561
+ if (!this.canOperate) return;
562
+ this.boxManager?.setMinimized(minimized, false);
563
+ }
564
+
516
565
  public get mainView(): View {
517
566
  if (this.appManager) {
518
567
  return this.appManager.mainViewProxy.view;
@@ -561,6 +610,48 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
561
610
  }
562
611
  }
563
612
 
613
+ public get focused(): string | undefined {
614
+ return this.attributes.focus;
615
+ }
616
+
617
+ public get mainViewSceneIndex(): number {
618
+ return this.appManager?.store.getMainViewSceneIndex();
619
+ }
620
+
621
+ public get mainViewSceneDir(): string {
622
+ if (this.appManager) {
623
+ return this.appManager?.getMainViewSceneDir();
624
+ } else {
625
+ throw new AppManagerNotInitError();
626
+ }
627
+ }
628
+
629
+ public get topApp(): string | undefined {
630
+ return this.boxManager?.getTopBox()?.id;
631
+ }
632
+
633
+ public get mainViewScenesLength(): number {
634
+ return this.appManager?.mainViewScenesLength || 0;
635
+ }
636
+
637
+ public get canRedoSteps(): number {
638
+ const focused = this.focused;
639
+ if (focused) {
640
+ return this.appManager?.focusApp?.view?.canRedoSteps || 0;
641
+ } else {
642
+ return this.mainView.canRedoSteps;
643
+ }
644
+ }
645
+
646
+ public get canUndoSteps(): number {
647
+ const focused = this.focused;
648
+ if (focused) {
649
+ return this.appManager?.focusApp?.view?.canUndoSteps || 0;
650
+ } else {
651
+ return this.mainView.canUndoSteps;
652
+ }
653
+ }
654
+
564
655
  /**
565
656
  * 查询所有的 App
566
657
  */
@@ -585,7 +676,14 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
585
676
  public moveCamera(
586
677
  camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }
587
678
  ): void {
679
+ const pureCamera = omit(camera, ["animationMode"]);
680
+ const mainViewCamera = { ...this.mainView.camera };
681
+ if (isEqual({ ...mainViewCamera, ...pureCamera }, mainViewCamera)) return;
588
682
  this.mainView.moveCamera(camera);
683
+ this.appManager?.dispatchInternalEvent(Events.MoveCamera, camera);
684
+ setTimeout(() => {
685
+ this.appManager?.mainViewProxy.setCameraAndSize();
686
+ }, 100);
589
687
  }
590
688
 
591
689
  public moveCameraToContain(
@@ -598,7 +696,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
598
696
  this.appManager?.dispatchInternalEvent(Events.MoveCameraToContain, rectangle);
599
697
  setTimeout(() => {
600
698
  this.appManager?.mainViewProxy.setCameraAndSize();
601
- }, 1000);
699
+ }, 100);
602
700
  }
603
701
 
604
702
  public convertToPointInWorld(point: Point): Point {
@@ -669,18 +767,38 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> {
669
767
  this.appManager?.boxManager?.setPrefersColorScheme(scheme);
670
768
  }
671
769
 
672
- private isDynamicPPT(scenes: SceneDefinition[]) {
673
- const sceneSrc = scenes[0]?.ppt?.src;
674
- return sceneSrc?.startsWith("pptx://");
770
+ public cleanCurrentScene(): void {
771
+ const focused = this.focused;
772
+ if (focused) {
773
+ this.appManager?.focusApp?.view?.cleanCurrentScene();
774
+ } else {
775
+ this.mainView.cleanCurrentScene();
776
+ }
777
+ }
778
+
779
+ public redo(): number {
780
+ const focused = this.focused;
781
+ if (focused) {
782
+ return this.appManager?.focusApp?.view?.redo() || 0;
783
+ } else {
784
+ return this.mainView.redo();
785
+ }
675
786
  }
676
787
 
677
- private static checkVersion() {
678
- const version = getVersionNumber(WhiteVersion);
679
- if (version < getVersionNumber(REQUIRE_VERSION)) {
680
- throw new WhiteWebSDKInvalidError(REQUIRE_VERSION);
788
+ public undo(): number {
789
+ const focused = this.focused;
790
+ if (focused) {
791
+ return this.appManager?.focusApp?.view?.undo() || 0;
792
+ } else {
793
+ return this.mainView.undo();
681
794
  }
682
795
  }
683
796
 
797
+ private isDynamicPPT(scenes: SceneDefinition[]) {
798
+ const sceneSrc = scenes[0]?.ppt?.src;
799
+ return sceneSrc?.startsWith("pptx://");
800
+ }
801
+
684
802
  private async ensureAttributes() {
685
803
  if (isNull(this.attributes)) {
686
804
  await wait(50);
package/src/shim.d.ts CHANGED
@@ -4,3 +4,8 @@ declare module "*.svelte" {
4
4
  const app: SvelteComponent;
5
5
  export default app;
6
6
  }
7
+
8
+ declare global {
9
+ const __APP_VERSION__: string;
10
+ const __APP_DEPENDENCIES__: Record<string, string>;
11
+ }
package/src/style.css CHANGED
@@ -122,7 +122,7 @@
122
122
  left: 0;
123
123
  top: 0;
124
124
  will-change: transform;
125
- transition: transform 0.05s;
125
+ transition: transform 0.1s;
126
126
  transform-origin: 0 0;
127
127
  user-select: none;
128
128
  }
@@ -153,6 +153,11 @@
153
153
  margin-top: 12px;
154
154
  }
155
155
 
156
+ .netless-window-manager-cursor-laserPointer-image {
157
+ margin-left: -22px;
158
+ margin-top: 3px;
159
+ }
160
+
156
161
  .netless-window-manager-cursor-name {
157
162
  width: 100%;
158
163
  height: 48px;
package/src/typings.ts CHANGED
@@ -12,7 +12,7 @@ import type {
12
12
  import type { AppContext } from "./AppContext";
13
13
  import type { ReadonlyTeleBox, TeleBoxRect } from "@netless/telebox-insider";
14
14
 
15
- export interface NetlessApp<Attributes = any, SetupResult = any, AppOptions = any> {
15
+ export interface NetlessApp<Attributes = any, MagixEventPayloads = any, AppOptions = any, SetupResult = any> {
16
16
  kind: string;
17
17
  config?: {
18
18
  /** Box width relative to whiteboard. 0~1. Default 0.5. */
@@ -28,7 +28,7 @@ export interface NetlessApp<Attributes = any, SetupResult = any, AppOptions = an
28
28
  /** App only single instance. */
29
29
  singleton?: boolean;
30
30
  };
31
- setup: (context: AppContext<Attributes, AppOptions>) => SetupResult;
31
+ setup: (context: AppContext<Attributes, MagixEventPayloads, AppOptions>) => SetupResult;
32
32
  }
33
33
 
34
34
  export type AppEmitterEvent<T = any> = {
package/vite.config.js CHANGED
@@ -1,13 +1,19 @@
1
1
  import path from "path";
2
2
  import { defineConfig } from "vite";
3
3
  import { svelte } from "@sveltejs/vite-plugin-svelte";
4
- import { dependencies ,peerDependencies } from "./package.json"
4
+ import { dependencies, peerDependencies, version, devDependencies } from "./package.json"
5
5
 
6
6
 
7
7
  export default defineConfig(({ mode }) => {
8
8
  const isProd = mode === "production";
9
9
 
10
10
  return {
11
+ define: {
12
+ __APP_VERSION__: JSON.stringify(version),
13
+ __APP_DEPENDENCIES__: JSON.stringify({
14
+ dependencies, peerDependencies, devDependencies
15
+ }),
16
+ },
11
17
  plugins: [
12
18
  svelte({
13
19
  emitCss: false,
@@ -20,7 +26,7 @@ export default defineConfig(({ mode }) => {
20
26
  lib: {
21
27
  // eslint-disable-next-line no-undef
22
28
  entry: path.resolve(__dirname, "src/index.ts"),
23
- formats: ["es","umd"], // TODO cjs 版本待修复
29
+ formats: ["es", "umd"], // TODO cjs 版本待修复
24
30
  name: "WindowManager",
25
31
  fileName: "index"
26
32
  },
@@ -1,26 +0,0 @@
1
- import type { AppContext } from "../../AppContext";
2
- import type { Diff } from "./typings";
3
- import { StorageEvent } from "./StorageEvent";
4
- export * from './typings';
5
- export declare class Storage<TState = any> implements Storage<TState> {
6
- readonly id: string;
7
- private readonly _context;
8
- private readonly _sideEffect;
9
- private _state;
10
- private _destroyed;
11
- private _refMap;
12
- /**
13
- * `setState` alters local state immediately before sending to server. This will cache the old value for onStateChanged diffing.
14
- */
15
- private _lastValue;
16
- constructor(context: AppContext<any>, id: string, defaultState?: TState);
17
- get state(): Readonly<TState>;
18
- readonly onStateChanged: StorageEvent<Diff<TState>>;
19
- ensureState(state: Partial<TState>): void;
20
- setState(state: Partial<TState>): void;
21
- emptyStore(): void;
22
- deleteStore(): void;
23
- get destroyed(): boolean;
24
- destroy(): void;
25
- private _updateProperties;
26
- }
@@ -1,46 +0,0 @@
1
- import { autorun, listenDisposed, listenUpdated, reaction, unlistenDisposed, unlistenUpdated, toJS } from 'white-web-sdk';
2
- import type { Room, SceneDefinition, View } from "white-web-sdk";
3
- import type { ReadonlyTeleBox } from "@netless/telebox-insider";
4
- import type Emittery from "emittery";
5
- import type { BoxManager } from "./BoxManager";
6
- import type { AppEmitterEvent } from "./index";
7
- import type { AppManager } from "./AppManager";
8
- import type { AppProxy } from "./AppProxy";
9
- import { Storage } from './App/Storage';
10
- export declare class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
11
- private manager;
12
- private boxManager;
13
- appId: string;
14
- private appProxy;
15
- private appOptions?;
16
- readonly emitter: Emittery<AppEmitterEvent<TAttrs>>;
17
- readonly mobxUtils: {
18
- autorun: typeof autorun;
19
- reaction: typeof reaction;
20
- toJS: typeof toJS;
21
- };
22
- readonly objectUtils: {
23
- listenUpdated: typeof listenUpdated;
24
- unlistenUpdated: typeof unlistenUpdated;
25
- listenDisposed: typeof listenDisposed;
26
- unlistenDisposed: typeof unlistenDisposed;
27
- };
28
- private store;
29
- readonly isAddApp: boolean;
30
- readonly isReplay: boolean;
31
- constructor(manager: AppManager, boxManager: BoxManager, appId: string, appProxy: AppProxy, appOptions?: AppOptions | (() => AppOptions) | undefined);
32
- getDisplayer(): import("white-web-sdk").Displayer<import("white-web-sdk").DisplayerCallbacks>;
33
- getAttributes(): TAttrs | undefined;
34
- getScenes(): SceneDefinition[] | undefined;
35
- getView(): View | undefined;
36
- getInitScenePath(): string | undefined;
37
- getIsWritable(): boolean;
38
- getBox(): ReadonlyTeleBox;
39
- getRoom(): Room | undefined;
40
- setAttributes(attributes: TAttrs): void;
41
- updateAttributes(keys: string[], value: any): void;
42
- setScenePath(scenePath: string): Promise<void>;
43
- mountView(dom: HTMLDivElement): void;
44
- getAppOptions(): AppOptions | undefined;
45
- createStorage<TState>(storeId: string, defaultState?: TState): Storage<TState>;
46
- }
@@ -1,12 +0,0 @@
1
- import type { AppManager } from "../AppManager";
2
- export declare class Context {
3
- private manager;
4
- observerId: number;
5
- constructor(manager: AppManager);
6
- get uid(): string;
7
- findMember: (memberId: number) => import("white-web-sdk").RoomMember | undefined;
8
- findMemberByUid: (uid: string) => import("white-web-sdk").RoomMember | undefined;
9
- updateManagerRect(): void;
10
- blurFocusBox(): void;
11
- }
12
- export declare const createContext: (manager: AppManager) => Context;