@netless/window-manager 1.0.0-canary.3 → 1.0.0-canary.32
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/__mocks__/white-web-sdk.ts +10 -1
- package/dist/index.cjs.js +120 -12
- package/dist/index.es.js +2284 -954
- package/dist/index.umd.js +120 -12
- package/dist/{App → src/App}/AppContext.d.ts +12 -8
- package/dist/{App → src/App}/AppPageStateImpl.d.ts +0 -0
- package/dist/{App → src/App}/AppProxy.d.ts +36 -7
- package/dist/{App → src/App}/MagixEvent/index.d.ts +0 -0
- package/dist/{App → src/App}/Storage/StorageEvent.d.ts +0 -0
- package/dist/{App → src/App}/Storage/index.d.ts +0 -0
- package/dist/{App → src/App}/Storage/typings.d.ts +0 -0
- package/dist/{App → src/App}/Storage/utils.d.ts +0 -0
- package/dist/src/App/WhiteboardView.d.ts +27 -0
- package/dist/{App → src/App}/index.d.ts +2 -1
- package/dist/src/App/type.d.ts +21 -0
- package/dist/{AppListener.d.ts → src/AppListener.d.ts} +0 -2
- package/dist/{AppManager.d.ts → src/AppManager.d.ts} +7 -6
- package/dist/{AttributesDelegate.d.ts → src/AttributesDelegate.d.ts} +11 -16
- package/dist/{BoxEmitter.d.ts → src/BoxEmitter.d.ts} +0 -0
- package/dist/{BoxManager.d.ts → src/BoxManager.d.ts} +10 -7
- package/dist/{BuiltinApps.d.ts → src/BuiltinApps.d.ts} +3 -0
- package/dist/{Cursor → src/Cursor}/Cursor.d.ts +0 -0
- package/dist/{Cursor → src/Cursor}/icons.d.ts +0 -0
- package/dist/{Cursor → src/Cursor}/index.d.ts +3 -3
- package/dist/{Helper.d.ts → src/Helper.d.ts} +4 -8
- package/dist/{InternalEmitter.d.ts → src/InternalEmitter.d.ts} +3 -4
- package/dist/{Page → src/Page}/PageController.d.ts +1 -0
- package/dist/{Page → src/Page}/index.d.ts +0 -0
- package/dist/{PageState.d.ts → src/PageState.d.ts} +0 -0
- package/dist/{ReconnectRefresher.d.ts → src/ReconnectRefresher.d.ts} +1 -1
- package/dist/{RedoUndo.d.ts → src/RedoUndo.d.ts} +0 -0
- package/dist/{Register → src/Register}/index.d.ts +0 -0
- package/dist/{Register → src/Register}/loader.d.ts +0 -0
- package/dist/{Register → src/Register}/storage.d.ts +0 -0
- package/dist/{Utils → src/Utils}/AppCreateQueue.d.ts +0 -0
- package/dist/{Utils → src/Utils}/Common.d.ts +1 -0
- package/dist/{Utils → src/Utils}/Reactive.d.ts +0 -0
- package/dist/{Utils → src/Utils}/RoomHacker.d.ts +0 -0
- package/dist/{Utils → src/Utils}/error.d.ts +0 -0
- package/dist/{Utils → src/Utils}/log.d.ts +0 -0
- package/dist/src/View/CameraSynchronizer.d.ts +18 -0
- package/dist/{View → src/View}/MainView.d.ts +18 -7
- package/dist/{View → src/View}/ViewManager.d.ts +0 -0
- package/dist/src/View/ViewSync.d.ts +24 -0
- package/dist/{callback.d.ts → src/callback.d.ts} +5 -0
- package/dist/{constants.d.ts → src/constants.d.ts} +8 -5
- package/dist/src/image.d.ts +19 -0
- package/dist/{index.d.ts → src/index.d.ts} +40 -14
- package/dist/src/shim.d.ts +11 -0
- package/dist/{typings.d.ts → src/typings.d.ts} +8 -2
- package/dist/style.css +1 -1
- package/docs/app-context.md +157 -25
- package/docs/mirgrate-to-1.0.md +28 -0
- package/package.json +12 -7
- package/playwright.config.ts +29 -0
- package/pnpm-lock.yaml +517 -35
- package/src/App/AppContext.ts +50 -28
- package/src/App/AppProxy.ts +266 -80
- package/src/App/{WhiteBoardView.ts → WhiteboardView.ts} +38 -7
- package/src/App/index.ts +2 -1
- package/src/App/type.ts +22 -0
- package/src/AppListener.ts +5 -21
- package/src/AppManager.ts +56 -43
- package/src/AttributesDelegate.ts +19 -19
- package/src/BoxManager.ts +60 -40
- package/src/BuiltinApps.ts +5 -0
- package/src/Cursor/Cursor.ts +7 -3
- package/src/Cursor/index.ts +7 -8
- package/src/Helper.ts +25 -7
- package/src/InternalEmitter.ts +3 -4
- package/src/Page/PageController.ts +1 -0
- package/src/PageState.ts +1 -1
- package/src/ReconnectRefresher.ts +7 -2
- package/src/Utils/Common.ts +9 -0
- package/src/Utils/Reactive.ts +27 -26
- package/src/Utils/RoomHacker.ts +3 -0
- package/src/View/CameraSynchronizer.ts +37 -34
- package/src/View/MainView.ts +108 -81
- package/src/View/ViewSync.ts +110 -0
- package/src/callback.ts +1 -0
- package/src/constants.ts +6 -3
- package/src/index.ts +141 -57
- package/src/style.css +3 -46
- package/src/typings.ts +8 -2
- package/vite.config.js +5 -3
- package/dist/App/WhiteBoardView.d.ts +0 -18
- package/dist/View/CameraSynchronizer.d.ts +0 -17
@@ -1,20 +1,20 @@
|
|
1
1
|
import { AnimationMode } from "white-web-sdk";
|
2
|
-
import {
|
2
|
+
import { isEqual, pick, throttle } from "lodash";
|
3
3
|
import type { TeleBoxRect } from "@netless/telebox-insider";
|
4
|
-
import type { Camera, View
|
5
|
-
import type {
|
4
|
+
import type { Camera, View } from "white-web-sdk";
|
5
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
6
6
|
|
7
|
-
export type SaveCamera = (camera:
|
7
|
+
export type SaveCamera = (camera: ICamera) => void;
|
8
8
|
|
9
9
|
export class CameraSynchronizer {
|
10
|
-
|
11
|
-
|
10
|
+
public remoteCamera?: ICamera;
|
11
|
+
public remoteSize?: ISize;
|
12
12
|
protected rect?: TeleBoxRect;
|
13
13
|
protected view?: View;
|
14
14
|
|
15
15
|
constructor(protected saveCamera: SaveCamera) {}
|
16
16
|
|
17
|
-
public setRect(rect: TeleBoxRect) {
|
17
|
+
public setRect = (rect: TeleBoxRect) => {
|
18
18
|
this.rect = rect;
|
19
19
|
if (this.remoteCamera && this.remoteSize) {
|
20
20
|
this.onRemoteUpdate(this.remoteCamera, this.remoteSize);
|
@@ -26,42 +26,45 @@ export class CameraSynchronizer {
|
|
26
26
|
}
|
27
27
|
|
28
28
|
// 远端 Camera 或者 size 更新
|
29
|
-
public onRemoteUpdate = throttle((camera:
|
29
|
+
public onRemoteUpdate = throttle((camera: ICamera, size: ISize) => {
|
30
30
|
this.remoteCamera = camera;
|
31
31
|
this.remoteSize = size;
|
32
32
|
if (this.remoteSize && this.rect) {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
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,
|
33
|
+
const wScale = this.rect.width / size.width;
|
34
|
+
const hScale = this.rect.height / size.height;
|
35
|
+
const nextScale = camera.scale * Math.min(wScale, hScale);
|
36
|
+
const config: Partial<Camera> & { animationMode: AnimationMode } = {
|
43
37
|
scale: nextScale,
|
44
|
-
animationMode: AnimationMode.
|
45
|
-
}
|
46
|
-
|
47
|
-
|
38
|
+
animationMode: AnimationMode.Continuous,
|
39
|
+
}
|
40
|
+
if (camera.centerX !== null) {
|
41
|
+
config.centerX = camera.centerX;
|
42
|
+
}
|
43
|
+
if (camera.centerY !== null) {
|
44
|
+
config.centerY = camera.centerY;
|
45
|
+
}
|
46
|
+
this.moveCamera(config);
|
48
47
|
}
|
49
|
-
},
|
48
|
+
}, 10);
|
50
49
|
|
50
|
+
public onRemoteSizeUpdate(size: ISize) {
|
51
|
+
this.remoteSize = size;
|
52
|
+
const needMoveCamera = !isEqual(pick(this.rect, ["width", "height"]), pick(size, ["width", "height"]));
|
53
|
+
if (this.rect && this.remoteCamera && needMoveCamera) {
|
54
|
+
const scale = this.rect.width / size.width;
|
55
|
+
const nextScale = this.remoteCamera.scale * scale;
|
56
|
+
this.moveCamera({
|
57
|
+
scale: nextScale,
|
58
|
+
})
|
59
|
+
}
|
60
|
+
}
|
51
61
|
|
52
|
-
public onLocalCameraUpdate(camera:
|
62
|
+
public onLocalCameraUpdate(camera: ICamera) {
|
53
63
|
this.saveCamera(camera);
|
64
|
+
this.remoteCamera = camera;
|
54
65
|
}
|
55
66
|
|
56
|
-
|
57
|
-
|
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
|
-
}
|
67
|
+
private moveCamera(camera: Partial<Camera>) {
|
68
|
+
this.view?.moveCamera({ ...camera, animationMode: AnimationMode.Continuous });
|
66
69
|
}
|
67
70
|
}
|
package/src/View/MainView.ts
CHANGED
@@ -1,73 +1,96 @@
|
|
1
|
-
import { reaction } from "white-web-sdk";
|
2
1
|
import { callbacks } from "../callback";
|
3
2
|
import { createView } from "./ViewManager";
|
4
3
|
import { debounce, get, isEqual } from "lodash";
|
5
4
|
import { emitter } from "../InternalEmitter";
|
6
5
|
import { Events } from "../constants";
|
7
6
|
import { Fields } from "../AttributesDelegate";
|
8
|
-
import {
|
7
|
+
import { AnimationMode, reaction, toJS } from "white-web-sdk";
|
8
|
+
import { releaseView, setScenePath, setViewFocusScenePath } from "../Utils/Common";
|
9
9
|
import { SideEffectManager } from "side-effect-manager";
|
10
|
-
import
|
10
|
+
import { Val } from "value-enhancer";
|
11
|
+
import { ViewSync } from "./ViewSync";
|
12
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
13
|
+
import type { Size, View } from "white-web-sdk";
|
11
14
|
import type { AppManager } from "../AppManager";
|
12
|
-
import { CameraSynchronizer } from "./CameraSynchronizer";
|
13
15
|
|
14
16
|
export class MainViewProxy {
|
15
17
|
private started = false;
|
16
18
|
private mainViewIsAddListener = false;
|
17
19
|
private mainView: View;
|
18
20
|
private store = this.manager.store;
|
19
|
-
private synchronizer: CameraSynchronizer;
|
20
21
|
|
21
22
|
private sideEffectManager = new SideEffectManager();
|
22
23
|
|
24
|
+
public camera$ = new Val<ICamera | undefined>(undefined);
|
25
|
+
public size$ = new Val<ISize | undefined>(undefined);
|
26
|
+
public view$ = new Val<View | undefined>(undefined);
|
27
|
+
|
28
|
+
public viewSync?: ViewSync;
|
29
|
+
|
23
30
|
constructor(private manager: AppManager) {
|
24
|
-
this.synchronizer = new CameraSynchronizer(
|
25
|
-
camera => this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
|
26
|
-
);
|
27
31
|
this.mainView = this.createMainView();
|
28
|
-
this.moveCameraSizeByAttributes();
|
29
32
|
emitter.once("mainViewMounted").then(() => {
|
30
33
|
this.addMainViewListener();
|
31
34
|
this.start();
|
32
35
|
this.ensureCameraAndSize();
|
33
36
|
this.startListenWritableChange();
|
34
37
|
});
|
35
|
-
this.sideEffectManager.add(() =>
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
this.sideEffectManager.add(() => [
|
39
|
+
emitter.on("startReconnect", () => {
|
40
|
+
releaseView(this.mainView);
|
41
|
+
}),
|
42
|
+
]);
|
43
|
+
this.createViewSync();
|
44
|
+
this.sideEffectManager.add(() => emitter.on("focusedChange", ({ focused }) => {
|
45
|
+
if (focused === undefined) {
|
46
|
+
const scenePath = this.store.getMainViewScenePath();
|
47
|
+
if (scenePath) {
|
48
|
+
setScenePath(this.manager.room, scenePath);
|
42
49
|
}
|
50
|
+
}
|
51
|
+
}));
|
52
|
+
}
|
53
|
+
|
54
|
+
public createViewSync = () => {
|
55
|
+
if (this.manager.boxManager && !this.viewSync) {
|
56
|
+
this.viewSync = new ViewSync({
|
57
|
+
uid: this.manager.uid,
|
58
|
+
view$: this.view$,
|
59
|
+
camera$: this.camera$,
|
60
|
+
size$: this.size$,
|
61
|
+
stageRect$: this.manager.boxManager?.stageRect$,
|
62
|
+
viewMode$: this.manager.windowManger.viewMode$,
|
63
|
+
storeCamera: this.storeCamera,
|
64
|
+
storeSize: this.storeSize,
|
43
65
|
});
|
44
|
-
});
|
45
|
-
const rect = this.manager.boxManager?.stageRect;
|
46
|
-
if (rect) {
|
47
|
-
this.synchronizer.setRect(rect);
|
48
66
|
}
|
49
|
-
|
50
|
-
return emitter.on("playgroundSizeChange", rect => {
|
51
|
-
this.synchronizer.setRect(rect);
|
52
|
-
this.synchronizer.onLocalSizeUpdate(rect);
|
53
|
-
});
|
54
|
-
});
|
55
|
-
}
|
67
|
+
};
|
56
68
|
|
57
69
|
private startListenWritableChange = () => {
|
58
|
-
this.sideEffectManager.add(() =>
|
59
|
-
|
70
|
+
this.sideEffectManager.add(() =>
|
71
|
+
emitter.on("writableChange", isWritable => {
|
60
72
|
if (isWritable) {
|
61
73
|
this.ensureCameraAndSize();
|
62
74
|
}
|
63
|
-
})
|
64
|
-
|
75
|
+
})
|
76
|
+
);
|
65
77
|
};
|
66
78
|
|
67
79
|
public ensureCameraAndSize() {
|
68
80
|
if (!this.mainViewCamera || !this.mainViewSize) {
|
69
81
|
this.manager.dispatchInternalEvent(Events.InitMainViewCamera);
|
70
|
-
this.
|
82
|
+
this.storeCamera({
|
83
|
+
id: this.manager.uid,
|
84
|
+
...this.view.camera
|
85
|
+
});
|
86
|
+
const stageRect = this.manager.boxManager?.stageRect;
|
87
|
+
if (stageRect && !this.mainViewSize) {
|
88
|
+
this.storeSize({
|
89
|
+
id: this.manager.uid,
|
90
|
+
width: stageRect.width,
|
91
|
+
height: stageRect.height
|
92
|
+
});
|
93
|
+
}
|
71
94
|
}
|
72
95
|
}
|
73
96
|
|
@@ -83,55 +106,73 @@ export class MainViewProxy {
|
|
83
106
|
return get(this.view, ["didRelease"]);
|
84
107
|
}
|
85
108
|
|
86
|
-
private moveCameraSizeByAttributes() {
|
87
|
-
this.synchronizer.onRemoteUpdate(this.mainViewCamera, this.mainViewSize);
|
88
|
-
}
|
89
|
-
|
90
109
|
public start() {
|
91
110
|
if (this.started) return;
|
92
|
-
this.sizeChangeHandler(this.mainViewSize);
|
93
111
|
this.addCameraListener();
|
94
112
|
this.addCameraReaction();
|
95
113
|
this.started = true;
|
96
114
|
}
|
97
115
|
|
98
116
|
public addCameraReaction = () => {
|
99
|
-
this.manager.refresher
|
117
|
+
this.manager.refresher.add(Fields.MainViewCamera, this.cameraReaction);
|
118
|
+
this.manager.refresher.add(Fields.MainViewSize, this.sizeReaction);
|
100
119
|
};
|
101
120
|
|
102
|
-
public
|
103
|
-
const
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
121
|
+
public storeCurrentCamera = () => {
|
122
|
+
const iCamera = this.view.camera;
|
123
|
+
this.storeCamera({
|
124
|
+
id: this.manager.uid,
|
125
|
+
...iCamera
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
public storeCurrentSize = () => {
|
130
|
+
const rect = this.manager.boxManager?.stageRect;
|
131
|
+
if (rect) {
|
132
|
+
this.storeSize({
|
133
|
+
id: this.manager.uid,
|
134
|
+
width: rect.width,
|
135
|
+
height: rect.height
|
136
|
+
});
|
108
137
|
}
|
109
138
|
}
|
110
139
|
|
140
|
+
public storeCamera = (camera: ICamera) => {
|
141
|
+
this.store.setMainViewCamera(camera);
|
142
|
+
};
|
143
|
+
|
144
|
+
public storeSize = (size: ISize) => {
|
145
|
+
this.store.setMainViewSize(size);
|
146
|
+
};
|
147
|
+
|
111
148
|
private cameraReaction = () => {
|
112
149
|
return reaction(
|
113
150
|
() => this.mainViewCamera,
|
114
151
|
camera => {
|
115
|
-
if (camera
|
116
|
-
|
152
|
+
if (camera) {
|
153
|
+
const rawCamera = toJS(camera);
|
154
|
+
if (!isEqual(rawCamera, this.camera$.value)) {
|
155
|
+
this.camera$.setValue(rawCamera);
|
156
|
+
}
|
117
157
|
}
|
118
158
|
},
|
119
159
|
{ fireImmediately: true }
|
120
160
|
);
|
121
161
|
};
|
122
162
|
|
123
|
-
|
124
|
-
|
125
|
-
this.
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
163
|
+
private sizeReaction = () => {
|
164
|
+
return reaction(
|
165
|
+
() => this.mainViewSize,
|
166
|
+
size => {
|
167
|
+
if (size) {
|
168
|
+
const rawSize = toJS(size);
|
169
|
+
if (!isEqual(rawSize, this.size$.value)) {
|
170
|
+
this.size$.setValue(rawSize);
|
171
|
+
}
|
172
|
+
}
|
173
|
+
},
|
174
|
+
{ fireImmediately: true }
|
175
|
+
);
|
135
176
|
};
|
136
177
|
|
137
178
|
public get view(): View {
|
@@ -148,7 +189,7 @@ export class MainViewProxy {
|
|
148
189
|
if (mainViewScenePath) {
|
149
190
|
setViewFocusScenePath(mainView, mainViewScenePath);
|
150
191
|
}
|
151
|
-
this.
|
192
|
+
this.view$.setValue(mainView);
|
152
193
|
return mainView;
|
153
194
|
}
|
154
195
|
|
@@ -170,33 +211,18 @@ export class MainViewProxy {
|
|
170
211
|
public rebind(): void {
|
171
212
|
const divElement = this.mainView.divElement;
|
172
213
|
const disableCameraTransform = this.mainView.disableCameraTransform;
|
214
|
+
const camera = { ...this.mainView.camera };
|
173
215
|
this.stop();
|
174
|
-
|
175
|
-
this.mainView.release();
|
176
|
-
}
|
216
|
+
releaseView(this.mainView);
|
177
217
|
this.removeMainViewListener();
|
178
218
|
this.mainView = this.createMainView();
|
179
219
|
this.mainView.disableCameraTransform = disableCameraTransform;
|
180
220
|
this.mainView.divElement = divElement;
|
221
|
+
this.mainView.moveCamera({ ...camera, animationMode: AnimationMode.Immediately });
|
181
222
|
this.addMainViewListener();
|
182
223
|
this.start();
|
183
224
|
}
|
184
225
|
|
185
|
-
private onCameraUpdatedByDevice = (camera: Camera) => {
|
186
|
-
this.synchronizer.onLocalCameraUpdate(camera);
|
187
|
-
const size = this.getStageSize();
|
188
|
-
if (size && !isEqual(size, this.mainViewSize)) {
|
189
|
-
this.setMainViewSize(size);
|
190
|
-
}
|
191
|
-
};
|
192
|
-
|
193
|
-
private getStageSize(): Size | undefined {
|
194
|
-
const stage = this.manager.boxManager?.stageRect;
|
195
|
-
if (stage) {
|
196
|
-
return { width: stage.width, height: stage.height };
|
197
|
-
}
|
198
|
-
}
|
199
|
-
|
200
226
|
public addMainViewListener(): void {
|
201
227
|
if (this.mainViewIsAddListener) return;
|
202
228
|
if (this.view.divElement) {
|
@@ -229,13 +255,11 @@ export class MainViewProxy {
|
|
229
255
|
}, 50);
|
230
256
|
|
231
257
|
private addCameraListener() {
|
232
|
-
this.view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
233
258
|
this.view.callbacks.on("onCameraUpdated", this.onCameraOrSizeUpdated);
|
234
259
|
this.view.callbacks.on("onSizeUpdated", this.onCameraOrSizeUpdated);
|
235
260
|
}
|
236
261
|
|
237
262
|
private removeCameraListener() {
|
238
|
-
this.view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
239
263
|
this.view.callbacks.off("onCameraUpdated", this.onCameraOrSizeUpdated);
|
240
264
|
this.view.callbacks.off("onSizeUpdated", this.onCameraOrSizeUpdated);
|
241
265
|
}
|
@@ -246,12 +270,15 @@ export class MainViewProxy {
|
|
246
270
|
|
247
271
|
public stop() {
|
248
272
|
this.removeCameraListener();
|
249
|
-
this.manager.refresher
|
250
|
-
this.manager.refresher
|
273
|
+
this.manager.refresher.remove(Fields.MainViewCamera);
|
274
|
+
this.manager.refresher.remove(Fields.MainViewSize);
|
251
275
|
this.started = false;
|
252
276
|
}
|
253
277
|
|
254
278
|
public destroy() {
|
279
|
+
this.camera$.destroy();
|
280
|
+
this.size$.destroy();
|
281
|
+
this.view$.destroy();
|
255
282
|
this.removeMainViewListener();
|
256
283
|
this.stop();
|
257
284
|
this.sideEffectManager.flushAll();
|
@@ -0,0 +1,110 @@
|
|
1
|
+
import { ViewMode, AnimationMode } from "white-web-sdk";
|
2
|
+
import { CameraSynchronizer } from "./CameraSynchronizer";
|
3
|
+
import { combine } from "value-enhancer";
|
4
|
+
import { isEqual } from "lodash";
|
5
|
+
import { SideEffectManager } from "side-effect-manager";
|
6
|
+
import type { Camera, View } from "white-web-sdk";
|
7
|
+
import type { Val, ReadonlyVal } from "value-enhancer";
|
8
|
+
import type { ICamera, ISize } from "../AttributesDelegate";
|
9
|
+
import type { TeleBoxRect } from "@netless/telebox-insider";
|
10
|
+
|
11
|
+
export type ViewSyncContext = {
|
12
|
+
uid: string;
|
13
|
+
// 远端 camera
|
14
|
+
camera$: Val<ICamera | undefined, boolean>;
|
15
|
+
// 远端 size
|
16
|
+
size$: Val<ISize | undefined>;
|
17
|
+
|
18
|
+
stageRect$: ReadonlyVal<TeleBoxRect>;
|
19
|
+
|
20
|
+
viewMode$?: Val<ViewMode>;
|
21
|
+
|
22
|
+
storeCamera: (camera: ICamera) => void;
|
23
|
+
|
24
|
+
storeSize: (size: ISize) => void;
|
25
|
+
|
26
|
+
view$: Val<View | undefined>;
|
27
|
+
};
|
28
|
+
|
29
|
+
export class ViewSync {
|
30
|
+
private sem = new SideEffectManager();
|
31
|
+
private synchronizer: CameraSynchronizer;
|
32
|
+
|
33
|
+
constructor(private context: ViewSyncContext) {
|
34
|
+
this.synchronizer = new CameraSynchronizer((camera: ICamera) => {
|
35
|
+
this.context.camera$.setValue(camera, true);
|
36
|
+
const notStoreCamera =
|
37
|
+
this.context.viewMode$ && this.context.viewMode$.value === ViewMode.Freedom;
|
38
|
+
if (notStoreCamera) {
|
39
|
+
return;
|
40
|
+
} else {
|
41
|
+
this.context.storeCamera(camera);
|
42
|
+
}
|
43
|
+
});
|
44
|
+
this.bindView(this.context.view$.value);
|
45
|
+
this.sem.add(() => [
|
46
|
+
this.context.view$.subscribe(view => {
|
47
|
+
const currentCamera = this.context.camera$.value;
|
48
|
+
if (currentCamera && this.context.size$.value) {
|
49
|
+
view?.moveCamera({
|
50
|
+
scale: 1,
|
51
|
+
animationMode: AnimationMode.Immediately,
|
52
|
+
});
|
53
|
+
this.synchronizer.onRemoteUpdate(currentCamera, this.context.size$.value);
|
54
|
+
}
|
55
|
+
|
56
|
+
this.bindView(view);
|
57
|
+
}),
|
58
|
+
this.context.camera$.subscribe((camera, skipUpdate) => {
|
59
|
+
const size = this.context.size$.value;
|
60
|
+
if (camera && size && !skipUpdate) {
|
61
|
+
this.synchronizer.onRemoteUpdate(camera, size);
|
62
|
+
}
|
63
|
+
}),
|
64
|
+
this.context.size$.subscribe(size => {
|
65
|
+
if (size) {
|
66
|
+
this.synchronizer.onRemoteSizeUpdate(size);
|
67
|
+
}
|
68
|
+
}),
|
69
|
+
this.context.stageRect$.subscribe(rect => {
|
70
|
+
if (rect) {
|
71
|
+
this.synchronizer.setRect(rect);
|
72
|
+
}
|
73
|
+
})
|
74
|
+
]);
|
75
|
+
const camera$size$ = combine([this.context.camera$, this.context.size$]);
|
76
|
+
camera$size$.reaction(([camera, size]) => {
|
77
|
+
if (camera && size) {
|
78
|
+
this.synchronizer.onRemoteUpdate(camera, size);
|
79
|
+
camera$size$.destroy();
|
80
|
+
}
|
81
|
+
});
|
82
|
+
}
|
83
|
+
|
84
|
+
public bindView = (view?: View) => {
|
85
|
+
if (!view) return;
|
86
|
+
this.synchronizer.setView(view);
|
87
|
+
this.sem.flush("view");
|
88
|
+
this.sem.add(() => {
|
89
|
+
view.callbacks.on("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
90
|
+
return () =>
|
91
|
+
view.callbacks.off("onCameraUpdatedByDevice", this.onCameraUpdatedByDevice);
|
92
|
+
}, "view");
|
93
|
+
};
|
94
|
+
|
95
|
+
private onCameraUpdatedByDevice = (camera: Camera) => {
|
96
|
+
if (!camera) return;
|
97
|
+
this.synchronizer.onLocalCameraUpdate({ ...camera, id: this.context.uid });
|
98
|
+
const stage = this.context.stageRect$.value;
|
99
|
+
if (stage) {
|
100
|
+
const size = { width: stage.width, height: stage.height, id: this.context.uid };
|
101
|
+
if (!isEqual(size, this.context.size$.value)) {
|
102
|
+
this.context.storeSize(size);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
};
|
106
|
+
|
107
|
+
public destroy() {
|
108
|
+
this.sem.flushAll();
|
109
|
+
}
|
110
|
+
}
|
package/src/callback.ts
CHANGED
package/src/constants.ts
CHANGED
@@ -5,18 +5,16 @@ export enum Events {
|
|
5
5
|
AppBoxStateChange = "AppBoxStateChange",
|
6
6
|
GetAttributes = "GetAttributes",
|
7
7
|
UpdateWindowManagerWrapper = "UpdateWindowManagerWrapper",
|
8
|
-
InitReplay = "InitReplay",
|
9
8
|
WindowCreated = "WindowCreated",
|
10
9
|
SetMainViewScenePath = "SetMainViewScenePath",
|
11
10
|
SetMainViewSceneIndex = "SetMainViewSceneIndex",
|
12
11
|
SetAppFocusIndex = "SetAppFocusIndex",
|
13
12
|
SwitchViewsToFreedom = "SwitchViewsToFreedom",
|
14
|
-
MoveCamera = "MoveCamera",
|
15
|
-
MoveCameraToContain = "MoveCameraToContain",
|
16
13
|
CursorMove = "CursorMove",
|
17
14
|
RootDirRemoved = "RootDirRemoved",
|
18
15
|
Refresh = "Refresh",
|
19
16
|
InitMainViewCamera = "InitMainViewCamera",
|
17
|
+
InvokeAttributesUpdateCallback = "InvokeAttributesUpdateCallback",
|
20
18
|
}
|
21
19
|
|
22
20
|
export const MagixEventName = "__WindowManger";
|
@@ -27,6 +25,11 @@ export enum AppAttributes {
|
|
27
25
|
Position = "position",
|
28
26
|
SceneIndex = "SceneIndex",
|
29
27
|
ZIndex = "zIndex",
|
28
|
+
Visible = "visible",
|
29
|
+
Ratio = "ratio",
|
30
|
+
StageRatio = "stageRatio",
|
31
|
+
Draggable = "draggable",
|
32
|
+
Resizable = "resizable",
|
30
33
|
}
|
31
34
|
|
32
35
|
export enum AppEvents {
|