@netless/window-manager 0.4.0-canary.15 → 0.4.0-canary.19

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 (52) 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 +29 -1
  7. package/dist/AppListener.d.ts +1 -0
  8. package/dist/AppManager.d.ts +8 -6
  9. package/dist/AppProxy.d.ts +3 -2
  10. package/dist/AttributesDelegate.d.ts +2 -2
  11. package/dist/BoxManager.d.ts +5 -3
  12. package/dist/BuiltinApps.d.ts +0 -1
  13. package/dist/Cursor/Cursor.d.ts +8 -11
  14. package/dist/Cursor/index.d.ts +5 -16
  15. package/dist/Register/storage.d.ts +5 -1
  16. package/dist/Utils/Common.d.ts +1 -0
  17. package/dist/Utils/RoomHacker.d.ts +1 -1
  18. package/dist/View/MainView.d.ts +4 -3
  19. package/dist/constants.d.ts +3 -2
  20. package/dist/index.d.ts +15 -2
  21. package/dist/index.es.js +41 -1
  22. package/dist/index.es.js.map +1 -1
  23. package/dist/index.umd.js +41 -1
  24. package/dist/index.umd.js.map +1 -1
  25. package/dist/style.css +1 -1
  26. package/docs/api.md +28 -0
  27. package/docs/concept.md +5 -0
  28. package/package.json +5 -5
  29. package/src/AppContext.ts +1 -4
  30. package/src/AppListener.ts +14 -6
  31. package/src/AppManager.ts +62 -33
  32. package/src/AppProxy.ts +13 -8
  33. package/src/AttributesDelegate.ts +2 -2
  34. package/src/BoxManager.ts +33 -19
  35. package/src/BuiltinApps.ts +0 -1
  36. package/src/Cursor/Cursor.ts +22 -36
  37. package/src/Cursor/index.ts +33 -139
  38. package/src/Register/index.ts +25 -16
  39. package/src/Register/loader.ts +1 -1
  40. package/src/Register/storage.ts +6 -1
  41. package/src/Utils/Common.ts +12 -2
  42. package/src/Utils/RoomHacker.ts +28 -15
  43. package/src/View/MainView.ts +17 -12
  44. package/src/constants.ts +3 -2
  45. package/src/index.ts +52 -3
  46. package/src/shim.d.ts +2 -1
  47. package/src/style.css +1 -1
  48. package/vite.config.js +5 -2
  49. package/dist/Base/Context.d.ts +0 -12
  50. package/dist/Base/index.d.ts +0 -7
  51. package/src/Base/Context.ts +0 -45
  52. package/src/Base/index.ts +0 -10
@@ -1,42 +1,34 @@
1
- import App from './Cursor.svelte';
2
- import { ApplianceMap } from './icons';
3
- import { ApplianceNames } from 'white-web-sdk';
4
- import { CursorState } from '../constants';
5
- import { Fields } from '../AttributesDelegate';
6
- import { get, omit } from 'lodash';
7
- import type { Position } from '../AttributesDelegate';
1
+ import App from "./Cursor.svelte";
2
+ import { ApplianceMap } from "./icons";
3
+ import { ApplianceNames } from "white-web-sdk";
4
+ import { omit } from "lodash";
5
+ import type { Position } from "../AttributesDelegate";
8
6
  import type { RoomMember } from "white-web-sdk";
9
7
  import type { CursorManager } from "./index";
10
8
  import type { SvelteComponent } from "svelte";
11
- import { Base } from '../Base';
12
- import type { AppManager } from '../AppManager';
9
+ import type { AppManager } from "../AppManager";
13
10
 
14
11
  export type Payload = {
15
- [key: string]: any
16
- }
17
-
12
+ [key: string]: any;
13
+ };
18
14
 
