@netless/window-manager 1.0.0-canary.8 → 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 -39
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/{index.es.js → index.mjs} +8393 -5913
- 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 +104 -71
- package/src/App/AppPageStateImpl.ts +6 -25
- package/src/App/AppProxy.ts +42 -147
- 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 +84 -75
- package/src/AttributesDelegate.ts +42 -22
- package/src/BoxEmitter.ts +12 -6
- package/src/BoxManager.ts +122 -106
- 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/PageController.ts +1 -0
- 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 +114 -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 +224 -74
- 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 -81
- 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 -100
- 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 -20
- 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 -17
- package/dist/View/MainView.d.ts +0 -48
- package/dist/View/ViewManager.d.ts +0 -13
- package/dist/View/ViewSync.d.ts +0 -7
- 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 -73
- package/src/View/ViewSync.ts +0 -10
- package/vite.config.js +0 -51
- /package/docs/{qickstart.md → cn/quickstart.md} +0 -0
package/src/index.ts
CHANGED
@@ -2,11 +2,12 @@ import pRetry from "p-retry";
|
|
2
2
|
import { AppManager } from "./AppManager";
|
3
3
|
import { appRegister } from "./Register";
|
4
4
|
import { callbacks } from "./callback";
|
5
|
-
import { checkVersion, setupWrapper } from "./Helper";
|
5
|
+
import { checkVersion, createInvisiblePlugin, setupWrapper } from "./Helper";
|
6
|
+
import { ContainerResizeObserver } from "./ContainerResizeObserver";
|
6
7
|
import { createBoxManager } from "./BoxManager";
|
7
8
|
import { CursorManager } from "./Cursor";
|
8
9
|
import { DEFAULT_CONTAINER_RATIO, Events, INIT_DIR, ROOT_DIR } from "./constants";
|
9
|
-
import {
|
10
|
+
import { internalEmitter } from "./InternalEmitter";
|
10
11
|
import { Fields } from "./AttributesDelegate";
|
11
12
|
import { initDb } from "./Register/storage";
|
12
13
|
import { InvisiblePlugin, isPlayer, isRoom, RoomPhase, ViewMode } from "white-web-sdk";
|
@@ -29,7 +30,7 @@ import {
|
|
29
30
|
} from "./Utils/Common";
|
30
31
|
import type { TELE_BOX_STATE, BoxManager } from "./BoxManager";
|
31
32
|
import * as Errors from "./Utils/error";
|
32
|
-
import type { Apps, Position
|
33
|
+
import type { Apps, Position } from "./AttributesDelegate";
|
33
34
|
import type {
|
34
35
|
Displayer,
|
35
36
|
SceneDefinition,
|
@@ -54,6 +55,9 @@ import type { PublicEvent } from "./callback";
|
|
54
55
|
import type Emittery from "emittery";
|
55
56
|
import type { PageController, AddPageParams, PageState } from "./Page";
|
56
57
|
import { boxEmitter } from "./BoxEmitter";
|
58
|
+
import { IframeBridge } from "./View/IframeBridge";
|
59
|
+
import { setOptions } from "@netless/app-media-player";
|
60
|
+
export * from "./View/IframeBridge";
|
57
61
|
|
58
62
|
export type WindowMangerAttributes = {
|
59
63
|
modelValue?: string;
|
@@ -104,8 +108,6 @@ export type AppSyncAttributes = {
|
|
104
108
|
isDynamicPPT?: boolean;
|
105
109
|
fullPath?: string;
|
106
110
|
createdAt?: number;
|
107
|
-
camera?: ICamera;
|
108
|
-
size?: ISize;
|
109
111
|
};
|
110
112
|
|
111
113
|
export type AppInitState = {
|
@@ -124,33 +126,53 @@ export type AppInitState = {
|
|
124
126
|
|
125
127
|
export type CursorMovePayload = { uid: string; state?: "leave"; position: Position };
|
126
128
|
|
129
|
+
export type CursorOptions = {
|
130
|
+
/**
|
131
|
+
* If `"custom"`, it will render the pencil / eraser cursor as a circle and shapes cursor as a cross.
|
132
|
+
*
|
133
|
+
* @default "default"
|
134
|
+
*/
|
135
|
+
style?: "default" | "custom";
|
136
|
+
};
|
137
|
+
|
127
138
|
export type MountParams = {
|
128
139
|
room: Room | Player;
|
129
140
|
container?: HTMLElement;
|
130
141
|
/** 白板高宽比例, 默认为 9 / 16 */
|
131
142
|
containerSizeRatio?: number;
|
132
|
-
/** 显示 PS 透明背景,默认 true */
|
143
|
+
/** @deprecated 显示 PS 透明背景,默认 true */
|
133
144
|
chessboard?: boolean;
|
134
145
|
collectorContainer?: HTMLElement;
|
135
146
|
collectorStyles?: Partial<CSSStyleDeclaration>;
|
136
147
|
overwriteStyles?: string;
|
137
148
|
cursor?: boolean;
|
149
|
+
cursorOptions?: CursorOptions;
|
138
150
|
debug?: boolean;
|
139
151
|
disableCameraTransform?: boolean;
|
140
152
|
prefersColorScheme?: TeleBoxColorScheme;
|
141
153
|
applianceIcons?: ApplianceIcons;
|
154
|
+
fullscreen?: boolean;
|
155
|
+
polling?: boolean;
|
156
|
+
supportAppliancePlugin?: boolean;
|
142
157
|
};
|
143
158
|
|
144
|
-
export const reconnectRefresher = new ReconnectRefresher({ emitter });
|
159
|
+
export const reconnectRefresher = new ReconnectRefresher({ emitter: internalEmitter });
|
145
160
|
|
146
|
-
export class WindowManager
|
161
|
+
export class WindowManager
|
162
|
+
extends InvisiblePlugin<WindowMangerAttributes, any>
|
163
|
+
implements PageController
|
164
|
+
{
|
147
165
|
public static kind = "WindowManager";
|
148
166
|
public static displayer: Displayer;
|
167
|
+
public static wrapper?: HTMLElement;
|
168
|
+
public static sizer?: HTMLElement;
|
149
169
|
public static playground?: HTMLElement;
|
150
170
|
public static container?: HTMLElement;
|
151
171
|
public static debug = false;
|
152
172
|
public static containerSizeRatio = DEFAULT_CONTAINER_RATIO;
|
173
|
+
public static supportAppliancePlugin?: boolean;
|
153
174
|
private static isCreated = false;
|
175
|
+
private static _resolve = (_manager: WindowManager) => void 0;
|
154
176
|
|
155
177
|
public version = __APP_VERSION__;
|
156
178
|
public dependencies = __APP_DEPENDENCIES__;
|
@@ -164,10 +186,14 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
164
186
|
public viewMode = ViewMode.Broadcaster;
|
165
187
|
public isReplay = isPlayer(this.displayer);
|
166
188
|
private _pageState?: PageStateImpl;
|
189
|
+
private _fullscreen?: boolean;
|
190
|
+
private _cursorUIDs: string[] = [];
|
191
|
+
private _cursorUIDsStyleDOM?: HTMLStyleElement;
|
167
192
|
|
168
193
|
private boxManager?: BoxManager;
|
169
194
|
private static params?: MountParams;
|
170
195
|
|
196
|
+
private containerResizeObserver?: ContainerResizeObserver;
|
171
197
|
public containerSizeRatio = WindowManager.containerSizeRatio;
|
172
198
|
|
173
199
|
constructor(context: InvisiblePluginContext) {
|
@@ -176,9 +202,14 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
176
202
|
(window as any).NETLESS_DEPS = __APP_DEPENDENCIES__;
|
177
203
|
}
|
178
204
|
|
205
|
+
public static onCreate(manager: WindowManager) {
|
206
|
+
WindowManager._resolve(manager);
|
207
|
+
}
|
208
|
+
|
179
209
|
public static async mount(params: MountParams): Promise<WindowManager> {
|
180
210
|
const room = params.room;
|
181
211
|
WindowManager.container = params.container;
|
212
|
+
WindowManager.supportAppliancePlugin = params.supportAppliancePlugin;
|
182
213
|
const containerSizeRatio = params.containerSizeRatio;
|
183
214
|
const debug = params.debug;
|
184
215
|
|
@@ -202,6 +233,9 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
202
233
|
}
|
203
234
|
|
204
235
|
this.debug = Boolean(debug);
|
236
|
+
if (this.debug) {
|
237
|
+
setOptions({ verbose: true });
|
238
|
+
}
|
205
239
|
log("Already insert room", manager);
|
206
240
|
|
207
241
|
if (isRoom(this.displayer)) {
|
@@ -211,13 +245,14 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
211
245
|
} else {
|
212
246
|
await pRetry(
|
213
247
|
async count => {
|
214
|
-
manager =
|
248
|
+
manager = room.getInvisiblePlugin(WindowManager.kind) as WindowManager;
|
215
249
|
if (!manager) {
|
216
250
|
log(`manager is empty. retrying ${count}`);
|
217
251
|
throw new Error();
|
218
252
|
}
|
219
253
|
},
|
220
|
-
|
254
|
+
// 1s, 2s, 4s, 5s, 5s, 5s, 5s, 5s, 5s
|
255
|
+
{ retries: 10, maxTimeout: 5000 } as any
|
221
256
|
);
|
222
257
|
}
|
223
258
|
|
@@ -230,25 +265,26 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
230
265
|
}
|
231
266
|
await manager.ensureAttributes();
|
232
267
|
|
268
|
+
manager._fullscreen = params.fullscreen;
|
233
269
|
manager.appManager = new AppManager(manager);
|
270
|
+
manager.appManager.polling = params.polling || false;
|
234
271
|
manager._pageState = new PageStateImpl(manager.appManager);
|
235
|
-
manager.cursorManager = new CursorManager(
|
272
|
+
manager.cursorManager = new CursorManager(
|
273
|
+
manager.appManager,
|
274
|
+
Boolean(cursor),
|
275
|
+
params.cursorOptions,
|
276
|
+
params.applianceIcons
|
277
|
+
);
|
236
278
|
if (containerSizeRatio) {
|
237
279
|
manager.containerSizeRatio = containerSizeRatio;
|
238
280
|
}
|
239
|
-
|
240
|
-
collectorContainer: params.collectorContainer,
|
241
|
-
collectorStyles: params.collectorStyles,
|
242
|
-
prefersColorScheme: params.prefersColorScheme,
|
243
|
-
stageRatio: params.containerSizeRatio,
|
244
|
-
});
|
245
|
-
manager.appManager?.setBoxManager(manager.boxManager);
|
281
|
+
|
246
282
|
if (params.container) {
|
247
283
|
manager.bindContainer(params.container);
|
248
284
|
}
|
249
285
|
|
250
286
|
replaceRoomFunction(room, manager);
|
251
|
-
|
287
|
+
internalEmitter.emit("onCreated");
|
252
288
|
WindowManager.isCreated = true;
|
253
289
|
try {
|
254
290
|
await initDb();
|
@@ -259,48 +295,44 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
259
295
|
return manager;
|
260
296
|
}
|
261
297
|
|
262
|
-
private static
|
263
|
-
|
264
|
-
if (!manager) {
|
265
|
-
if (isRoom(room)) {
|
266
|
-
if (room.isWritable === false) {
|
267
|
-
try {
|
268
|
-
await room.setWritable(true);
|
269
|
-
} catch (error) {
|
270
|
-
throw new Error("[WindowManger]: room must be switched to be writable");
|
271
|
-
}
|
272
|
-
manager = (await room.createInvisiblePlugin(
|
273
|
-
WindowManager,
|
274
|
-
{}
|
275
|
-
)) as WindowManager;
|
276
|
-
manager.ensureAttributes();
|
277
|
-
await wait(500);
|
278
|
-
await room.setWritable(false);
|
279
|
-
} else {
|
280
|
-
manager = (await room.createInvisiblePlugin(
|
281
|
-
WindowManager,
|
282
|
-
{}
|
283
|
-
)) as WindowManager;
|
284
|
-
}
|
285
|
-
}
|
286
|
-
}
|
287
|
-
return manager;
|
298
|
+
private static initManager(room: Room): Promise<WindowManager | undefined> {
|
299
|
+
return createInvisiblePlugin(room);
|
288
300
|
}
|
289
301
|
|
290
302
|
private static initContainer(
|
303
|
+
manager: WindowManager,
|
291
304
|
container: HTMLElement,
|
292
|
-
|
305
|
+
params: {
|
306
|
+
chessboard?: boolean;
|
307
|
+
overwriteStyles?: string;
|
308
|
+
fullscreen?: boolean;
|
309
|
+
}
|
293
310
|
) {
|
311
|
+
const { chessboard, overwriteStyles, fullscreen } = params;
|
294
312
|
if (!WindowManager.container) {
|
295
313
|
WindowManager.container = container;
|
296
314
|
}
|
297
|
-
const { playground, mainViewElement } = setupWrapper(container);
|
315
|
+
const { playground, wrapper, sizer, mainViewElement } = setupWrapper(container);
|
298
316
|
WindowManager.playground = playground;
|
317
|
+
if (chessboard) {
|
318
|
+
sizer.classList.add("netless-window-manager-chess-sizer");
|
319
|
+
}
|
320
|
+
if (fullscreen) {
|
321
|
+
sizer.classList.add("netless-window-manager-fullscreen");
|
322
|
+
}
|
299
323
|
if (overwriteStyles) {
|
300
324
|
const style = document.createElement("style");
|
301
325
|
style.textContent = overwriteStyles;
|
302
326
|
playground.appendChild(style);
|
303
327
|
}
|
328
|
+
manager.containerResizeObserver = ContainerResizeObserver.create(
|
329
|
+
playground,
|
330
|
+
sizer,
|
331
|
+
wrapper,
|
332
|
+
internalEmitter
|
333
|
+
);
|
334
|
+
WindowManager.wrapper = wrapper;
|
335
|
+
WindowManager.sizer = sizer;
|
304
336
|
return mainViewElement;
|
305
337
|
}
|
306
338
|
|
@@ -319,20 +351,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
319
351
|
} else {
|
320
352
|
if (WindowManager.params) {
|
321
353
|
const params = WindowManager.params;
|
322
|
-
const mainViewElement = WindowManager.initContainer(
|
323
|
-
|
324
|
-
|
325
|
-
);
|
326
|
-
if (this.boxManager && WindowManager.playground) {
|
327
|
-
this.boxManager.setRoot(WindowManager.playground);
|
354
|
+
const mainViewElement = WindowManager.initContainer(this, container, params);
|
355
|
+
if (this.boxManager) {
|
356
|
+
this.boxManager.destroy();
|
328
357
|
}
|
358
|
+
const boxManager = createBoxManager(this, callbacks, internalEmitter, boxEmitter, {
|
359
|
+
collectorContainer: params.collectorContainer,
|
360
|
+
collectorStyles: params.collectorStyles,
|
361
|
+
prefersColorScheme: params.prefersColorScheme,
|
362
|
+
});
|
363
|
+
this.boxManager = boxManager;
|
364
|
+
this.appManager?.setBoxManager(boxManager);
|
329
365
|
this.bindMainView(mainViewElement, params.disableCameraTransform);
|
330
|
-
if (WindowManager.
|
331
|
-
this.cursorManager?.setupWrapper(WindowManager.
|
366
|
+
if (WindowManager.wrapper) {
|
367
|
+
this.cursorManager?.setupWrapper(WindowManager.wrapper);
|
332
368
|
}
|
333
369
|
}
|
334
370
|
}
|
335
|
-
|
371
|
+
internalEmitter.emit("updateManagerRect");
|
336
372
|
this.appManager?.refresh();
|
337
373
|
this.appManager?.resetMaximized();
|
338
374
|
this.appManager?.resetMinimized();
|
@@ -342,7 +378,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
342
378
|
|
343
379
|
public bindCollectorContainer(container: HTMLElement) {
|
344
380
|
if (WindowManager.isCreated && this.boxManager) {
|
345
|
-
this.boxManager.
|
381
|
+
this.boxManager.setCollectorContainer(container);
|
346
382
|
} else {
|
347
383
|
if (WindowManager.params) {
|
348
384
|
WindowManager.params.collectorContainer = container;
|
@@ -353,9 +389,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
353
389
|
/**
|
354
390
|
* 注册插件
|
355
391
|
*/
|
356
|
-
public static register<
|
357
|
-
params: RegisterParams<AppOptions, SetupResult, Attributes>
|
358
|
-
): Promise<void> {
|
392
|
+
public static register(params: RegisterParams<any, any, any>): Promise<void> {
|
359
393
|
return appRegister.register(params);
|
360
394
|
}
|
361
395
|
|
@@ -374,7 +408,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
374
408
|
// 移除根目录时需要做一些异步的释放操作 addApp 需要等待释放完成才可以继续添加
|
375
409
|
if (this.appManager.rootDirRemoving) {
|
376
410
|
return new Promise((resolve, reject) => {
|
377
|
-
|
411
|
+
internalEmitter.once("rootDirRemoved").then(async () => {
|
378
412
|
try {
|
379
413
|
const appId = await this._addApp(params);
|
380
414
|
resolve(appId);
|
@@ -396,6 +430,9 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
396
430
|
if (!params.kind || typeof params.kind !== "string") {
|
397
431
|
throw new Errors.ParamsInvalidError();
|
398
432
|
}
|
433
|
+
if (params.src && typeof params.src === "string") {
|
434
|
+
appRegister.register({ kind: params.kind, src: params.src });
|
435
|
+
}
|
399
436
|
const appImpl = await appRegister.appClasses.get(params.kind)?.();
|
400
437
|
if (appImpl && appImpl.config?.singleton) {
|
401
438
|
if (this.appManager.appProxies.has(params.kind)) {
|
@@ -428,11 +465,12 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
428
465
|
for (const appId of apps) {
|
429
466
|
const appScenePath = appManager.store.getAppScenePath(appId);
|
430
467
|
if (appScenePath && appScenePath === scenePath) {
|
431
|
-
console.warn(`[WindowManager]: ScenePath ${scenePath}
|
468
|
+
console.warn(`[WindowManager]: ScenePath "${scenePath}" already opened`);
|
432
469
|
if (this.boxManager) {
|
433
470
|
const topBox = this.boxManager.getTopBox();
|
434
471
|
if (topBox) {
|
435
472
|
this.boxManager.setZIndex(appId, topBox.zIndex + 1, false);
|
473
|
+
this.boxManager.focusBox({ appId }, false);
|
436
474
|
}
|
437
475
|
}
|
438
476
|
return;
|
@@ -504,6 +542,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
504
542
|
}
|
505
543
|
}
|
506
544
|
|
545
|
+
public async jumpPage(index: number): Promise<boolean> {
|
546
|
+
if (this.appManager) {
|
547
|
+
if (index < 0 || index >= this.pageState.length) {
|
548
|
+
console.warn(`[WindowManager]: index ${index} out of range`);
|
549
|
+
return false;
|
550
|
+
}
|
551
|
+
await this.appManager.setMainViewSceneIndex(index);
|
552
|
+
return true;
|
553
|
+
} else {
|
554
|
+
return false;
|
555
|
+
}
|
556
|
+
}
|
557
|
+
|
507
558
|
public async addPage(params?: AddPageParams): Promise<void> {
|
508
559
|
if (this.appManager) {
|
509
560
|
const after = params?.after;
|
@@ -533,7 +584,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
533
584
|
console.warn(`[WindowManager]: index ${index} out of range`);
|
534
585
|
return false;
|
535
586
|
}
|
536
|
-
return this.appManager.removeSceneByIndex(needRemoveIndex)
|
587
|
+
return this.appManager.removeSceneByIndex(needRemoveIndex);
|
537
588
|
} else {
|
538
589
|
return false;
|
539
590
|
}
|
@@ -559,7 +610,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
559
610
|
public setReadonly(readonly: boolean): void {
|
560
611
|
this.readonly = readonly;
|
561
612
|
this.boxManager?.setReadonly(readonly);
|
562
|
-
|
613
|
+
internalEmitter.emit("setReadonly", readonly);
|
563
614
|
}
|
564
615
|
|
565
616
|
/**
|
@@ -576,12 +627,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
576
627
|
addEmitterOnceListener(`destroy-${kind}`, listener);
|
577
628
|
}
|
578
629
|
|
630
|
+
/**
|
631
|
+
* app 本地自定义事件回调
|
632
|
+
*
|
633
|
+
* 返回一个用于撤销此监听的函数
|
634
|
+
*/
|
635
|
+
public onAppEvent(
|
636
|
+
kind: string,
|
637
|
+
listener: (args: { kind: string; appId: string; type: string; value: any }) => void
|
638
|
+
): () => void {
|
639
|
+
return internalEmitter.on(`custom-${kind}` as any, listener);
|
640
|
+
}
|
641
|
+
|
579
642
|
/**
|
580
643
|
* 设置 ViewMode
|
581
644
|
*/
|
582
645
|
public setViewMode(mode: ViewMode): void {
|
583
|
-
if (mode === ViewMode.Broadcaster) {
|
584
|
-
if (this.canOperate) {
|
646
|
+
if (mode === ViewMode.Broadcaster || mode === ViewMode.Follower) {
|
647
|
+
if (this.canOperate && mode === ViewMode.Broadcaster) {
|
585
648
|
this.appManager?.mainViewProxy.setCameraAndSize();
|
586
649
|
}
|
587
650
|
this.appManager?.mainViewProxy.start();
|
@@ -590,6 +653,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
590
653
|
this.appManager?.mainViewProxy.stop();
|
591
654
|
}
|
592
655
|
this.viewMode = mode;
|
656
|
+
this.appManager?.mainViewProxy.setViewMode(mode);
|
593
657
|
}
|
594
658
|
|
595
659
|
public setBoxState(boxState: TeleBoxState): void {
|
@@ -621,6 +685,35 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
621
685
|
this.boxManager?.setMinimized(minimized, false);
|
622
686
|
}
|
623
687
|
|
688
|
+
public setFullscreen(fullscreen: boolean): void {
|
689
|
+
if (this._fullscreen !== fullscreen) {
|
690
|
+
this._fullscreen = fullscreen;
|
691
|
+
WindowManager.sizer?.classList.toggle("netless-window-manager-fullscreen", fullscreen);
|
692
|
+
callbacks.emit("fullscreenChange", fullscreen);
|
693
|
+
}
|
694
|
+
}
|
695
|
+
|
696
|
+
public get cursorUIDs(): string[] {
|
697
|
+
return this._cursorUIDs;
|
698
|
+
}
|
699
|
+
|
700
|
+
public setCursorUIDs(cursorUIDs?: string[] | null): void {
|
701
|
+
this._cursorUIDs = cursorUIDs || [];
|
702
|
+
if (this._cursorUIDs.length === 0) {
|
703
|
+
this._cursorUIDsStyleDOM?.remove();
|
704
|
+
} else {
|
705
|
+
if (!this._cursorUIDsStyleDOM) {
|
706
|
+
this._cursorUIDsStyleDOM = document.createElement("style");
|
707
|
+
}
|
708
|
+
WindowManager.playground?.appendChild(this._cursorUIDsStyleDOM);
|
709
|
+
let style = "[data-cursor-uid] { display: none }";
|
710
|
+
for (const uid of this._cursorUIDs) {
|
711
|
+
style += `\n[data-cursor-uid="${uid}"] { display: flex }`;
|
712
|
+
}
|
713
|
+
this._cursorUIDsStyleDOM.textContent = style;
|
714
|
+
}
|
715
|
+
}
|
716
|
+
|
624
717
|
public get mainView(): View {
|
625
718
|
if (this.appManager) {
|
626
719
|
return this.appManager.mainViewProxy.view;
|
@@ -677,6 +770,27 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
677
770
|
return this.appManager?.focusApp?.view || this.mainView;
|
678
771
|
}
|
679
772
|
|
773
|
+
public get polling(): boolean {
|
774
|
+
return this.appManager?.polling || false;
|
775
|
+
}
|
776
|
+
|
777
|
+
public set polling(b: boolean) {
|
778
|
+
if (this.appManager) {
|
779
|
+
this.appManager.polling = b;
|
780
|
+
}
|
781
|
+
}
|
782
|
+
|
783
|
+
public get cursorStyle(): "default" | "custom" {
|
784
|
+
return this.cursorManager?.style || "default";
|
785
|
+
}
|
786
|
+
|
787
|
+
public set cursorStyle(value: "default" | "custom") {
|
788
|
+
if (!this.cursorManager) {
|
789
|
+
throw new Error("[WindowManager]: cursor is not enabled, please set { cursor: true }.");
|
790
|
+
}
|
791
|
+
this.cursorManager.style = value;
|
792
|
+
}
|
793
|
+
|
680
794
|
public get mainViewSceneIndex(): number {
|
681
795
|
return this._pageState?.index || 0;
|
682
796
|
}
|
@@ -722,6 +836,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
722
836
|
}
|
723
837
|
}
|
724
838
|
|
839
|
+
public get fullscreen(): boolean {
|
840
|
+
return Boolean(this._fullscreen);
|
841
|
+
}
|
842
|
+
|
725
843
|
/**
|
726
844
|
* 查询所有的 App
|
727
845
|
*/
|
@@ -743,6 +861,18 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
743
861
|
return this.appManager?.closeApp(appId);
|
744
862
|
}
|
745
863
|
|
864
|
+
/**
|
865
|
+
* 切换 focus 到指定的 app, 并且把这个 app 放到最前面
|
866
|
+
*/
|
867
|
+
public focusApp(appId: string) {
|
868
|
+
const box = this.boxManager?.getBox(appId);
|
869
|
+
if (box) {
|
870
|
+
this.boxManager?.focusBox({ appId }, false);
|
871
|
+
// 1.0 版本这里会有正式的 api
|
872
|
+
(this.boxManager?.teleBoxManager as any).makeBoxTop(box, false);
|
873
|
+
}
|
874
|
+
}
|
875
|
+
|
746
876
|
public moveCamera(
|
747
877
|
camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }
|
748
878
|
): void {
|
@@ -786,14 +916,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
786
916
|
}
|
787
917
|
|
788
918
|
private _destroy() {
|
919
|
+
this.containerResizeObserver?.disconnect();
|
789
920
|
this.appManager?.destroy();
|
790
921
|
this.cursorManager?.destroy();
|
791
922
|
WindowManager.container = undefined;
|
923
|
+
WindowManager.wrapper = undefined;
|
924
|
+
WindowManager.sizer = undefined;
|
792
925
|
WindowManager.isCreated = false;
|
793
926
|
if (WindowManager.playground) {
|
794
927
|
WindowManager.playground.parentNode?.removeChild(WindowManager.playground);
|
795
928
|
}
|
796
929
|
WindowManager.params = undefined;
|
930
|
+
this._iframeBridge?.destroy();
|
931
|
+
this._iframeBridge = undefined;
|
797
932
|
log("Destroyed");
|
798
933
|
}
|
799
934
|
|
@@ -836,6 +971,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
836
971
|
}
|
837
972
|
|
838
973
|
public cleanCurrentScene(): void {
|
974
|
+
log("clean current scene");
|
839
975
|
this.focusedView?.cleanCurrentScene();
|
840
976
|
}
|
841
977
|
|
@@ -884,26 +1020,28 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
884
1020
|
}
|
885
1021
|
|
886
1022
|
public refresh() {
|
887
|
-
|
888
|
-
|
1023
|
+
this._refresh();
|
1024
|
+
this.appManager?.dispatchInternalEvent(Events.Refresh);
|
889
1025
|
}
|
890
|
-
|
891
|
-
/** @
|
1026
|
+
|
1027
|
+
/** @internal */
|
892
1028
|
public _refresh() {
|
893
1029
|
this.appManager?.mainViewProxy.rebind();
|
894
1030
|
if (WindowManager.container) {
|
895
1031
|
this.bindContainer(WindowManager.container);
|
896
1032
|
}
|
897
|
-
this.appManager?.refresher
|
1033
|
+
this.appManager?.refresher.refresh();
|
898
1034
|
}
|
899
1035
|
|
900
1036
|
public setContainerSizeRatio(ratio: number) {
|
901
|
-
if (!isNumber(ratio)) {
|
902
|
-
throw new Error(
|
1037
|
+
if (!isNumber(ratio) || !(ratio > 0)) {
|
1038
|
+
throw new Error(
|
1039
|
+
`[WindowManager]: updateContainerSizeRatio error, ratio must be a positive number. but got ${ratio}`
|
1040
|
+
);
|
903
1041
|
}
|
904
1042
|
WindowManager.containerSizeRatio = ratio;
|
905
1043
|
this.containerSizeRatio = ratio;
|
906
|
-
|
1044
|
+
internalEmitter.emit("containerSizeRatioUpdate", ratio);
|
907
1045
|
}
|
908
1046
|
|
909
1047
|
private isDynamicPPT(scenes: SceneDefinition[]) {
|
@@ -931,7 +1069,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
931
1069
|
if (!this.attributes[Fields.Registered]) {
|
932
1070
|
this.safeSetAttributes({ [Fields.Registered]: {} });
|
933
1071
|
}
|
1072
|
+
if (!this.attributes[Fields.IframeBridge]) {
|
1073
|
+
this.safeSetAttributes({ [Fields.IframeBridge]: {} });
|
1074
|
+
}
|
1075
|
+
}
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
private _iframeBridge?: IframeBridge;
|
1079
|
+
public getIframeBridge() {
|
1080
|
+
if (!this.appManager) {
|
1081
|
+
throw new Error("[WindowManager]: should call getIframeBridge() after await mount()");
|
934
1082
|
}
|
1083
|
+
this._iframeBridge || (this._iframeBridge = new IframeBridge(this, this.appManager));
|
1084
|
+
return this._iframeBridge;
|
935
1085
|
}
|
936
1086
|
}
|
937
1087
|
|
package/src/style.css
CHANGED
@@ -53,7 +53,6 @@
|
|
53
53
|
height: 100%;
|
54
54
|
}
|
55
55
|
|
56
|
-
|
57
56
|
.netless-window-manager-cursor-pencil-image {
|
58
57
|
width: 26px;
|
59
58
|
height: 26px;
|
@@ -122,9 +121,10 @@
|
|
122
121
|
left: 0;
|
123
122
|
top: 0;
|
124
123
|
will-change: transform;
|
125
|
-
transition: transform 0.
|
124
|
+
transition: transform 0.12s;
|
126
125
|
transform-origin: 0 0;
|
127
126
|
user-select: none;
|
127
|
+
pointer-events: none;
|
128
128
|
}
|
129
129
|
|
130
130
|
.netless-window-manager-cursor-pencil-offset {
|
@@ -158,6 +158,20 @@
|
|
158
158
|
margin-top: 3px;
|
159
159
|
}
|
160
160
|
|
161
|
+
.netless-window-manager-cursor-pencilEraser-image {
|
162
|
+
margin-left: -22px;
|
163
|
+
margin-top: 3px;
|
164
|
+
}
|
165
|
+
|
166
|
+
.netless-window-manager-laserPointer-pencilEraser-offset {
|
167
|
+
margin-left: -18px;
|
168
|
+
}
|
169
|
+
|
170
|
+
.netless-window-manager-pencilEraser-3-offset {
|
171
|
+
margin-top: -14px;
|
172
|
+
margin-left: -6px;
|
173
|
+
}
|
174
|
+
|
161
175
|
.netless-window-manager-cursor-name {
|
162
176
|
width: 100%;
|
163
177
|
height: 48px;
|
@@ -179,11 +193,14 @@
|
|
179
193
|
bottom: 15px;
|
180
194
|
}
|
181
195
|
|
182
|
-
.
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
196
|
+
.netless-iframe-brdige-hidden {
|
197
|
+
display: none;
|
198
|
+
}
|
199
|
+
|
200
|
+
.netless-window-manager-fullscreen .telebox-titlebar,
|
201
|
+
.netless-window-manager-fullscreen .telebox-max-titlebar-maximized,
|
202
|
+
.netless-window-manager-fullscreen .netless-app-slide-footer,
|
203
|
+
.netless-window-manager-fullscreen .telebox-footer-wrap,
|
204
|
+
.netless-window-manager-fullscreen .telebox-titlebar-wrap {
|
205
|
+
display: none;
|
206
|
+
}
|