@netless/window-manager 0.3.17-canary.1 → 0.4.0-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.
package/src/BoxManager.ts CHANGED
@@ -1,22 +1,22 @@
1
- import { callbacks, emitter, WindowManager } from "./index";
2
- import { debounce, maxBy } from "lodash";
3
1
  import { AppAttributes, DEFAULT_COLLECTOR_STYLE, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
2
+ import { debounce, maxBy } from "lodash";
4
3
  import {
5
4
  TELE_BOX_MANAGER_EVENT,
6
5
  TELE_BOX_STATE,
7
6
  TeleBoxCollector,
8
7
  TeleBoxManager,
9
8
  } from "@netless/telebox-insider";
10
- import type { AddAppOptions, AppInitState } from "./index";
9
+ import { WindowManager } from "./index";
10
+ import type { AddAppOptions, AppInitState, EmitterType, CallbacksType } from "./index";
11
11
  import type {
12
12
  TeleBoxManagerUpdateConfig,
13
13
  TeleBoxManagerCreateConfig,
14
14
  ReadonlyTeleBox,
15
15
  TeleBoxManagerConfig,
16
16
  TeleBoxColorScheme,
17
+ TeleBoxRect,
17
18
  } from "@netless/telebox-insider";
18
19
  import type Emittery from "emittery";
19
- import type { AppManager } from "./AppManager";
20
20
  import type { NetlessApp } from "./typings";
21
21
  import type { View } from "white-web-sdk";
22
22
 
@@ -48,27 +48,63 @@ export type CreateTeleBoxManagerConfig = {
48
48
  prefersColorScheme?: TeleBoxColorScheme;
49
49
  };
50
50
 
51
+ export type BoxManagerContext = {
52
+ safeSetAttributes: (attributes: any) => void;
53
+ getMainView: () => View;
54
+ updateAppState: (appId: string, field: AppAttributes, value: any) => void;
55
+ emitter: EmitterType;
56
+ callbacks: CallbacksType;
57
+ canOperate: () => boolean;
58
+ notifyContainerRectUpdate: (rect: TeleBoxRect) => void;
59
+ cleanFocus: () => void;
60
+ };
61
+
62
+ export const createBoxManager = (
63
+ manager: WindowManager,
64
+ callbacks: CallbacksType,
65
+ emitter: EmitterType,
66
+ options: CreateTeleBoxManagerConfig
67
+ ) => {
68
+ return new BoxManager(
69
+ {
70
+ safeSetAttributes: (attributes: any) => manager.safeSetAttributes(attributes),
71
+ getMainView: () => manager.mainView,
72
+ updateAppState: (...args) => manager.appManager?.store.updateAppState(...args),
73
+ canOperate: () => manager.canOperate,
74
+ notifyContainerRectUpdate: (rect: TeleBoxRect) =>
75
+ manager.appManager?.notifyContainerRectUpdate(rect),
76
+ cleanFocus: () => manager.appManager?.store.cleanFocus(),
77
+ callbacks,
78
+ emitter,
79
+ },
80
+ options
81
+ );
82
+ };
83
+
51
84
  export class BoxManager {
52
85
  public teleBoxManager: TeleBoxManager;
53
- public appBoxMap: Map<string, string> = new Map();
54
- private mainView = this.manager.mainView;
55
86
 
56
87
  constructor(
57
- private manager: AppManager,
58
- createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
88
+ private context: BoxManagerContext,
89
+ private createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
59
90
  ) {
91
+ const { emitter, callbacks } = context;
60
92
  this.teleBoxManager = this.setupBoxManager(createTeleBoxManagerConfig);
61
93
  this.teleBoxManager.events.on(TELE_BOX_MANAGER_EVENT.State, state => {
62
94
  if (state) {
63
- callbacks.emit("boxStateChange", state);
64
- emitter.emit("boxStateChange", state);
95
+ this.context.callbacks.emit("boxStateChange", state);
96
+ this.context.emitter.emit("boxStateChange", state);
65
97
  }
66
98
  });
67
99
  this.teleBoxManager.events.on("minimized", minimized => {
68
- this.manager.safeSetAttributes({ minimized });
100
+ this.context.safeSetAttributes({ minimized });
101
+ if (minimized) {
102
+ this.context.cleanFocus();
103
+ this.blurAllBox();
104
+ }
69
105
  });
70
106
  this.teleBoxManager.events.on("maximized", maximized => {
71
- this.manager.safeSetAttributes({ maximized });
107
+ this.context.safeSetAttributes({ maximized });
72
108
  });
73
109
  this.teleBoxManager.events.on("removed", boxes => {
74
110
  boxes.forEach(box => {
@@ -93,7 +129,7 @@ export class BoxManager {
93
129
  );
94
130
  this.teleBoxManager.events.on("focused", box => {
95
131
  if (box) {
96
- if (this.manager.canOperate) {
132
+ if (this.canOperate) {
97
133
  emitter.emit("focus", { appId: box.id });
98
134
  } else {
99
135
  this.teleBoxManager.blurBox(box.id);
@@ -107,10 +143,19 @@ export class BoxManager {
107
143
  callbacks.emit("prefersColorSchemeChange", colorScheme);
108
144
  });
109
145
  this.teleBoxManager.events.on("z_index", box => {
110
- this.manager.store.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
146
+ console.log("on z_index", box.id, box.zIndex);
147
+ this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
111
148
  });
112
149
  }
113
150
 
151
+ private get mainView() {
152
+ return this.context.getMainView();
153
+ }
154
+
155
+ private get canOperate() {
156
+ return this.context.canOperate();
157
+ }
158
+
114
159
  public get boxState() {
115
160
  return this.teleBoxManager.state;
116
161
  }
@@ -131,6 +176,10 @@ export class BoxManager {
131
176
  return this.teleBoxManager.prefersColorScheme;
132
177
  }
133
178
 
179
+ public get boxSize() {
180
+ return this.teleBoxManager.boxes.length;
181
+ }
182
+
134
183
  public createBox(params: CreateBoxParams): void {
135
184
  if (!this.teleBoxManager) return;
136
185
  let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT } = params.app.config ?? {};
@@ -155,14 +204,14 @@ export class BoxManager {
155
204
  id: params.appId,
156
205
  };
157
206
  this.teleBoxManager.create(createBoxConfig, params.smartPosition);
158
- emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
207
+ this.context.emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
159
208
  }
160
209
 
161
210
  public setBoxInitState(appId: string): void {
162
211
  const box = this.teleBoxManager.queryOne({ id: appId });
163
212
  if (box) {
164
213
  if (box.state === TELE_BOX_STATE.Maximized) {
165
- emitter.emit("resize", {
214
+ this.context.emitter.emit("resize", {
166
215
  appId: appId,
167
216
  x: box.x,
168
217
  y: box.y,
@@ -189,24 +238,30 @@ export class BoxManager {
189
238
  fence: false,
190
239
  prefersColorScheme: createTeleBoxManagerConfig?.prefersColorScheme,
191
240
  };
192
- const container = createTeleBoxManagerConfig?.collectorContainer || WindowManager.wrapper;
193
- const styles = {
194
- ...DEFAULT_COLLECTOR_STYLE,
195
- ...createTeleBoxManagerConfig?.collectorStyles,
196
- };
197
- const teleBoxCollector = new TeleBoxCollector({
198
- styles: styles,
199
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
200
- }).mount(container!);
201
- initManagerState.collector = teleBoxCollector;
241
+
202
242
  const manager = new TeleBoxManager(initManagerState);
203
243
  if (this.teleBoxManager) {
204
244
  this.teleBoxManager.destroy();
205
245
  }
206
246
  this.teleBoxManager = manager;
247
+ const container = createTeleBoxManagerConfig?.collectorContainer || WindowManager.wrapper;
248
+ if (container) {
249
+ this.setCollectorContainer(container);
250
+ }
207
251
  return manager;
208
252
  }
209
253
 
254
+ public setCollectorContainer(container: HTMLElement) {
255
+ const styles = {
256
+ ...DEFAULT_COLLECTOR_STYLE,
257
+ ...this.createTeleBoxManagerConfig?.collectorStyles,
258
+ };
259
+ const collector = new TeleBoxCollector({
260
+ styles
261
+ }).mount(container);
262
+ this.teleBoxManager.setCollector(collector);
263
+ }
264
+
210
265
  public getBox(appId: string): ReadonlyTeleBox | undefined {
211
266
  return this.teleBoxManager.queryOne({ id: appId });
212
267
  }
@@ -245,16 +300,18 @@ export class BoxManager {
245
300
  },
246
301
  true
247
302
  );
248
- if (state.maximized != null) {
249
- this.teleBoxManager.setMaximized(Boolean(state.maximized), true);
250
- this.teleBoxManager.setMinimized(Boolean(state.minimized), true);
251
- }
252
303
  setTimeout(() => {
253
304
  if (state.focus) {
254
- this.teleBoxManager.focusBox(box.id, true)
305
+ this.teleBoxManager.focusBox(box.id, true);
306
+ }
307
+ if (state.maximized != null) {
308
+ this.teleBoxManager.setMaximized(Boolean(state.maximized), true);
309
+ }
310
+ if (state.minimized != null) {
311
+ this.teleBoxManager.setMinimized(Boolean(state.minimized), true);
255
312
  }
256
313
  }, 50);
257
- callbacks.emit("boxStateChange", this.teleBoxManager.state);
314
+ this.context.callbacks.emit("boxStateChange", this.teleBoxManager.state);
258
315
  }
259
316
  }
260
317
 
@@ -263,7 +320,7 @@ export class BoxManager {
263
320
  if (rect && rect.width > 0 && rect.height > 0) {
264
321
  const containerRect = { x: 0, y: 0, width: rect.width, height: rect.height };
265
322
  this.teleBoxManager.setContainerRect(containerRect);
266
- this.manager.notifyContainerRectUpdate(this.teleBoxManager.containerRect);
323
+ this.context.notifyContainerRectUpdate(this.teleBoxManager.containerRect);
267
324
  }
268
325
  }
269
326
 
@@ -303,7 +360,9 @@ export class BoxManager {
303
360
  }
304
361
 
305
362
  public setMaximized(maximized: boolean) {
306
- this.teleBoxManager.setMaximized(maximized, true);
363
+ if (maximized !== this.maximized) {
364
+ this.teleBoxManager.setMaximized(maximized, true);
365
+ }
307
366
  }
308
367
 
309
368
  public setMinimized(minimized: boolean, skipUpdate = true) {
@@ -328,6 +387,10 @@ export class BoxManager {
328
387
  this.teleBoxManager.setPrefersColorScheme(colorScheme);
329
388
  }
330
389
 
390
+ public setZIndex(id: string, zIndex: number, skipUpdate = true) {
391
+ this.teleBoxManager.update(id, { zIndex }, skipUpdate);
392
+ }
393
+
331
394
  public destroy() {
332
395
  this.teleBoxManager.destroy();
333
396
  }
@@ -70,13 +70,20 @@ export class Cursor extends Base {
70
70
  }
71
71
 
72
72
  private moveCursor(cursor: Position, rect: DOMRect, view: any) {
73
- const { x, y } = cursor;
73
+ const { x, y, type } = cursor;
74
74
  const point = view?.screen.convertPointToScreen(x, y);
75
75
  if (point) {
76
- const translateX = point.x + rect.x - 2;
77
- const translateY = point.y + rect.y - 18;
76
+ let translateX = point.x - 2;
77
+ let translateY = point.y - 18;
78
+ if (type === "app") {
79
+ const wrapperRect = this.cursorManager.wrapperRect;
80
+ if (wrapperRect) {
81
+ translateX = translateX + rect.x - wrapperRect.x;
82
+ translateY = translateY + rect.y - wrapperRect.y;
83
+ }
84
+ }
78
85
  if (point.x < 0 || point.x > rect.width || point.y < 0 || point.y > rect.height) {
79
- this.component?.$set({ visible: false });
86
+ this.component?.$set({ visible: false, x: translateX, y: translateY });
80
87
  } else {
81
88
  this.component?.$set({ visible: true, x: translateX, y: translateY });
82
89
  }
@@ -149,7 +156,7 @@ export class Cursor extends Base {
149
156
  private async createCursor() {
150
157
  if (this.member && this.wrapper) {
151
158
  this.component = new App({
152
- target: document.documentElement,
159
+ target: this.wrapper,
153
160
  props: this.initProps(),
154
161
  });
155
162
  }
@@ -31,17 +31,24 @@ export class CursorManager extends Base {
31
31
  this.roomMembers = this.appManager.room?.state.roomMembers;
32
32
  const wrapper = WindowManager.wrapper;
33
33
  if (wrapper) {
34
- wrapper.addEventListener("mousemove", this.mouseMoveListener);
35
- wrapper.addEventListener("touchstart", this.touchMoveListener);
36
- wrapper.addEventListener("touchmove", this.touchMoveListener);
37
- wrapper.addEventListener("mouseleave", this.mouseLeaveListener);
38
- wrapper.addEventListener("touchend", this.mouseLeaveListener);
39
- this.initCursorAttributes();
40
- this.wrapperRect = wrapper.getBoundingClientRect();
41
- this.startReaction(wrapper);
34
+ this.setupWrapper(wrapper);
42
35
  }
43
36
  }
44
37
 
38
+ public setupWrapper(wrapper: HTMLElement) {
39
+ if (this.manager.refresher?.hasReactor("cursors")) {
40
+ this.destroy();
41
+ }
42
+ wrapper.addEventListener("mousemove", this.mouseMoveListener);
43
+ wrapper.addEventListener("touchstart", this.touchMoveListener);
44
+ wrapper.addEventListener("touchmove", this.touchMoveListener);
45
+ wrapper.addEventListener("mouseleave", this.mouseLeaveListener);
46
+ wrapper.addEventListener("touchend", this.mouseLeaveListener);
47
+ this.initCursorAttributes();
48
+ this.wrapperRect = wrapper.getBoundingClientRect();
49
+ this.startReaction(wrapper);
50
+ }
51
+
45
52
  public setMainViewDivElement(div: HTMLDivElement) {
46
53
  this.mainViewElement = div;
47
54
  }
@@ -1,8 +1,8 @@
1
- import { isFunction } from 'lodash';
2
- import { RoomPhase } from 'white-web-sdk';
1
+ import { isFunction, debounce } from "lodash";
2
+ import { log } from "./Utils/log";
3
+ import { RoomPhase } from "white-web-sdk";
3
4
  import type { Room } from "white-web-sdk";
4
- import type { AppManager } from './AppManager';
5
- import { log } from './Utils/log';
5
+ import type { AppManager } from "./AppManager";
6
6
 
7
7
  // 白板重连之后会刷新所有的对象,导致 listener 失效, 所以这里在重连之后重新对所有对象进行监听
8
8
  export class ReconnectRefresher {
@@ -22,9 +22,9 @@ export class ReconnectRefresher {
22
22
  this.onReconnected();
23
23
  }
24
24
  this.phase = phase;
25
- }
25
+ };
26
26
 
27
- private onReconnected = () => {
27
+ private onReconnected = debounce(() => {
28
28
  log("onReconnected refresh reactors");
29
29
  this.releaseDisposers();
30
30
  this.reactors.forEach((func, id) => {
@@ -33,14 +33,14 @@ export class ReconnectRefresher {
33
33
  }
34
34
  });
35
35
  this.manager.notifyReconnected();
36
- }
36
+ }, 3000);
37
37
 
38
38
  private releaseDisposers() {
39
39
  this.disposers.forEach(disposer => {
40
40
  if (isFunction(disposer)) {
41
41
  disposer();
42
42
  }
43
- })
43
+ });
44
44
  this.disposers.clear();
45
45
  }
46
46
 
@@ -64,6 +64,10 @@ export class ReconnectRefresher {
64
64
  }
65
65
  }
66
66
 
67
+ public hasReactor(id: string) {
68
+ return this.reactors.has(id);
69
+ }
70
+
67
71
  public destroy() {
68
72
  this.room?.callbacks.off("onPhaseChanged", this.onPhaseChanged);
69
73
  this.releaseDisposers();
@@ -1,10 +1,10 @@
1
- import { emitter } from '../index';
2
- import { isPlayer } from 'white-web-sdk';
1
+ import { emitter } from "../index";
2
+ import { isPlayer } from "white-web-sdk";
3
+ import type { WindowManager } from '../index';
3
4
  import type { Camera, Room , Player , PlayerSeekingResult } from "white-web-sdk";
4
- import type { AppManager } from "../AppManager";
5
5
 
6
6
  // 修改多窗口状态下一些失效的方法实现到 manager 的 mainview 上, 降低迁移成本
7
- export const replaceRoomFunction = (room: Room, manager: AppManager) => {
7
+ export const replaceRoomFunction = (room: Room, manager: WindowManager) => {
8
8
  if (isPlayer(room)) {
9
9
  const player = room as unknown as Player;
10
10
  const originSeek = player.seekToProgressTime;
@@ -30,7 +30,7 @@ export const replaceRoomFunction = (room: Room, manager: AppManager) => {
30
30
  });
31
31
 
32
32
  room.moveCamera = (camera: Camera) => manager.mainView.moveCamera(camera);
33
- room.moveCameraToContain = (...args) => manager.mainView.moveCameraToContain(...args);
33
+ room.moveCameraToContain = (...args) => manager.moveCameraToContain(...args);
34
34
  room.convertToPointInWorld = (...args) => manager.mainView.convertToPointInWorld(...args);
35
35
  room.setCameraBound = (...args) => manager.mainView.setCameraBound(...args);
36
36
  room.scenePreview = (...args) => manager.mainView.scenePreview(...args);
@@ -1,3 +1,4 @@
1
+
1
2
  export class AppCreateError extends Error {
2
3
  override message = "[WindowManager]: app duplicate exists and cannot be created again";
3
4
  }
@@ -28,4 +29,8 @@ export class BoxNotCreatedError extends Error {
28
29
 
29
30
  export class InvalidScenePath extends Error {
30
31
  override message = `[WindowManager]: ScenePath should start with "/"`;
31
- }
32
+ }
33
+
34
+ export class BoxManagerNotFoundError extends Error {
35
+ override message = "[WindowManager]: boxManager not found";
36
+ }