19
- export class Cursor extends Base {
15
+ export class Cursor {
20
16
  private member?: RoomMember;
21
17
  private timer?: number;
22
18
  private component?: SvelteComponent;
23
19
 
24
20
  constructor(
25
- manager: AppManager,
26
- addCursorChangeListener: (uid: string, callback: (position: Position, state: CursorState) => void) => void,
27
- private cursors: any,
21
+ private manager: AppManager,
28
22
  private memberId: string,
29
23
  private cursorManager: CursorManager,
30
- private wrapper?: HTMLElement,
24
+ private wrapper?: HTMLElement
31
25
  ) {
32
- super(manager);
33
26
  this.setMember();
34
27
  this.createCursor();
35
- addCursorChangeListener(this.memberId, this.onCursorChange);
36
28
  this.autoHidden();
37
29
  }
38
30
 
39
- private onCursorChange = (position: Position, state: CursorState) => {
31
+ public move = (position: Position) => {
40
32
  if (position.type === "main") {
41
33
  const rect = this.cursorManager.wrapperRect;
42
34
  if (this.component && rect) {
@@ -45,7 +37,6 @@ export class Cursor extends Base {
45
37
  }
46
38
  } else {
47
39
  const focusView = this.cursorManager.focusView;
48
- // TODO 可以存一个当前 focusView 的 Rect 这样只有 focus 切换的时候才调用 getBoundingClientRect
49
40
  const viewRect = focusView?.divElement?.getBoundingClientRect();
50
41
  const viewCamera = focusView?.camera;
51
42
  if (focusView && viewRect && viewCamera && this.component) {
@@ -53,10 +44,11 @@ export class Cursor extends Base {
53
44
  this.moveCursor(position, viewRect, focusView);
54
45
  }
55
46
  }
56
- if (state && state === CursorState.Leave) {
57
- this.hide();
58
- }
59
- }
47
+ };
48
+
49
+ public leave = () => {
50
+ this.hide();
51
+ };
60
52
 
61
53
  private moveCursor(cursor: Position, rect: DOMRect, view: any) {
62
54
  const { x, y, type } = cursor;
@@ -124,21 +116,12 @@ export class Cursor extends Base {
124
116
  }
125
117
  }
126
118
 
127
- public get cursorState(): CursorState | undefined {
128
- return get(this.cursors, [this.memberId, Fields.CursorState]);
129
- }
130
-
131
- public get cursorPosition(): Position | undefined {
132
- return get(this.cursors, [this.memberId, Fields.Position]);
133
- }
134
-
135
119
  private autoHidden() {
136
120
  if (this.timer) {
137
121
  clearTimeout(this.timer);
138
122
  }
139
123
  this.timer = window.setTimeout(() => {
140
124
  this.hide();
141
- this.store.updateCursorState(this.memberId, CursorState.Leave);
142
125
  }, 1000 * 10); // 10 秒钟自动隐藏
143
126
  }
144
127
 
@@ -176,7 +159,7 @@ export class Cursor extends Base {
176
159
  }
177
160
 
178
161
  public setMember() {
179
- this.member = this.context.findMemberByUid(this.memberId);
162
+ this.member = this.manager.findMemberByUid(this.memberId);
180
163
  this.updateComponent();
181
164
  }
182
165
 
@@ -188,13 +171,16 @@ export class Cursor extends Base {
188
171
  if (this.component) {
189
172
  this.component.$destroy();
190
173
  }
191
- this.manager.refresher?.remove(this.memberId);
192
174
  this.cursorManager.cursorInstances.delete(this.memberId);
175
+ if (this.timer) {
176
+ clearTimeout(this.timer);
177
+ }
193
178
  }
194
179
 
195
180
  public hide() {
196
181
  if (this.component) {
197
182
  this.component.$set({ visible: false });
183
+ this.destroy();
198
184
  }
199
185
  }
200
186
  }
@@ -1,13 +1,10 @@
1
- import { autorun } from "white-web-sdk";
2
- import { Base } from "../Base";
3
- import { compact, debounce, get, uniq } from "lodash";
1
+ import { throttle } from "lodash";
4
2
  import { Cursor } from "./Cursor";
5
- import { CursorState } from "../constants";
3
+ import { CursorState, Events } from "../constants";
6
4
  import { emitter, WindowManager } from "../index";
7
- import { Fields } from "../AttributesDelegate";
8
- import { onObjectInserted } from "../Utils/Reactive";
9
5
  import { SideEffectManager } from "side-effect-manager";
10
- import type { PositionType, Position } from "../AttributesDelegate";
6
+ import type { CursorMovePayload } from "../index";
7
+ import type { PositionType } from "../AttributesDelegate";
11
8
  import type { Point, RoomMember, View } from "white-web-sdk";
12
9
  import type { AppManager } from "../AppManager";
13
10
 
@@ -21,30 +18,36 @@ export type MoveCursorParams = {
21
18
  x: number;
22
19
  y: number;
23
20
  };
24
- export class CursorManager extends Base {
21
+ export class CursorManager {
25
22
  public containerRect?: DOMRect;
26
23
  public wrapperRect?: DOMRect;
27
24
  public cursorInstances: Map<string, Cursor> = new Map();
28
25
  public roomMembers?: readonly RoomMember[];
29
26
  private mainViewElement?: HTMLDivElement;
30
27
  private sideEffectManager = new SideEffectManager();
28
+ private store = this.manager.store;
31
29
 
32
- constructor(private appManager: AppManager) {
33
- super(appManager);
34
- this.roomMembers = this.appManager.room?.state.roomMembers;
30
+ constructor(private manager: AppManager) {
31
+ this.roomMembers = this.manager.room?.state.roomMembers;
35
32
  const wrapper = WindowManager.wrapper;
36
33
  if (wrapper) {
37
34
  this.setupWrapper(wrapper);
38
35
  }
39
- emitter.on("onReconnected", () => {
40
- this.onReconnect();
36
+ emitter.on("cursorMove", payload => {
37
+ let cursorInstance = this.cursorInstances.get(payload.uid);
38
+ if (!cursorInstance) {
39
+ cursorInstance = new Cursor(this.manager, payload.uid, this, WindowManager.wrapper);
40
+ this.cursorInstances.set(payload.uid, cursorInstance);
41
+ }
42
+ if (payload.state === CursorState.Leave) {
43
+ cursorInstance.leave();
44
+ } else {
45
+ cursorInstance.move(payload.position);
46
+ }
41
47
  });
42
48
  }
43
49
 
44
50
  public setupWrapper(wrapper: HTMLElement) {
45
- if (this.manager.refresher?.hasReactor("cursors")) {
46
- this.destroy();
47
- }
48
51
  this.sideEffectManager.add(() => {
49
52
  wrapper.addEventListener("pointerenter", this.mouseMoveListener);
50
53
  wrapper.addEventListener("pointermove", this.mouseMoveListener);
@@ -56,77 +59,38 @@ export class CursorManager extends Base {
56
59
  };
57
60
  });
58
61
 
59
- this.initCursorAttributes();
60
62
  this.wrapperRect = wrapper.getBoundingClientRect();
61
- this.startReaction(wrapper);
62
63
  }
63
64
 
64
65
  public setMainViewDivElement(div: HTMLDivElement) {
65
66
  this.mainViewElement = div;
66
67
  }
67
68
 
68
- private startReaction(wrapper: HTMLElement) {
69
- this.manager.refresher?.add("cursors", () => {
70
- return onObjectInserted(this.cursors, () => {
71
- this.handleRoomMembersChange(wrapper);
72
- });
73
- });
74
- }
75
-
76
- private getUids = (members: readonly RoomMember[] | undefined) => {
77
- return compact(uniq(members?.map(member => member.payload?.uid)));
78
- };
79
-
80
- private handleRoomMembersChange = debounce((wrapper: HTMLElement) => {
81
- const uids = this.getUids(this.roomMembers);
82
- const cursors = Object.keys(this.cursors);
83
- if (uids?.length) {
84
- cursors.map(uid => {
85
- if (uids.includes(uid) && !this.cursorInstances.has(uid)) {
86
- if (uid === this.context.uid) {
87
- return;
88
- }
89
- const component = new Cursor(
90
- this.appManager,
91
- this.addCursorChangeListener,
92
- this.cursors,
93
- uid,
94
- this,
95
- wrapper
96
- );
97
- this.cursorInstances.set(uid, component);
98
- }
99
- });
100
- }
101
- }, 100);
102
-
103
- public get cursors() {
104
- return this.manager.attributes?.[Fields.Cursors];
105
- }
106
-
107
69
  public get boxState() {
108
70
  return this.store.getBoxState();
109
71
  }
110
72
 
111
73
  public get focusView() {
112
- return this.appManager.focusApp?.view;
74
+ return this.manager.focusApp?.view;
113
75
  }
114
76
 
115
- private mouseMoveListener = debounce((event: MouseEvent) => {
77
+ private mouseMoveListener = throttle((event: MouseEvent) => {
116
78
  this.updateCursor(this.getType(event), event.clientX, event.clientY);
117
- }, 5);
79
+ }, 16);
118
80
 
119
81
  private updateCursor(event: EventType, clientX: number, clientY: number) {
120
82
  if (this.wrapperRect && this.manager.canOperate) {
121
- const view = event.type === "main" ? this.appManager.mainView : this.focusView;
83
+ const view = event.type === "main" ? this.manager.mainView : this.focusView;
122
84
  const point = this.getPoint(view, clientX, clientY);
123
85
  if (point) {
124
- this.setNormalCursorState();
125
- this.store.updateCursor(this.context.uid, {
126
- x: point.x,
127
- y: point.y,
128
- ...event,
129
- });
86
+ this.manager.dispatchInternalEvent(Events.CursorMove, {
87
+ uid: this.manager.uid,
88
+ position: {
89
+ x: point.x,
90
+ y: point.y,
91
+ type: event.type,
92
+ },
93
+ } as CursorMovePayload);
130
94
  }
131
95
  }
132
96
  }
@@ -151,7 +115,7 @@ export class CursorManager extends Base {
151
115
  */
152
116
  private getType = (event: MouseEvent | Touch): EventType => {
153
117
  const target = event.target as HTMLElement;
154
- const focusApp = this.appManager.focusApp;
118
+ const focusApp = this.manager.focusApp;
155
119
  switch (target.parentElement) {
156
120
  case this.mainViewElement: {
157
121
  return { type: "main" };
@@ -165,25 +129,8 @@ export class CursorManager extends Base {
165
129
  }
166
130
  };
167
131
 
168
- private initCursorAttributes() {
169
- this.store.updateCursor(this.context.uid, {
170
- x: 0,
171
- y: 0,
172
- type: "main",
173
- });
174
- this.store.updateCursorState(this.context.uid, CursorState.Leave);
175
- }
176
-
177
- private setNormalCursorState() {
178
- const cursorState = this.store.getCursorState(this.context.uid);
179
- if (cursorState !== CursorState.Normal) {
180
- this.store.updateCursorState(this.context.uid, CursorState.Normal);
181
- }
182
- }
183
-
184
132
  private mouseLeaveListener = () => {
185
- this.hideCursor(this.context.uid);
186
- this.store.updateCursorState(this.context.uid, CursorState.Leave);
133
+ this.hideCursor(this.manager.uid);
187
134
  };
188
135
 
189
136
  public updateContainerRect() {
@@ -191,16 +138,6 @@ export class CursorManager extends Base {
191
138
  this.wrapperRect = WindowManager.wrapper?.getBoundingClientRect();
192
139
  }
193
140
 
194
- public setRoomMembers(members: readonly RoomMember[]) {
195
- this.roomMembers = members;
196
- this.cursorInstances.forEach(cursor => {
197
- cursor.setMember();
198
- });
199
- if (WindowManager.wrapper) {
200
- this.handleRoomMembersChange(WindowManager.wrapper);
201
- }
202
- }
203
-
204
141
  public deleteCursor(uid: string) {
205
142
  this.store.cleanCursor(uid);
206
143
  const cursor = this.cursorInstances.get(uid);
@@ -216,48 +153,6 @@ export class CursorManager extends Base {
216
153
  }
217
154
  }
218
155
 
219
- public cleanMemberAttributes(members: readonly RoomMember[]) {
220
- const uids = this.getUids(members);
221
- const needDeleteIds: string[] = [];
222
- const cursors = Object.keys(this.cursors);
223
- cursors.map(cursorId => {
224
- const index = uids.findIndex(id => id === cursorId);
225
- if (index === -1) {
226
- needDeleteIds.push(cursorId);
227
- }
228
- });
229
- needDeleteIds.forEach(uid => {
230
- this.deleteCursor(uid);
231
- });
232
- }
233
-
234
- public onReconnect() {
235
- if (this.cursorInstances.size) {
236
- this.cursorInstances.forEach(cursor => cursor.destroy());
237
- this.cursorInstances.clear();
238
- }
239
- this.roomMembers = this.appManager.room?.state.roomMembers;
240
- if (WindowManager.wrapper) {
241
- this.handleRoomMembersChange(WindowManager.wrapper);
242
- }
243
- }
244
-
245
- public addCursorChangeListener = (
246
- uid: string,
247
- callback: (position: Position, state: CursorState) => void
248
- ) => {
249
- this.manager.refresher?.add(uid, () => {
250
- const disposer = autorun(() => {
251
- const position = get(this.cursors, [uid, Fields.Position]);
252
- const state = get(this.cursors, [uid, Fields.CursorState]);
253
- if (position) {
254
- callback(position, state);
255
- }
256
- });
257
- return disposer;
258
- });
259
- };
260
-
261
156
  public destroy() {
262
157
  this.sideEffectManager.flushAll();
263
158
  if (this.cursorInstances.size) {
@@ -266,6 +161,5 @@ export class CursorManager extends Base {
266
161
  });
267
162
  this.cursorInstances.clear();
268
163
  }
269
- this.manager.refresher?.remove("cursors");
270
164
  }
271
165
  }
@@ -10,34 +10,39 @@ class AppRegister {
10
10
 
11
11
  public async register(params: RegisterParams): Promise<void> {
12
12
  this.registered.set(params.kind, params);
13
-
14
- const srcOrAppOrFunction = params.src
15
- let downloadApp: () => Promise<NetlessApp>
16
-
13
+
14
+ const srcOrAppOrFunction = params.src;
15
+ let downloadApp: () => Promise<NetlessApp>;
16
+
17
17
  if (typeof srcOrAppOrFunction === "string") {
18
18
  downloadApp = async () => {
19
- const appClass = await loadApp(srcOrAppOrFunction, params.kind);
19
+ let appClass = (await loadApp(srcOrAppOrFunction, params.kind)) as any;
20
20
  if (appClass) {
21
- return appClass
21
+ if (appClass.__esModule) {
22
+ appClass = appClass.default;
23
+ }
24
+ return appClass;
22
25
  } else {
23
- throw new Error(`[WindowManager]: load remote script failed, ${srcOrAppOrFunction}`);
26
+ throw new Error(
27
+ `[WindowManager]: load remote script failed, ${srcOrAppOrFunction}`
28
+ );
24
29
  }
25
- }
30
+ };
26
31
  } else if (typeof srcOrAppOrFunction === "function") {
27
- downloadApp = srcOrAppOrFunction
32
+ downloadApp = srcOrAppOrFunction;
28
33
  } else {
29
- downloadApp = async () => srcOrAppOrFunction
34
+ downloadApp = async () => srcOrAppOrFunction;
30
35
  }
31
36
 
32
37
  this.appClasses.set(params.kind, async () => {
33
- let app = this.appClassesCache.get(params.kind)
38
+ let app = this.appClassesCache.get(params.kind);
34
39
  if (!app) {
35
- app = downloadApp()
36
- this.appClassesCache.set(params.kind, app)
40
+ app = downloadApp();
41
+ this.appClassesCache.set(params.kind, app);
37
42
  }
38
- return app
43
+ return app;
39
44
  });
40
-
45
+
41
46
  if (params.addHooks) {
42
47
  const emitter = this.createKindEmitter(params.kind);
43
48
  if (emitter) {
@@ -46,7 +51,11 @@ class AppRegister {
46
51
  }
47
52
  }
48
53
 
49
- public async notifyApp<T extends keyof RegisterEvents>(kind: string, event: T, payload: RegisterEvents[T]) {
54
+ public async notifyApp<T extends keyof RegisterEvents>(
55
+ kind: string,
56
+ event: T,
57
+ payload: RegisterEvents[T]
58
+ ) {
50
59
  const emitter = this.kindEmitters.get(kind);
51
60
  await emitter?.emit(event, payload);
52
61
  }
@@ -8,7 +8,7 @@ const TIMEOUT = 10000; // 10 秒超时
8
8
  export const getScript = async (url: string): Promise<string> => {
9
9
  const item = await getItem(url);
10
10
  if (item) {
11
- return item;
11
+ return item.sourceCode;
12
12
  } else {
13
13
  const result = await fetchWithTimeout(url, { timeout: TIMEOUT });
14
14
  const text = await result.text();
@@ -3,6 +3,11 @@ const DatabaseName = "__WindowManagerAppCache";
3
3
  let db: IDBDatabase;
4
4
  let store: IDBObjectStore;
5
5
 
6
+ export type Item = {
7
+ kind: string;
8
+ sourceCode: string;
9
+ }
10
+
6
11
  export const initDb = async () => {
7
12
  db = await createDb();
8
13
  }
@@ -12,7 +17,7 @@ export const setItem = (key: string, val: any) => {
12
17
  return addRecord(db, { kind: key, sourceCode: val })
13
18
  };
14
19
 
15
- export const getItem = async (key: string): Promise<string | null> => {
20
+ export const getItem = async (key: string): Promise<Item | null> => {
16
21
  if (!db) return null;
17
22
  return await query(db, key);
18
23
  };
@@ -1,6 +1,7 @@
1
1
  import { appRegister } from "../Register";
2
2
  import { debounce } from "lodash";
3
3
  import { emitter } from "../index";
4
+ import { ScenePathType } from "white-web-sdk";
4
5
  import { v4 } from "uuid";
5
6
  import type { PublicEvent } from "../index";
6
7
  import type { Displayer, ViewVisionMode, Room, View } from "white-web-sdk";
@@ -26,7 +27,7 @@ export const setViewSceneIndex = (view: View, index: number) => {
26
27
  view.focusSceneIndex = index;
27
28
  return view;
28
29
  }
29
- }
30
+ };
30
31
 
31
32
  export const setScenePath = (room: Room | undefined, scenePath: string) => {
32
33
  if (room && room.isWritable) {
@@ -50,6 +51,15 @@ export const getScenePath = (
50
51
  }
51
52
  };
52
53
 
54
+ export const removeScenes = (room: Room | undefined, scenePath: string) => {
55
+ if (room) {
56
+ const type = room.scenePathType(scenePath);
57
+ if (type !== ScenePathType.None) {
58
+ room.removeScenes(scenePath);
59
+ }
60
+ }
61
+ };
62
+
53
63
  export const setViewMode = (view: View, mode: ViewVisionMode) => {
54
64
  if (!(view as any).didRelease && view.mode !== mode) {
55
65
  view.mode = mode;
@@ -105,7 +115,7 @@ export const parseSceneDir = (scenePath: string) => {
105
115
  sceneDir = "/";
106
116
  }
107
117
  return sceneDir;
108
- }
118
+ };
109
119
 
110
120
  export const ensureValidScenePath = (scenePath: string) => {
111
121
  if (scenePath.endsWith("/")) {
@@ -1,22 +1,13 @@
1
1
  import { emitter } from "../index";
2
2
  import { isPlayer } from "white-web-sdk";
3
- import type { WindowManager } from '../index';
4
- import type { Camera, Room , Player , PlayerSeekingResult } from "white-web-sdk";
3
+ import type { WindowManager } from "../index";
4
+ import type { Camera, Room, Player, PlayerSeekingResult } from "white-web-sdk";
5
5
 
6
6
  // 修改多窗口状态下一些失效的方法实现到 manager 的 mainview 上, 降低迁移成本
7
7
  export const replaceRoomFunction = (room: Room, manager: WindowManager) => {
8
8
  if (isPlayer(room)) {
9
9
  const player = room as unknown as Player;
10
- const originSeek = player.seekToProgressTime;
11
- // eslint-disable-next-line no-inner-declarations
12
- async function newSeek(time: number): Promise<PlayerSeekingResult> {
13
- const seekResult = await originSeek.call(player, time);
14
- if (seekResult === "success") {
15
- emitter.emit("seek", time);
16
- }
17
- return seekResult;
18
- }
19
- player.seekToProgressTime = newSeek;
10
+ delegateSeekToProgressTime(player);
20
11
  } else {
21
12
  const descriptor = Object.getOwnPropertyDescriptor(room, "disableCameraTransform");
22
13
  if (descriptor) return;
@@ -32,13 +23,13 @@ export const replaceRoomFunction = (room: Room, manager: WindowManager) => {
32
23
  Object.defineProperty(room, "canUndoSteps", {
33
24
  get() {
34
25
  return manager.mainView.canUndoSteps;
35
- }
26
+ },
36
27
  });
37
28
 
38
29
  Object.defineProperty(room, "canRedoSteps", {
39
30
  get() {
40
31
  return manager.mainView.canRedoSteps;
41
- }
32
+ },
42
33
  });
43
34
 
44
35
  room.moveCamera = (camera: Camera) => manager.mainView.moveCamera(camera);
@@ -52,6 +43,28 @@ export const replaceRoomFunction = (room: Room, manager: WindowManager) => {
52
43
  room.redo = () => manager.mainView.redo();
53
44
  room.undo = () => manager.mainView.undo();
54
45
  room.cleanCurrentScene = () => manager.mainView.cleanCurrentScene();
46
+ delegateRemoveScenes(room);
55
47
  }
48
+ };
56
49
 
57
- };
50
+ const delegateRemoveScenes = (room: Room) => {
51
+ const originRemoveScenes = room.removeScenes;
52
+ room.removeScenes = (scenePath: string) => {
53
+ const result = originRemoveScenes.call(room, scenePath);
54
+ emitter.emit("removeScenes", scenePath);
55
+ return result;
56
+ };
57
+ };
58
+
59
+ const delegateSeekToProgressTime = (player: Player) => {
60
+ const originSeek = player.seekToProgressTime;
61
+ // eslint-disable-next-line no-inner-declarations
62
+ async function newSeek(time: number): Promise<PlayerSeekingResult> {
63
+ const seekResult = await originSeek.call(player, time);
64
+ if (seekResult === "success") {
65
+ emitter.emit("seek", time);
66
+ }
67
+ return seekResult;
68
+ }
69
+ player.seekToProgressTime = newSeek;
70
+ };
@@ -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,17 +8,16 @@ 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(() => {
@@ -62,15 +60,15 @@ export class MainViewProxy extends Base {
62
60
  }
63
61
 
64
62
  public setCameraAndSize(): void {
65
- this.store.setMainViewCamera({ ...this.mainView.camera, id: this.context.uid });
66
- 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 });
67
65
  }
68
66
 
69
67
  private cameraReaction = () => {
70
68
  return reaction(
71
69
  () => this.mainViewCamera,
72
70
  camera => {
73
- if (camera && camera.id !== this.context.uid) {
71
+ if (camera && camera.id !== this.manager.uid) {
74
72
  this.moveCameraToContian(this.mainViewSize);
75
73
  this.moveCamera(camera);
76
74
  }
@@ -105,9 +103,16 @@ export class MainViewProxy extends Base {
105
103
  return mainView;
106
104
  }
107
105
 
106
+ public onReconnect(): void {
107
+ const mainViewScenePath = this.store.getMainViewScenePath();
108
+ if (mainViewScenePath) {
109
+ setViewFocusScenePath(this.view, mainViewScenePath);
110
+ }
111
+ }
112
+
108
113
  private onCameraUpdatedByDevice = (camera: Camera) => {
109
- this.store.setMainViewCamera({ ...camera, id: this.context.uid });
110
- 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 })) {
111
116
  this.setMainViewSize(this.view.size);
112
117
  }
113
118
  };
@@ -135,11 +140,11 @@ export class MainViewProxy extends Base {
135
140
  public async mainViewClickHandler(): Promise<void> {
136
141
  if (!this.manager.canOperate) return;
137
142
  this.store.cleanFocus();
138
- this.context.blurFocusBox();
143
+ this.manager.boxManager?.blurAllBox();
139
144
  }
140
145
 
141
146
  public setMainViewSize = debounce(size => {
142
- this.store.setMainViewSize({ ...size, id: this.context.uid });
147
+ this.store.setMainViewSize({ ...size, id: this.manager.uid });
143
148
  }, 50);
144
149
 
145
150
  private addCameraListener() {