@netless/window-manager 0.4.32 → 1.0.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/dist/App/AppProxy.d.ts +0 -1
- package/dist/BoxManager.d.ts +5 -5
- package/dist/Helper.d.ts +0 -2
- package/dist/InternalEmitter.d.ts +2 -1
- package/dist/View/CameraSynchronizer.d.ts +17 -0
- package/dist/View/MainView.d.ts +4 -5
- package/dist/index.cjs.js +21 -22
- package/dist/index.d.ts +0 -2
- package/dist/index.es.js +2226 -1843
- package/dist/index.umd.js +21 -22
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/pnpm-lock.yaml +84 -97
- package/src/App/AppContext.ts +1 -1
- package/src/App/AppProxy.ts +0 -9
- package/src/BoxManager.ts +94 -107
- package/src/Cursor/index.ts +5 -5
- package/src/Helper.ts +2 -15
- package/src/InternalEmitter.ts +6 -4
- package/src/View/CameraSynchronizer.ts +67 -0
- package/src/View/MainView.ts +45 -53
- package/src/index.ts +13 -33
- package/vite.config.js +0 -1
- package/dist/ContainerResizeObserver.d.ts +0 -11
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.es.js.map +0 -1
- package/dist/index.umd.js.map +0 -1
- package/src/ContainerResizeObserver.ts +0 -73
package/src/App/AppProxy.ts
CHANGED
@@ -191,7 +191,6 @@ export class AppProxy implements PageRemoveService {
|
|
191
191
|
const result = await app.setup(context);
|
192
192
|
this.appResult = result;
|
193
193
|
appRegister.notifyApp(this.kind, "created", { appId, result });
|
194
|
-
this.afterSetupApp(boxInitState);
|
195
194
|
this.fixMobileSize();
|
196
195
|
}, SETUP_APP_DELAY);
|
197
196
|
});
|
@@ -225,14 +224,6 @@ export class AppProxy implements PageRemoveService {
|
|
225
224
|
}
|
226
225
|
}
|
227
226
|
|
228
|
-
private afterSetupApp(boxInitState: AppInitState | undefined): void {
|
229
|
-
if (boxInitState) {
|
230
|
-
if (!boxInitState?.x || !boxInitState.y) {
|
231
|
-
this.boxManager?.setBoxInitState(this.id);
|
232
|
-
}
|
233
|
-
}
|
234
|
-
}
|
235
|
-
|
236
227
|
public async onSeek(time: number) {
|
237
228
|
this.appEmitter.emit("seek", time).catch(err => {
|
238
229
|
console.log(`[WindowManager]: emit seek error: ${err.message}`);
|
package/src/BoxManager.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { AppAttributes, Events, MIN_HEIGHT, MIN_WIDTH } from "./constants";
|
2
2
|
import { debounce } from "lodash";
|
3
|
-
import { TELE_BOX_STATE,
|
3
|
+
import { TELE_BOX_STATE, TeleBoxManager } from "@netless/telebox-insider";
|
4
4
|
import { WindowManager } from "./index";
|
5
5
|
import type { BoxEmitterType } from "./BoxEmitter";
|
6
6
|
import type { AddAppOptions, AppInitState } from "./index";
|
@@ -18,6 +18,7 @@ import type { NetlessApp } from "./typings";
|
|
18
18
|
import type { View } from "white-web-sdk";
|
19
19
|
import type { CallbacksType } from "./callback";
|
20
20
|
import type { EmitterType } from "./InternalEmitter";
|
21
|
+
import { SideEffectManager } from "side-effect-manager";
|
21
22
|
|
22
23
|
export { TELE_BOX_STATE };
|
23
24
|
|
@@ -45,6 +46,7 @@ export type CreateTeleBoxManagerConfig = {
|
|
45
46
|
collectorContainer?: HTMLElement;
|
46
47
|
collectorStyles?: Partial<CSSStyleDeclaration>;
|
47
48
|
prefersColorScheme?: TeleBoxColorScheme;
|
49
|
+
stageRatio?: number;
|
48
50
|
};
|
49
51
|
|
50
52
|
export type BoxManagerContext = {
|
@@ -87,79 +89,93 @@ export const createBoxManager = (
|
|
87
89
|
|
88
90
|
export class BoxManager {
|
89
91
|
public teleBoxManager: TeleBoxManager;
|
92
|
+
protected sideEffectManager: SideEffectManager;
|
90
93
|
|
91
94
|
constructor(
|
92
95
|
private context: BoxManagerContext,
|
93
|
-
|
96
|
+
createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
|
94
97
|
) {
|
98
|
+
this.sideEffectManager = new SideEffectManager();
|
95
99
|
const { emitter, callbacks, boxEmitter } = context;
|
96
100
|
this.teleBoxManager = this.setupBoxManager(createTeleBoxManagerConfig);
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
this.teleBoxManager.events.on("minimized", minimized => {
|
113
|
-
this.context.safeSetAttributes({ minimized });
|
114
|
-
if (minimized) {
|
115
|
-
this.context.cleanFocus();
|
116
|
-
this.blurAllBox();
|
117
|
-
} else {
|
118
|
-
const topBox = this.getTopBox();
|
119
|
-
if (topBox) {
|
120
|
-
this.context.setAppFocus(topBox.id);
|
121
|
-
this.focusBox({ appId: topBox.id }, false);
|
101
|
+
this.sideEffectManager.add(() => [
|
102
|
+
// 使用 _xxx$.reaction 订阅修改的值, 不管有没有 skipUpdate, 修改值都会触发回调
|
103
|
+
this.teleBoxManager._state$.reaction(state => {
|
104
|
+
callbacks.emit("boxStateChange", state);
|
105
|
+
emitter.emit("boxStateChange", state);
|
106
|
+
}),
|
107
|
+
this.teleBoxManager._darkMode$.reaction(darkMode => {
|
108
|
+
callbacks.emit("darkModeChange", darkMode);
|
109
|
+
}),
|
110
|
+
this.teleBoxManager._prefersColorScheme$.reaction(colorScheme => {
|
111
|
+
callbacks.emit("prefersColorSchemeChange", colorScheme);
|
112
|
+
}),
|
113
|
+
this.teleBoxManager._minimized$.reaction((minimized, skipUpdate) => {
|
114
|
+
if (skipUpdate) {
|
115
|
+
return;
|
122
116
|
}
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
});
|
128
|
-
this.teleBoxManager.events.on("removed", boxes => {
|
129
|
-
boxes.forEach(box => {
|
130
|
-
boxEmitter.emit("close", { appId: box.id });
|
131
|
-
});
|
132
|
-
});
|
133
|
-
this.teleBoxManager.events.on(
|
134
|
-
"intrinsic_move",
|
135
|
-
debounce((box: ReadonlyTeleBox): void => {
|
136
|
-
boxEmitter.emit("move", { appId: box.id, x: box.intrinsicX, y: box.intrinsicY });
|
137
|
-
}, 50)
|
138
|
-
);
|
139
|
-
this.teleBoxManager.events.on(
|
140
|
-
"intrinsic_resize",
|
141
|
-
debounce((box: ReadonlyTeleBox): void => {
|
142
|
-
boxEmitter.emit("resize", {
|
143
|
-
appId: box.id,
|
144
|
-
width: box.intrinsicWidth,
|
145
|
-
height: box.intrinsicHeight,
|
146
|
-
});
|
147
|
-
}, 200)
|
148
|
-
);
|
149
|
-
this.teleBoxManager.events.on("focused", box => {
|
150
|
-
if (box) {
|
151
|
-
if (this.canOperate) {
|
152
|
-
boxEmitter.emit("focus", { appId: box.id });
|
117
|
+
this.context.safeSetAttributes({ minimized });
|
118
|
+
if (minimized) {
|
119
|
+
this.context.cleanFocus();
|
120
|
+
this.blurAllBox();
|
153
121
|
} else {
|
154
|
-
this.
|
122
|
+
const topBox = this.getTopBox();
|
123
|
+
if (topBox) {
|
124
|
+
this.context.setAppFocus(topBox.id);
|
125
|
+
this.focusBox({ appId: topBox.id }, false);
|
126
|
+
}
|
155
127
|
}
|
156
|
-
}
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
128
|
+
}),
|
129
|
+
this.teleBoxManager._maximized$.reaction((maximized, skipUpdate) => {
|
130
|
+
if (skipUpdate) {
|
131
|
+
return;
|
132
|
+
}
|
133
|
+
this.context.safeSetAttributes({ maximized });
|
134
|
+
}),
|
135
|
+
this.teleBoxManager.events.on("removed", boxes => {
|
136
|
+
boxes.forEach(box => {
|
137
|
+
boxEmitter.emit("close", { appId: box.id });
|
138
|
+
});
|
139
|
+
}),
|
140
|
+
this.teleBoxManager.events.on(
|
141
|
+
"intrinsic_move",
|
142
|
+
debounce((box: ReadonlyTeleBox): void => {
|
143
|
+
boxEmitter.emit("move", { appId: box.id, x: box.intrinsicX, y: box.intrinsicY });
|
144
|
+
}, 50)
|
145
|
+
),
|
146
|
+
this.teleBoxManager.events.on(
|
147
|
+
"intrinsic_resize",
|
148
|
+
debounce((box: ReadonlyTeleBox): void => {
|
149
|
+
boxEmitter.emit("resize", {
|
150
|
+
appId: box.id,
|
151
|
+
width: box.intrinsicWidth,
|
152
|
+
height: box.intrinsicHeight,
|
153
|
+
});
|
154
|
+
}, 200)
|
155
|
+
),
|
156
|
+
this.teleBoxManager.events.on("focused", box => {
|
157
|
+
if (box) {
|
158
|
+
if (this.canOperate) {
|
159
|
+
boxEmitter.emit("focus", { appId: box.id });
|
160
|
+
} else {
|
161
|
+
this.teleBoxManager.blurBox(box.id);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
}),
|
165
|
+
this.teleBoxManager.events.on("z_index", box => {
|
166
|
+
this.context.updateAppState(box.id, AppAttributes.ZIndex, box.zIndex);
|
167
|
+
}),
|
168
|
+
this.teleBoxManager._stageRect$.subscribe(stage => {
|
169
|
+
emitter.emit("playgroundSizeChange", stage);
|
170
|
+
this.context.notifyContainerRectUpdate(stage);
|
171
|
+
}),
|
172
|
+
emitter.on("writableChange", isWritable => {
|
173
|
+
this.teleBoxManager.setHighlightStage(isWritable);
|
174
|
+
}),
|
175
|
+
emitter.on("containerSizeRatioUpdate", ratio => {
|
176
|
+
this.teleBoxManager._stageRatio$.setValue(ratio);
|
177
|
+
}),
|
178
|
+
]);
|
163
179
|
}
|
164
180
|
|
165
181
|
private get mainView() {
|
@@ -199,7 +215,7 @@ export class BoxManager {
|
|
199
215
|
let { minwidth = MIN_WIDTH, minheight = MIN_HEIGHT } = params.app.config ?? {};
|
200
216
|
const { width, height } = params.app.config ?? {};
|
201
217
|
const title = params.options?.title || params.appId;
|
202
|
-
const rect = this.teleBoxManager.
|
218
|
+
const rect = this.teleBoxManager.rootRect;
|
203
219
|
|
204
220
|
if (minwidth > 1) {
|
205
221
|
minwidth = minwidth / rect.width;
|
@@ -221,34 +237,13 @@ export class BoxManager {
|
|
221
237
|
this.context.emitter.emit(`${params.appId}${Events.WindowCreated}` as any);
|
222
238
|
}
|
223
239
|
|
224
|
-
public setBoxInitState(appId: string): void {
|
225
|
-
const box = this.teleBoxManager.queryOne({ id: appId });
|
226
|
-
if (box) {
|
227
|
-
if (box.state === TELE_BOX_STATE.Maximized) {
|
228
|
-
this.context.boxEmitter.emit("resize", {
|
229
|
-
appId: appId,
|
230
|
-
x: box.x,
|
231
|
-
y: box.y,
|
232
|
-
width: box.intrinsicWidth,
|
233
|
-
height: box.intrinsicHeight,
|
234
|
-
});
|
235
|
-
}
|
236
|
-
}
|
237
|
-
}
|
238
|
-
|
239
240
|
public setupBoxManager(
|
240
241
|
createTeleBoxManagerConfig?: CreateTeleBoxManagerConfig
|
241
242
|
): TeleBoxManager {
|
242
|
-
const root = WindowManager.
|
243
|
-
const rect = root.getBoundingClientRect();
|
243
|
+
const root = WindowManager.playground;
|
244
244
|
const initManagerState: TeleBoxManagerConfig = {
|
245
|
+
stageRatio: 3 / 4,
|
245
246
|
root: root,
|
246
|
-
containerRect: {
|
247
|
-
x: 0,
|
248
|
-
y: 0,
|
249
|
-
width: rect.width,
|
250
|
-
height: rect.height,
|
251
|
-
},
|
252
247
|
fence: false,
|
253
248
|
prefersColorScheme: createTeleBoxManagerConfig?.prefersColorScheme,
|
254
249
|
};
|
@@ -258,20 +253,16 @@ export class BoxManager {
|
|
258
253
|
this.teleBoxManager.destroy();
|
259
254
|
}
|
260
255
|
this.teleBoxManager = manager;
|
261
|
-
const container = createTeleBoxManagerConfig?.collectorContainer
|
256
|
+
const container = createTeleBoxManagerConfig?.collectorContainer;
|
262
257
|
if (container) {
|
263
|
-
this.
|
258
|
+
this.teleBoxManager.collector.set$collector(container);
|
259
|
+
}
|
260
|
+
if (createTeleBoxManagerConfig?.collectorStyles) {
|
261
|
+
this.teleBoxManager.collector.setStyles(createTeleBoxManagerConfig.collectorStyles);
|
264
262
|
}
|
265
263
|
return manager;
|
266
264
|
}
|
267
265
|
|
268
|
-
public setCollectorContainer(container: HTMLElement) {
|
269
|
-
const collector = new TeleBoxCollector({
|
270
|
-
styles: this.createTeleBoxManagerConfig?.collectorStyles,
|
271
|
-
}).mount(container);
|
272
|
-
this.teleBoxManager.setCollector(collector);
|
273
|
-
}
|
274
|
-
|
275
266
|
public getBox(appId: string): ReadonlyTeleBox | undefined {
|
276
267
|
return this.teleBoxManager.queryOne({ id: appId });
|
277
268
|
}
|
@@ -324,15 +315,6 @@ export class BoxManager {
|
|
324
315
|
}
|
325
316
|
}
|
326
317
|
|
327
|
-
public updateManagerRect(): void {
|
328
|
-
const rect = this.mainView.divElement?.getBoundingClientRect();
|
329
|
-
if (rect && rect.width > 0 && rect.height > 0) {
|
330
|
-
const containerRect = { x: 0, y: 0, width: rect.width, height: rect.height };
|
331
|
-
this.teleBoxManager.setContainerRect(containerRect);
|
332
|
-
this.context.notifyContainerRectUpdate(this.teleBoxManager.containerRect);
|
333
|
-
}
|
334
|
-
}
|
335
|
-
|
336
318
|
public moveBox({ appId, x, y }: MoveBoxParams): void {
|
337
319
|
this.teleBoxManager.update(appId, { x, y }, true);
|
338
320
|
}
|
@@ -404,7 +386,12 @@ export class BoxManager {
|
|
404
386
|
this.teleBoxManager.update(id, { zIndex }, skipUpdate);
|
405
387
|
}
|
406
388
|
|
389
|
+
public setRoot(root: HTMLElement) {
|
390
|
+
this.teleBoxManager._root$.setValue(root);
|
391
|
+
}
|
392
|
+
|
407
393
|
public destroy() {
|
394
|
+
this.sideEffectManager.flushAll();
|
408
395
|
this.teleBoxManager.destroy();
|
409
396
|
}
|
410
397
|
}
|
package/src/Cursor/index.ts
CHANGED
@@ -34,9 +34,9 @@ export class CursorManager {
|
|
34
34
|
|
35
35
|
constructor(private manager: AppManager, private enableCursor: boolean, applianceIcons?: ApplianceIcons) {
|
36
36
|
this.roomMembers = this.manager.room?.state.roomMembers;
|
37
|
-
const
|
38
|
-
if (
|
39
|
-
this.setupWrapper(
|
37
|
+
const playground = WindowManager.playground;
|
38
|
+
if (playground) {
|
39
|
+
this.setupWrapper(playground);
|
40
40
|
}
|
41
41
|
this.sideEffectManager.add(() => {
|
42
42
|
return emitter.on("cursorMove", this.onCursorMove);
|
@@ -65,7 +65,7 @@ export class CursorManager {
|
|
65
65
|
private initCursorInstance = (uid: string) => {
|
66
66
|
let cursorInstance = this.cursorInstances.get(uid);
|
67
67
|
if (!cursorInstance) {
|
68
|
-
cursorInstance = new Cursor(this.manager, uid, this, WindowManager.
|
68
|
+
cursorInstance = new Cursor(this.manager, uid, this, WindowManager.playground);
|
69
69
|
this.cursorInstances.set(uid, cursorInstance);
|
70
70
|
}
|
71
71
|
return cursorInstance;
|
@@ -169,7 +169,7 @@ export class CursorManager {
|
|
169
169
|
|
170
170
|
public updateContainerRect() {
|
171
171
|
this.containerRect = WindowManager.container?.getBoundingClientRect();
|
172
|
-
this.wrapperRect = WindowManager.
|
172
|
+
this.wrapperRect = WindowManager.playground?.getBoundingClientRect();
|
173
173
|
}
|
174
174
|
|
175
175
|
public deleteCursor(uid: string) {
|
package/src/Helper.ts
CHANGED
@@ -2,36 +2,23 @@ import { getVersionNumber } from "./Utils/Common";
|
|
2
2
|
import { REQUIRE_VERSION } from "./constants";
|
3
3
|
import { WhiteVersion } from "white-web-sdk";
|
4
4
|
import { WhiteWebSDKInvalidError } from "./Utils/error";
|
5
|
-
import { WindowManager } from "./index";
|
6
5
|
import type { Room } from "white-web-sdk";
|
7
6
|
|
8
7
|
export const setupWrapper = (
|
9
8
|
root: HTMLElement
|
10
9
|
): {
|
11
10
|
playground: HTMLDivElement;
|
12
|
-
wrapper: HTMLDivElement;
|
13
|
-
sizer: HTMLDivElement;
|
14
11
|
mainViewElement: HTMLDivElement;
|
15
12
|
} => {
|
16
13
|
const playground = document.createElement("div");
|
17
14
|
playground.className = "netless-window-manager-playground";
|
18
15
|
|
19
|
-
const sizer = document.createElement("div");
|
20
|
-
sizer.className = "netless-window-manager-sizer";
|
21
|
-
|
22
|
-
const wrapper = document.createElement("div");
|
23
|
-
wrapper.className = "netless-window-manager-wrapper";
|
24
|
-
|
25
16
|
const mainViewElement = document.createElement("div");
|
26
17
|
mainViewElement.className = "netless-window-manager-main-view";
|
27
|
-
|
28
|
-
playground.appendChild(sizer);
|
29
|
-
sizer.appendChild(wrapper);
|
30
|
-
wrapper.appendChild(mainViewElement);
|
18
|
+
playground.appendChild(mainViewElement);
|
31
19
|
root.appendChild(playground);
|
32
|
-
WindowManager.wrapper = wrapper;
|
33
20
|
|
34
|
-
return { playground,
|
21
|
+
return { playground, mainViewElement };
|
35
22
|
};
|
36
23
|
|
37
24
|
export const checkVersion = () => {
|
package/src/InternalEmitter.ts
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
import Emittery from "emittery";
|
2
|
+
import type { TeleBoxRect } from "@netless/telebox-insider";
|
2
3
|
import type { AppInitState, CursorMovePayload } from "./index";
|
3
4
|
|
4
5
|
export type RemoveSceneParams = {
|
5
|
-
scenePath: string
|
6
|
-
|
6
|
+
scenePath: string;
|
7
|
+
index?: number;
|
8
|
+
};
|
7
9
|
|
8
10
|
export type EmitterEvent = {
|
9
11
|
onCreated: undefined;
|
@@ -14,14 +16,14 @@ export type EmitterEvent = {
|
|
14
16
|
mainViewMounted: undefined;
|
15
17
|
observerIdChange: number;
|
16
18
|
boxStateChange: string;
|
17
|
-
playgroundSizeChange:
|
19
|
+
playgroundSizeChange: TeleBoxRect;
|
18
20
|
startReconnect: undefined;
|
19
21
|
onReconnected: undefined;
|
20
22
|
removeScenes: RemoveSceneParams;
|
21
23
|
cursorMove: CursorMovePayload;
|
22
24
|
updateManagerRect: undefined;
|
23
25
|
focusedChange: { focused: string | undefined; prev: string | undefined };
|
24
|
-
rootDirRemoved: undefined;
|
26
|
+
rootDirRemoved: undefined; // 根目录整个被删除
|
25
27
|
rootDirSceneRemoved: string; // 根目录下的场景被删除
|
26
28
|
setReadonly: boolean;
|
27
29
|
changePageState: undefined;
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import { AnimationMode } from "white-web-sdk";
|
2
|
+
import { delay, throttle } from "lodash";
|
3
|
+
import type { TeleBoxRect } from "@netless/telebox-insider";
|
4
|
+
import type { Camera, View, Size } from "white-web-sdk";
|
5
|
+
import type { MainViewSize } from "../AttributesDelegate";
|
6
|
+
|
7
|
+
export type SaveCamera = (camera: Camera) => void;
|
8
|
+
|
9
|
+
export class CameraSynchronizer {
|
10
|
+
protected remoteCamera?: Camera;
|
11
|
+
protected remoteSize?: MainViewSize;
|
12
|
+
protected rect?: TeleBoxRect;
|
13
|
+
protected view?: View;
|
14
|
+
|
15
|
+
constructor(protected saveCamera: SaveCamera) {}
|
16
|
+
|
17
|
+
public setRect(rect: TeleBoxRect) {
|
18
|
+
this.rect = rect;
|
19
|
+
if (this.remoteCamera && this.remoteSize) {
|
20
|
+
this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
public setView(view: View) {
|
25
|
+
this.view = view;
|
26
|
+
}
|
27
|
+
|
28
|
+
// 远端 Camera 或者 size 更新
|
29
|
+
public onRemoteUpdate = throttle((camera: Camera, size: MainViewSize) => {
|
30
|
+
this.remoteCamera = camera;
|
31
|
+
this.remoteSize = size;
|
32
|
+
if (this.remoteSize && this.rect) {
|
33
|
+
let scale: number;
|
34
|
+
if (size.width < size.height) {
|
35
|
+
scale = this.rect.width / size.width;
|
36
|
+
} else {
|
37
|
+
scale = this.rect.height / size.height;
|
38
|
+
}
|
39
|
+
const nextScale = camera.scale * scale;
|
40
|
+
const moveCamera = () => this.view?.moveCamera({
|
41
|
+
centerX: camera.centerX,
|
42
|
+
centerY: camera.centerY,
|
43
|
+
scale: nextScale,
|
44
|
+
animationMode: AnimationMode.Immediately,
|
45
|
+
});
|
46
|
+
// TODO 直接调用 moveCamera 依然会出现 camera 错误的情况,这里暂时加一个 delay 保证 camera 是对的, 后续需要 SDK 进行修改
|
47
|
+
delay(moveCamera, 10);
|
48
|
+
}
|
49
|
+
}, 50);
|
50
|
+
|
51
|
+
|
52
|
+
public onLocalCameraUpdate(camera: Camera) {
|
53
|
+
this.saveCamera(camera);
|
54
|
+
}
|
55
|
+
|
56
|
+
// 本地 Size 更新, 先匹配 camera 到新的 size 然后再发送 camera 数据到远端
|
57
|
+
public onLocalSizeUpdate(size: Size) {
|
58
|
+
if (this.rect && this.view) {
|
59
|
+
const scale = this.rect.width / size.width;
|
60
|
+
const nextScale = this.view.camera.scale * scale;
|
61
|
+
this.view.moveCamera({
|
62
|
+
scale: nextScale,
|
63
|
+
animationMode: AnimationMode.Immediately
|
64
|
+
});
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
package/src/View/MainView.ts
CHANGED
@@ -1,25 +1,29 @@
|
|
1
|
-
import {
|
1
|
+
import { reaction } from "white-web-sdk";
|
2
2
|
import { callbacks } from "../callback";
|
3
3
|
import { createView } from "./ViewManager";
|
4
|
-
import { debounce, get,
|
4
|
+
import { debounce, get, isEqual } from "lodash";
|
5
5
|
import { emitter } from "../InternalEmitter";
|
6
|
+
import { Events } from "../constants";
|
6
7
|
import { Fields } from "../AttributesDelegate";
|
7
8
|
import { setViewFocusScenePath } from "../Utils/Common";
|
8
9
|
import { SideEffectManager } from "side-effect-manager";
|
9
10
|
import type { Camera, Size, View } from "white-web-sdk";
|
10
11
|
import type { AppManager } from "../AppManager";
|
11
|
-
import {
|
12
|
+
import { CameraSynchronizer } from "./CameraSynchronizer";
|
12
13
|
|
13
14
|
export class MainViewProxy {
|
14
|
-
private scale?: number;
|
15
15
|
private started = false;
|
16
16
|
private mainViewIsAddListener = false;
|
17
17
|
private mainView: View;
|
18
18
|
private store = this.manager.store;
|
19
|
+
private synchronizer: CameraSynchronizer;
|
19
20
|
|
20
21
|
private sideEffectManager = new SideEffectManager();
|
21
22
|
|
22
23
|
constructor(private manager: AppManager) {
|
24
|
+
this.synchronizer = new CameraSynchronizer(
|
25
|
+
camera => this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
|
26
|
+
);
|
23
27
|
this.mainView = this.createMainView();
|
24
28
|
this.moveCameraSizeByAttributes();
|
25
29
|
emitter.once("mainViewMounted").then(() => {
|
@@ -28,18 +32,24 @@ export class MainViewProxy {
|
|
28
32
|
this.ensureCameraAndSize();
|
29
33
|
this.startListenWritableChange();
|
30
34
|
});
|
31
|
-
const playgroundSizeChangeListener = () => {
|
32
|
-
this.sizeChangeHandler(this.mainViewSize);
|
33
|
-
};
|
34
|
-
this.sideEffectManager.add(() => {
|
35
|
-
return emitter.on("playgroundSizeChange", playgroundSizeChangeListener);
|
36
|
-
});
|
37
35
|
this.sideEffectManager.add(() => {
|
38
36
|
return emitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio);
|
39
37
|
});
|
40
38
|
this.sideEffectManager.add(() => {
|
41
39
|
return emitter.on("startReconnect", () => {
|
42
|
-
this.mainView.
|
40
|
+
if (!(this.mainView as any).didRelease) {
|
41
|
+
this.mainView.release();
|
42
|
+
}
|
43
|
+
});
|
44
|
+
});
|
45
|
+
const rect = this.manager.boxManager?.teleBoxManager.stageRect;
|
46
|
+
if (rect) {
|
47
|
+
this.synchronizer.setRect(rect);
|
48
|
+
}
|
49
|
+
this.sideEffectManager.add(() => {
|
50
|
+
return emitter.on("playgroundSizeChange", rect => {
|
51
|
+
this.synchronizer.setRect(rect);
|
52
|
+
this.synchronizer.onLocalSizeUpdate(rect);
|
43
53
|
});
|
44
54
|
});
|
45
55
|
}
|
@@ -52,7 +62,7 @@ export class MainViewProxy {
|
|
52
62
|
}
|
53
63
|
});
|
54
64
|
});
|
55
|
-
}
|
65
|
+
};
|
56
66
|
|
57
67
|
public ensureCameraAndSize() {
|
58
68
|
if (!this.mainViewCamera || !this.mainViewSize) {
|
@@ -74,8 +84,7 @@ export class MainViewProxy {
|
|
74
84
|
}
|
75
85
|
|
76
86
|
private moveCameraSizeByAttributes() {
|
77
|
-
this.
|
78
|
-
this.moveCamera(this.mainViewCamera);
|
87
|
+
this.synchronizer.onRemoteUpdate(this.mainViewCamera, this.mainViewSize);
|
79
88
|
}
|
80
89
|
|
81
90
|
public start() {
|
@@ -91,9 +100,12 @@ export class MainViewProxy {
|
|
91
100
|
};
|
92
101
|
|
93
102
|
public setCameraAndSize(): void {
|
94
|
-
const
|
95
|
-
|
96
|
-
|
103
|
+
const stageSize = this.getStageSize();
|
104
|
+
if (stageSize) {
|
105
|
+
const camera = { ...this.mainView.camera, id: this.manager.uid };
|
106
|
+
const size = { ...stageSize, id: this.manager.uid };
|
107
|
+
this.store.setMainViewCameraAndSize(camera, size);
|
108
|
+
}
|
97
109
|
}
|
98
110
|
|
99
111
|
private cameraReaction = () => {
|
@@ -101,8 +113,7 @@ export class MainViewProxy {
|
|
101
113
|
() => this.mainViewCamera,
|
102
114
|
camera => {
|
103
115
|
if (camera && camera.id !== this.manager.uid) {
|
104
|
-
this.
|
105
|
-
this.moveCamera(camera);
|
116
|
+
this.synchronizer.onRemoteUpdate(camera, this.mainViewSize);
|
106
117
|
}
|
107
118
|
},
|
108
119
|
{ fireImmediately: true }
|
@@ -111,8 +122,7 @@ export class MainViewProxy {
|
|
111
122
|
|
112
123
|
public sizeChangeHandler = debounce((size: Size) => {
|
113
124
|
if (size) {
|
114
|
-
this.
|
115
|
-
this.moveCamera(this.mainViewCamera);
|
125
|
+
this.synchronizer.onLocalSizeUpdate(size);
|
116
126
|
}
|
117
127
|
}, 30);
|
118
128
|
|
@@ -122,7 +132,7 @@ export class MainViewProxy {
|
|
122
132
|
if (size.id === this.manager.uid) {
|
123
133
|
this.setCameraAndSize();
|
124
134
|
}
|
125
|
-
}
|
135
|
+
};
|
126
136
|
|
127
137
|
public get view(): View {
|
128
138
|
return this.mainView;
|
@@ -138,6 +148,7 @@ export class MainViewProxy {
|
|
138
148
|
if (mainViewScenePath) {
|
139
149
|
setViewFocusScenePath(mainView, mainViewScenePath);
|
140
150
|
}
|
151
|
+
this.synchronizer.setView(mainView);
|
141
152
|
return mainView;
|
142
153
|
}
|
143
154
|
|
@@ -172,12 +183,20 @@ export class MainViewProxy {
|
|
172
183
|
}
|
173
184
|
|
174
185
|
private onCameraUpdatedByDevice = (camera: Camera) => {
|
175
|
-
this.
|
176
|
-
|
177
|
-
|
186
|
+
this.synchronizer.onLocalCameraUpdate(camera);
|
187
|
+
const size = this.getStageSize();
|
188
|
+
if (size && !isEqual(size, this.mainViewSize)) {
|
189
|
+
this.setMainViewSize(size);
|
178
190
|
}
|
179
191
|
};
|
180
192
|
|
193
|
+
private getStageSize(): Size | undefined {
|
194
|
+
const stage = this.manager.boxManager?.teleBoxManager.stageRect;
|
195
|
+
if (stage) {
|
196
|
+
return { width: stage.width, height: stage.height };
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
181
200
|
public addMainViewListener(): void {
|
182
201
|
if (this.mainViewIsAddListener) return;
|
183
202
|
if (this.view.divElement) {
|
@@ -205,7 +224,7 @@ export class MainViewProxy {
|
|
205
224
|
this.manager.boxManager?.blurAllBox();
|
206
225
|
}
|
207
226
|
|
208
|
-
public setMainViewSize = debounce(size => {
|
227
|
+
public setMainViewSize = debounce((size: Size) => {
|
209
228
|
this.store.setMainViewSize({ ...size, id: this.manager.uid });
|
210
229
|
}, 50);
|
211
230
|
|
@@ -225,33 +244,6 @@ export class MainViewProxy {
|
|
225
244
|
callbacks.emit("cameraStateChange", this.cameraState);
|
226
245
|
};
|
227
246
|
|
228
|
-
public moveCameraToContian(size: Size): void {
|
229
|
-
if (!isEmpty(size)) {
|
230
|
-
this.view.moveCameraToContain({
|
231
|
-
width: size.width,
|
232
|
-
height: size.height,
|
233
|
-
originX: -size.width / 2,
|
234
|
-
originY: -size.height / 2,
|
235
|
-
animationMode: AnimationMode.Immediately,
|
236
|
-
});
|
237
|
-
this.scale = this.view.camera.scale;
|
238
|
-
}
|
239
|
-
}
|
240
|
-
|
241
|
-
public moveCamera(camera: Camera): void {
|
242
|
-
if (!isEmpty(camera)) {
|
243
|
-
if (isEqual(camera, this.view.camera)) return;
|
244
|
-
const { centerX, centerY, scale } = camera;
|
245
|
-
const needScale = scale * (this.scale || 1);
|
246
|
-
this.view.moveCamera({
|
247
|
-
centerX: centerX,
|
248
|
-
centerY: centerY,
|
249
|
-
scale: needScale,
|
250
|
-
animationMode: AnimationMode.Immediately,
|
251
|
-
});
|
252
|
-
}
|
253
|
-
}
|
254
|
-
|
255
247
|
public stop() {
|
256
248
|
this.removeCameraListener();
|
257
249
|
this.manager.refresher?.remove(Fields.MainViewCamera);
|