@netless/window-manager 1.0.0-canary.9 → 1.0.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/LICENSE.txt +21 -0
- package/README.md +90 -64
- package/README.zh-cn.md +224 -0
- package/dist/index.d.ts +1133 -40
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/{index.es.js → index.mjs} +9480 -6984
- package/dist/index.mjs.map +1 -0
- package/dist/style.css +1 -1
- package/docs/advanced.md +55 -55
- package/docs/api.md +124 -113
- package/docs/app-context.md +248 -209
- package/docs/basic.md +25 -26
- package/docs/camera.md +19 -20
- package/docs/cn/advanced.md +137 -0
- package/docs/cn/api.md +309 -0
- package/docs/cn/app-context.md +369 -0
- package/docs/cn/basic.md +64 -0
- package/docs/cn/camera.md +53 -0
- package/docs/cn/concept.md +9 -0
- package/docs/cn/custom-max-bar.md +31 -0
- package/docs/cn/develop-app.md +94 -0
- package/docs/cn/export-pdf.md +48 -0
- package/docs/cn/migrate.md +60 -0
- package/docs/cn/replay.md +40 -0
- package/docs/concept.md +6 -5
- package/docs/custom-max-bar.md +31 -0
- package/docs/develop-app.md +22 -19
- package/docs/export-pdf.md +48 -0
- package/docs/migrate.md +25 -27
- package/docs/quickstart.md +50 -0
- package/docs/replay.md +20 -20
- package/package.json +32 -22
- package/src/App/AppContext.ts +105 -73
- package/src/App/AppPageStateImpl.ts +6 -25
- package/src/App/AppProxy.ts +41 -166
- package/src/App/MagixEvent/index.ts +38 -38
- package/src/App/Storage/StorageEvent.ts +13 -13
- package/src/App/Storage/index.ts +269 -245
- package/src/App/Storage/typings.ts +4 -2
- package/src/App/Storage/utils.ts +3 -3
- package/src/App/index.ts +0 -1
- package/src/AppListener.ts +8 -8
- package/src/AppManager.ts +88 -77
- package/src/AttributesDelegate.ts +42 -22
- package/src/BoxEmitter.ts +12 -6
- package/src/BoxManager.ts +128 -108
- package/src/ContainerResizeObserver.ts +75 -0
- package/src/Cursor/Cursor.svelte +16 -5
- package/src/Cursor/Cursor.svelte.d.ts +21 -0
- package/src/Cursor/Cursor.ts +77 -13
- package/src/Cursor/icons.ts +6 -0
- package/src/Cursor/icons2.ts +66 -0
- package/src/Cursor/index.ts +127 -26
- package/src/Helper.ts +94 -14
- package/src/InternalEmitter.ts +2 -7
- package/src/Page/index.ts +1 -1
- package/src/PageState.ts +6 -5
- package/src/ReconnectRefresher.ts +9 -4
- package/src/RedoUndo.ts +3 -3
- package/src/Register/index.ts +22 -17
- package/src/Register/loader.ts +26 -22
- package/src/Register/storage.ts +13 -13
- package/src/Utils/Common.ts +18 -14
- package/src/Utils/Reactive.ts +26 -25
- package/src/Utils/RoomHacker.ts +4 -4
- package/src/Utils/error.ts +0 -1
- package/src/View/IframeBridge.ts +680 -0
- package/src/View/MainView.ts +127 -53
- package/src/callback.ts +21 -1
- package/src/constants.ts +0 -2
- package/src/image/pencil-eraser-1.svg +3 -0
- package/src/image/pencil-eraser-2.svg +3 -0
- package/src/image/pencil-eraser-3.svg +3 -0
- package/src/index.ts +220 -83
- package/src/style.css +27 -10
- package/src/typings.ts +20 -10
- package/.prettierignore +0 -7
- package/.prettierrc.json +0 -9
- package/CHANGELOG.md +0 -196
- package/__mocks__/white-web-sdk.ts +0 -50
- package/dist/App/AppContext.d.ts +0 -76
- package/dist/App/AppPageStateImpl.d.ts +0 -21
- package/dist/App/AppProxy.d.ts +0 -86
- package/dist/App/AppViewSync.d.ts +0 -11
- package/dist/App/MagixEvent/index.d.ts +0 -29
- package/dist/App/Storage/StorageEvent.d.ts +0 -8
- package/dist/App/Storage/index.d.ts +0 -39
- package/dist/App/Storage/typings.d.ts +0 -22
- package/dist/App/Storage/utils.d.ts +0 -5
- package/dist/App/WhiteboardView.d.ts +0 -22
- package/dist/App/index.d.ts +0 -3
- package/dist/AppListener.d.ts +0 -21
- package/dist/AppManager.d.ts +0 -107
- package/dist/AttributesDelegate.d.ts +0 -80
- package/dist/BoxEmitter.d.ts +0 -34
- package/dist/BoxManager.d.ts +0 -99
- package/dist/BuiltinApps.d.ts +0 -5
- package/dist/Cursor/Cursor.d.ts +0 -39
- package/dist/Cursor/icons.d.ts +0 -3
- package/dist/Cursor/index.d.ts +0 -46
- package/dist/Helper.d.ts +0 -17
- package/dist/InternalEmitter.d.ts +0 -39
- package/dist/Page/PageController.d.ts +0 -21
- package/dist/Page/index.d.ts +0 -3
- package/dist/PageState.d.ts +0 -9
- package/dist/ReconnectRefresher.d.ts +0 -24
- package/dist/RedoUndo.d.ts +0 -18
- package/dist/Register/index.d.ts +0 -28
- package/dist/Register/loader.d.ts +0 -4
- package/dist/Register/storage.d.ts +0 -8
- package/dist/Utils/AppCreateQueue.d.ts +0 -15
- package/dist/Utils/Common.d.ts +0 -23
- package/dist/Utils/Reactive.d.ts +0 -6
- package/dist/Utils/RoomHacker.d.ts +0 -3
- package/dist/Utils/error.d.ts +0 -27
- package/dist/Utils/log.d.ts +0 -1
- package/dist/View/CameraSynchronizer.d.ts +0 -16
- package/dist/View/MainView.d.ts +0 -47
- package/dist/View/ViewManager.d.ts +0 -13
- package/dist/callback.d.ts +0 -24
- package/dist/constants.d.ts +0 -49
- package/dist/index.cjs.js +0 -46
- package/dist/index.umd.js +0 -46
- package/dist/typings.d.ts +0 -82
- package/jest.config.js +0 -27
- package/pnpm-lock.yaml +0 -6302
- package/src/App/AppViewSync.ts +0 -68
- package/src/App/WhiteboardView.ts +0 -83
- package/src/View/CameraSynchronizer.ts +0 -56
- package/vite.config.js +0 -51
- /package/docs/{qickstart.md → cn/quickstart.md} +0 -0
package/src/View/MainView.ts
CHANGED
@@ -1,63 +1,78 @@
|
|
1
|
+
import { AnimationMode, reaction, ViewMode } from "white-web-sdk";
|
1
2
|
import { callbacks } from "../callback";
|
2
|
-
import { CameraSynchronizer } from "./CameraSynchronizer";
|
3
3
|
import { createView } from "./ViewManager";
|
4
|
-
import { debounce, get, isEqual } from "lodash";
|
5
|
-
import {
|
6
|
-
import { Events } from "../constants";
|
4
|
+
import { debounce, get, isEmpty, isEqual } from "lodash";
|
5
|
+
import { internalEmitter } from "../InternalEmitter";
|
7
6
|
import { Fields } from "../AttributesDelegate";
|
8
|
-
import {
|
9
|
-
import { releaseView, setViewFocusScenePath } from "../Utils/Common";
|
7
|
+
import { setViewFocusScenePath } from "../Utils/Common";
|
10
8
|
import { SideEffectManager } from "side-effect-manager";
|
11
|
-
import type { Camera, Size, View } from "white-web-sdk";
|
9
|
+
import type { Camera, Room, Size, View } from "white-web-sdk";
|
12
10
|
import type { AppManager } from "../AppManager";
|
11
|
+
import { Events } from "../constants";
|
13
12
|
|
14
13
|
export class MainViewProxy {
|
14
|
+
/** Refresh the view's camera in an interval of 1.5s. */
|
15
|
+
public polling = false;
|
16
|
+
|
17
|
+
private scale?: number;
|
15
18
|
private started = false;
|
16
19
|
private mainViewIsAddListener = false;
|
17
20
|
private mainView: View;
|
18
21
|
private store = this.manager.store;
|
19
|
-
private
|
22
|
+
private viewMode = this.manager.windowManger.viewMode;
|
20
23
|
|
21
24
|
private sideEffectManager = new SideEffectManager();
|
22
25
|
|
23
26
|
constructor(private manager: AppManager) {
|
24
|
-
this.synchronizer = new CameraSynchronizer(camera =>
|
25
|
-
this.store.setMainViewCamera({ ...camera, id: this.manager.uid })
|
26
|
-
);
|
27
27
|
this.mainView = this.createMainView();
|
28
28
|
this.moveCameraSizeByAttributes();
|
29
|
-
|
29
|
+
internalEmitter.once("mainViewMounted").then(() => {
|
30
30
|
this.addMainViewListener();
|
31
31
|
this.start();
|
32
32
|
this.ensureCameraAndSize();
|
33
33
|
this.startListenWritableChange();
|
34
34
|
});
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
35
|
+
const playgroundSizeChangeListener = () => {
|
36
|
+
this.sizeChangeHandler(this.mainViewSize);
|
37
|
+
};
|
38
|
+
this.sideEffectManager.add(() => {
|
39
|
+
return internalEmitter.on("playgroundSizeChange", playgroundSizeChangeListener);
|
40
|
+
});
|
41
|
+
this.sideEffectManager.add(() => {
|
42
|
+
return internalEmitter.on("containerSizeRatioUpdate", this.onUpdateContainerSizeRatio);
|
43
|
+
});
|
44
|
+
this.sideEffectManager.add(() => {
|
45
|
+
return internalEmitter.on("startReconnect", () => {
|
46
|
+
if (!this.didRelease) {
|
47
|
+
this.mainView.release();
|
48
|
+
}
|
49
|
+
});
|
50
|
+
});
|
51
|
+
this.sideEffectManager.setInterval(this.syncCamera, 1500);
|
48
52
|
}
|
49
53
|
|
54
|
+
// Guard function when the camera is not synced
|
55
|
+
private syncCamera = () => {
|
56
|
+
if (!this.polling || this.viewMode !== ViewMode.Broadcaster) return;
|
57
|
+
const { mainViewCamera } = this;
|
58
|
+
if (mainViewCamera && mainViewCamera.id !== this.manager.uid) {
|
59
|
+
this.moveCameraSizeByAttributes();
|
60
|
+
}
|
61
|
+
};
|
62
|
+
|
50
63
|
private startListenWritableChange = () => {
|
51
|
-
this.sideEffectManager.add(() =>
|
52
|
-
|
64
|
+
this.sideEffectManager.add(() => {
|
65
|
+
return internalEmitter.on("writableChange", isWritable => {
|
53
66
|
if (isWritable) {
|
54
67
|
this.ensureCameraAndSize();
|
55
68
|
}
|
56
|
-
|
57
|
-
|
69
|
+
if (this.manager.room) this.syncMainView(this.manager.room);
|
70
|
+
});
|
71
|
+
});
|
58
72
|
};
|
59
73
|
|
60
74
|
public ensureCameraAndSize() {
|
75
|
+
if (this.viewMode !== ViewMode.Broadcaster) return;
|
61
76
|
if (!this.mainViewCamera || !this.mainViewSize) {
|
62
77
|
this.manager.dispatchInternalEvent(Events.InitMainViewCamera);
|
63
78
|
this.setCameraAndSize();
|
@@ -77,13 +92,16 @@ export class MainViewProxy {
|
|
77
92
|
}
|
78
93
|
|
79
94
|
private moveCameraSizeByAttributes() {
|
80
|
-
this.
|
95
|
+
this.moveCameraToContian(this.mainViewSize);
|
96
|
+
this.moveCamera(this.mainViewCamera);
|
81
97
|
}
|
82
98
|
|
83
99
|
public start() {
|
100
|
+
this.sizeChangeHandler(this.mainViewSize);
|
84
101
|
if (this.started) return;
|
85
102
|
this.addCameraListener();
|
86
103
|
this.addCameraReaction();
|
104
|
+
if (this.manager.room) this.syncMainView(this.manager.room);
|
87
105
|
this.started = true;
|
88
106
|
}
|
89
107
|
|
@@ -92,12 +110,9 @@ export class MainViewProxy {
|
|
92
110
|
};
|
93
111
|
|
94
112
|
public setCameraAndSize(): void {
|
95
|
-
const
|
96
|
-
|
97
|
-
|
98
|
-
const size = { ...stageSize, id: this.manager.uid };
|
99
|
-
this.store.setMainViewCameraAndSize(camera, size);
|
100
|
-
}
|
113
|
+
const camera = { ...this.mainView.camera, id: this.manager.uid };
|
114
|
+
const size = { ...this.mainView.size, id: this.manager.uid };
|
115
|
+
this.store.setMainViewCameraAndSize(camera, size);
|
101
116
|
}
|
102
117
|
|
103
118
|
private cameraReaction = () => {
|
@@ -105,18 +120,25 @@ export class MainViewProxy {
|
|
105
120
|
() => this.mainViewCamera,
|
106
121
|
camera => {
|
107
122
|
if (camera && camera.id !== this.manager.uid) {
|
108
|
-
this.
|
123
|
+
this.moveCameraToContian(this.mainViewSize);
|
124
|
+
this.moveCamera(camera);
|
109
125
|
}
|
110
126
|
},
|
111
127
|
{ fireImmediately: true }
|
112
128
|
);
|
113
129
|
};
|
114
130
|
|
131
|
+
public sizeChangeHandler = debounce((size: Size) => {
|
132
|
+
if (size) {
|
133
|
+
this.moveCameraToContian(size);
|
134
|
+
this.moveCamera(this.mainViewCamera);
|
135
|
+
}
|
136
|
+
this.ensureMainViewSize();
|
137
|
+
}, 30);
|
138
|
+
|
115
139
|
public onUpdateContainerSizeRatio = () => {
|
116
140
|
const size = this.store.getMainViewSize();
|
117
|
-
|
118
|
-
this.setCameraAndSize();
|
119
|
-
}
|
141
|
+
this.sizeChangeHandler(size);
|
120
142
|
};
|
121
143
|
|
122
144
|
public get view(): View {
|
@@ -133,7 +155,6 @@ export class MainViewProxy {
|
|
133
155
|
if (mainViewScenePath) {
|
134
156
|
setViewFocusScenePath(mainView, mainViewScenePath);
|
135
157
|
}
|
136
|
-
this.synchronizer.setView(mainView);
|
137
158
|
return mainView;
|
138
159
|
}
|
139
160
|
|
@@ -156,30 +177,26 @@ export class MainViewProxy {
|
|
156
177
|
const divElement = this.mainView.divElement;
|
157
178
|
const disableCameraTransform = this.mainView.disableCameraTransform;
|
158
179
|
this.stop();
|
159
|
-
|
180
|
+
if (!this.didRelease) {
|
181
|
+
this.mainView.release();
|
182
|
+
}
|
160
183
|
this.removeMainViewListener();
|
161
184
|
this.mainView = this.createMainView();
|
162
185
|
this.mainView.disableCameraTransform = disableCameraTransform;
|
163
186
|
this.mainView.divElement = divElement;
|
164
187
|
this.addMainViewListener();
|
165
188
|
this.start();
|
189
|
+
callbacks.emit("onMainViewRebind", this.mainView);
|
166
190
|
}
|
167
191
|
|
168
192
|
private onCameraUpdatedByDevice = (camera: Camera) => {
|
169
|
-
this.
|
170
|
-
|
171
|
-
if (
|
172
|
-
this.setMainViewSize(size);
|
193
|
+
if (this.viewMode === ViewMode.Follower) return;
|
194
|
+
this.store.setMainViewCamera({ ...camera, id: this.manager.uid });
|
195
|
+
if (!isEqual(this.mainViewSize, { ...this.mainView.size, id: this.manager.uid })) {
|
196
|
+
this.setMainViewSize(this.view.size);
|
173
197
|
}
|
174
198
|
};
|
175
199
|
|
176
|
-
private getStageSize(): Size | undefined {
|
177
|
-
const stage = this.manager.boxManager?.stageRect;
|
178
|
-
if (stage) {
|
179
|
-
return { width: stage.width, height: stage.height };
|
180
|
-
}
|
181
|
-
}
|
182
|
-
|
183
200
|
public addMainViewListener(): void {
|
184
201
|
if (this.mainViewIsAddListener) return;
|
185
202
|
if (this.view.divElement) {
|
@@ -223,10 +240,63 @@ export class MainViewProxy {
|
|
223
240
|
this.view.callbacks.off("onSizeUpdated", this.onCameraOrSizeUpdated);
|
224
241
|
}
|
225
242
|
|
243
|
+
private _syncMainViewTimer = 0;
|
226
244
|
private onCameraOrSizeUpdated = () => {
|
227
245
|
callbacks.emit("cameraStateChange", this.cameraState);
|
246
|
+
// sdk >= 2.16.43 的 syncMainView() 可以写入当前 main view 的 camera, 以修复复制粘贴元素的位置
|
247
|
+
// 注意到这个操作会发送信令,应当避免频繁调用
|
248
|
+
if (this.manager.room && (this.manager.room as any).syncMainView) {
|
249
|
+
clearTimeout(this._syncMainViewTimer);
|
250
|
+
this._syncMainViewTimer = setTimeout(this.syncMainView, 100, this.manager.room);
|
251
|
+
}
|
252
|
+
this.ensureMainViewSize();
|
228
253
|
};
|
229
254
|
|
255
|
+
private ensureMainViewSize() {
|
256
|
+
if (
|
257
|
+
(!this.mainViewSize ||
|
258
|
+
this.mainViewSize.width === 0 ||
|
259
|
+
this.mainViewSize.height === 0) &&
|
260
|
+
this.mainView.size.width > 0 &&
|
261
|
+
this.mainView.size.height > 0
|
262
|
+
) {
|
263
|
+
this.setMainViewSize(this.mainView.size);
|
264
|
+
}
|
265
|
+
}
|
266
|
+
|
267
|
+
private syncMainView = (room: Room) => {
|
268
|
+
if (room.isWritable) {
|
269
|
+
room.syncMainView(this.mainView);
|
270
|
+
}
|
271
|
+
};
|
272
|
+
|
273
|
+
public moveCameraToContian(size: Size): void {
|
274
|
+
if (!isEmpty(size)) {
|
275
|
+
this.view.moveCameraToContain({
|
276
|
+
width: size.width,
|
277
|
+
height: size.height,
|
278
|
+
originX: -size.width / 2,
|
279
|
+
originY: -size.height / 2,
|
280
|
+
animationMode: AnimationMode.Immediately,
|
281
|
+
});
|
282
|
+
this.scale = this.view.camera.scale;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
public moveCamera(camera: Camera): void {
|
287
|
+
if (!isEmpty(camera)) {
|
288
|
+
if (isEqual(camera, this.view.camera)) return;
|
289
|
+
const { centerX, centerY, scale } = camera;
|
290
|
+
const needScale = scale * (this.scale || 1);
|
291
|
+
this.view.moveCamera({
|
292
|
+
centerX: centerX,
|
293
|
+
centerY: centerY,
|
294
|
+
scale: needScale,
|
295
|
+
animationMode: AnimationMode.Immediately,
|
296
|
+
});
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
230
300
|
public stop() {
|
231
301
|
this.removeCameraListener();
|
232
302
|
this.manager.refresher.remove(Fields.MainViewCamera);
|
@@ -234,6 +304,10 @@ export class MainViewProxy {
|
|
234
304
|
this.started = false;
|
235
305
|
}
|
236
306
|
|
307
|
+
public setViewMode = (mode: ViewMode) => {
|
308
|
+
this.viewMode = mode;
|
309
|
+
};
|
310
|
+
|
237
311
|
public destroy() {
|
238
312
|
this.removeMainViewListener();
|
239
313
|
this.stop();
|
package/src/callback.ts
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
import Emittery from "emittery";
|
2
2
|
import type { TeleBoxColorScheme, TELE_BOX_STATE } from "@netless/telebox-insider";
|
3
|
-
import type { CameraState, SceneState, ViewVisionMode } from "white-web-sdk";
|
3
|
+
import type { CameraState, SceneState, View, ViewVisionMode } from "white-web-sdk";
|
4
4
|
import type { LoadAppEvent } from "./Register";
|
5
5
|
import type { PageState } from "./Page";
|
6
|
+
import type {
|
7
|
+
BoxClosePayload,
|
8
|
+
BoxFocusPayload,
|
9
|
+
BoxMovePayload,
|
10
|
+
BoxResizePayload,
|
11
|
+
BoxStateChangePayload,
|
12
|
+
} from "./BoxEmitter";
|
13
|
+
import type { AppPayload } from "./typings";
|
6
14
|
|
7
15
|
export type PublicEvent = {
|
8
16
|
mainViewModeChange: ViewVisionMode;
|
@@ -20,6 +28,18 @@ export type PublicEvent = {
|
|
20
28
|
ready: undefined; // 所有 APP 创建完毕时触发
|
21
29
|
sceneStateChange: SceneState;
|
22
30
|
pageStateChange: PageState;
|
31
|
+
fullscreenChange: boolean;
|
32
|
+
appsChange: string[]; // APP 列表变化时触发
|
33
|
+
onBoxMove: BoxMovePayload;
|
34
|
+
onBoxResize: BoxResizePayload;
|
35
|
+
onBoxFocus: BoxFocusPayload;
|
36
|
+
onBoxClose: BoxClosePayload;
|
37
|
+
onBoxStateChange: BoxStateChangePayload;
|
38
|
+
onMainViewMounted: View;
|
39
|
+
onMainViewRebind: View;
|
40
|
+
onAppViewMounted: AppPayload;
|
41
|
+
onAppSetup: string;
|
42
|
+
onAppScenePathChange: AppPayload;
|
23
43
|
};
|
24
44
|
|
25
45
|
export type CallbacksType = Emittery<PublicEvent>;
|
package/src/constants.ts
CHANGED