@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/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
|
-
/**
|
133
|
-
|
143
|
+
/** @deprecated 显示 PS 透明背景,默认 true */
|
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,26 +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
|
-
highlightStage: params.highlightStage
|
245
|
-
});
|
246
|
-
manager.appManager?.setBoxManager(manager.boxManager);
|
281
|
+
|
247
282
|
if (params.container) {
|
248
283
|
manager.bindContainer(params.container);
|
249
284
|
}
|
250
285
|
|
251
286
|
replaceRoomFunction(room, manager);
|
252
|
-
|
287
|
+
internalEmitter.emit("onCreated");
|
253
288
|
WindowManager.isCreated = true;
|
254
289
|
try {
|
255
290
|
await initDb();
|
@@ -260,48 +295,44 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
260
295
|
return manager;
|
261
296
|
}
|
262
297
|
|
263
|
-
private static
|
264
|
-
|
265
|
-
if (!manager) {
|
266
|
-
if (isRoom(room)) {
|
267
|
-
if (room.isWritable === false) {
|
268
|
-
try {
|
269
|
-
await room.setWritable(true);
|
270
|
-
} catch (error) {
|
271
|
-
throw new Error("[WindowManger]: room must be switched to be writable");
|
272
|
-
}
|
273
|
-
manager = (await room.createInvisiblePlugin(
|
274
|
-
WindowManager,
|
275
|
-
{}
|
276
|
-
)) as WindowManager;
|
277
|
-
manager.ensureAttributes();
|
278
|
-
await wait(500);
|
279
|
-
await room.setWritable(false);
|
280
|
-
} else {
|
281
|
-
manager = (await room.createInvisiblePlugin(
|
282
|
-
WindowManager,
|
283
|
-
{}
|
284
|
-
)) as WindowManager;
|
285
|
-
}
|
286
|
-
}
|
287
|
-
}
|
288
|
-
return manager;
|
298
|
+
private static initManager(room: Room): Promise<WindowManager | undefined> {
|
299
|
+
return createInvisiblePlugin(room);
|
289
300
|
}
|
290
301
|
|
291
302
|
private static initContainer(
|
303
|
+
manager: WindowManager,
|
292
304
|
container: HTMLElement,
|
293
|
-
|
305
|
+
params: {
|
306
|
+
chessboard?: boolean;
|
307
|
+
overwriteStyles?: string;
|
308
|
+
fullscreen?: boolean;
|
309
|
+
}
|
294
310
|
) {
|
311
|
+
const { chessboard, overwriteStyles, fullscreen } = params;
|
295
312
|
if (!WindowManager.container) {
|
296
313
|
WindowManager.container = container;
|
297
314
|
}
|
298
|
-
const { playground, mainViewElement } = setupWrapper(container);
|
315
|
+
const { playground, wrapper, sizer, mainViewElement } = setupWrapper(container);
|
299
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
|
+
}
|
300
323
|
if (overwriteStyles) {
|
301
324
|
const style = document.createElement("style");
|
302
325
|
style.textContent = overwriteStyles;
|
303
326
|
playground.appendChild(style);
|
304
327
|
}
|
328
|
+
manager.containerResizeObserver = ContainerResizeObserver.create(
|
329
|
+
playground,
|
330
|
+
sizer,
|
331
|
+
wrapper,
|
332
|
+
internalEmitter
|
333
|
+
);
|
334
|
+
WindowManager.wrapper = wrapper;
|
335
|
+
WindowManager.sizer = sizer;
|
305
336
|
return mainViewElement;
|
306
337
|
}
|
307
338
|
|
@@ -320,20 +351,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
320
351
|
} else {
|
321
352
|
if (WindowManager.params) {
|
322
353
|
const params = WindowManager.params;
|
323
|
-
const mainViewElement = WindowManager.initContainer(
|
324
|
-
|
325
|
-
|
326
|
-
);
|
327
|
-
if (this.boxManager && WindowManager.playground) {
|
328
|
-
this.boxManager.setRoot(WindowManager.playground);
|
354
|
+
const mainViewElement = WindowManager.initContainer(this, container, params);
|
355
|
+
if (this.boxManager) {
|
356
|
+
this.boxManager.destroy();
|
329
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);
|
330
365
|
this.bindMainView(mainViewElement, params.disableCameraTransform);
|
331
|
-
if (WindowManager.
|
332
|
-
this.cursorManager?.setupWrapper(WindowManager.
|
366
|
+
if (WindowManager.wrapper) {
|
367
|
+
this.cursorManager?.setupWrapper(WindowManager.wrapper);
|
333
368
|
}
|
334
369
|
}
|
335
370
|
}
|
336
|
-
|
371
|
+
internalEmitter.emit("updateManagerRect");
|
337
372
|
this.appManager?.refresh();
|
338
373
|
this.appManager?.resetMaximized();
|
339
374
|
this.appManager?.resetMinimized();
|
@@ -343,7 +378,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
343
378
|
|
344
379
|
public bindCollectorContainer(container: HTMLElement) {
|
345
380
|
if (WindowManager.isCreated && this.boxManager) {
|
346
|
-
this.boxManager.
|
381
|
+
this.boxManager.setCollectorContainer(container);
|
347
382
|
} else {
|
348
383
|
if (WindowManager.params) {
|
349
384
|
WindowManager.params.collectorContainer = container;
|
@@ -354,9 +389,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
354
389
|
/**
|
355
390
|
* 注册插件
|
356
391
|
*/
|
357
|
-
public static register<
|
358
|
-
params: RegisterParams<AppOptions, SetupResult, Attributes>
|
359
|
-
): Promise<void> {
|
392
|
+
public static register(params: RegisterParams<any, any, any>): Promise<void> {
|
360
393
|
return appRegister.register(params);
|
361
394
|
}
|
362
395
|
|
@@ -375,7 +408,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
375
408
|
// 移除根目录时需要做一些异步的释放操作 addApp 需要等待释放完成才可以继续添加
|
376
409
|
if (this.appManager.rootDirRemoving) {
|
377
410
|
return new Promise((resolve, reject) => {
|
378
|
-
|
411
|
+
internalEmitter.once("rootDirRemoved").then(async () => {
|
379
412
|
try {
|
380
413
|
const appId = await this._addApp(params);
|
381
414
|
resolve(appId);
|
@@ -397,6 +430,9 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
397
430
|
if (!params.kind || typeof params.kind !== "string") {
|
398
431
|
throw new Errors.ParamsInvalidError();
|
399
432
|
}
|
433
|
+
if (params.src && typeof params.src === "string") {
|
434
|
+
appRegister.register({ kind: params.kind, src: params.src });
|
435
|
+
}
|
400
436
|
const appImpl = await appRegister.appClasses.get(params.kind)?.();
|
401
437
|
if (appImpl && appImpl.config?.singleton) {
|
402
438
|
if (this.appManager.appProxies.has(params.kind)) {
|
@@ -429,11 +465,12 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
429
465
|
for (const appId of apps) {
|
430
466
|
const appScenePath = appManager.store.getAppScenePath(appId);
|
431
467
|
if (appScenePath && appScenePath === scenePath) {
|
432
|
-
console.warn(`[WindowManager]: ScenePath ${scenePath}
|
468
|
+
console.warn(`[WindowManager]: ScenePath "${scenePath}" already opened`);
|
433
469
|
if (this.boxManager) {
|
434
470
|
const topBox = this.boxManager.getTopBox();
|
435
471
|
if (topBox) {
|
436
472
|
this.boxManager.setZIndex(appId, topBox.zIndex + 1, false);
|
473
|
+
this.boxManager.focusBox({ appId }, false);
|
437
474
|
}
|
438
475
|
}
|
439
476
|
return;
|
@@ -506,15 +543,16 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
506
543
|
}
|
507
544
|
|
508
545
|
public async jumpPage(index: number): Promise<boolean> {
|
509
|
-
if (
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
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 {
|
514
554
|
return false;
|
515
555
|
}
|
516
|
-
await this.appManager.setMainViewSceneIndex(index);
|
517
|
-
return true;
|
518
556
|
}
|
519
557
|
|
520
558
|
public async addPage(params?: AddPageParams): Promise<void> {
|
@@ -546,7 +584,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
546
584
|
console.warn(`[WindowManager]: index ${index} out of range`);
|
547
585
|
return false;
|
548
586
|
}
|
549
|
-
return this.appManager.removeSceneByIndex(needRemoveIndex)
|
587
|
+
return this.appManager.removeSceneByIndex(needRemoveIndex);
|
550
588
|
} else {
|
551
589
|
return false;
|
552
590
|
}
|
@@ -572,7 +610,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
572
610
|
public setReadonly(readonly: boolean): void {
|
573
611
|
this.readonly = readonly;
|
574
612
|
this.boxManager?.setReadonly(readonly);
|
575
|
-
|
613
|
+
internalEmitter.emit("setReadonly", readonly);
|
576
614
|
}
|
577
615
|
|
578
616
|
/**
|
@@ -589,12 +627,24 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
589
627
|
addEmitterOnceListener(`destroy-${kind}`, listener);
|
590
628
|
}
|
591
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
|
+
|
592
642
|
/**
|
593
643
|
* 设置 ViewMode
|
594
644
|
*/
|
595
645
|
public setViewMode(mode: ViewMode): void {
|
596
|
-
if (mode === ViewMode.Broadcaster) {
|
597
|
-
if (this.canOperate) {
|
646
|
+
if (mode === ViewMode.Broadcaster || mode === ViewMode.Follower) {
|
647
|
+
if (this.canOperate && mode === ViewMode.Broadcaster) {
|
598
648
|
this.appManager?.mainViewProxy.setCameraAndSize();
|
599
649
|
}
|
600
650
|
this.appManager?.mainViewProxy.start();
|
@@ -603,6 +653,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
603
653
|
this.appManager?.mainViewProxy.stop();
|
604
654
|
}
|
605
655
|
this.viewMode = mode;
|
656
|
+
this.appManager?.mainViewProxy.setViewMode(mode);
|
606
657
|
}
|
607
658
|
|
608
659
|
public setBoxState(boxState: TeleBoxState): void {
|
@@ -634,6 +685,35 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
634
685
|
this.boxManager?.setMinimized(minimized, false);
|
635
686
|
}
|
636
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
|
+
|
637
717
|
public get mainView(): View {
|
638
718
|
if (this.appManager) {
|
639
719
|
return this.appManager.mainViewProxy.view;
|
@@ -690,6 +770,27 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
690
770
|
return this.appManager?.focusApp?.view || this.mainView;
|
691
771
|
}
|
692
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
|
+
|
693
794
|
public get mainViewSceneIndex(): number {
|
694
795
|
return this._pageState?.index || 0;
|
695
796
|
}
|
@@ -735,6 +836,10 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
735
836
|
}
|
736
837
|
}
|
737
838
|
|
839
|
+
public get fullscreen(): boolean {
|
840
|
+
return Boolean(this._fullscreen);
|
841
|
+
}
|
842
|
+
|
738
843
|
/**
|
739
844
|
* 查询所有的 App
|
740
845
|
*/
|
@@ -756,6 +861,18 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
756
861
|
return this.appManager?.closeApp(appId);
|
757
862
|
}
|
758
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
|
+
|
759
876
|
public moveCamera(
|
760
877
|
camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }
|
761
878
|
): void {
|
@@ -799,14 +916,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
799
916
|
}
|
800
917
|
|
801
918
|
private _destroy() {
|
919
|
+
this.containerResizeObserver?.disconnect();
|
802
920
|
this.appManager?.destroy();
|
803
921
|
this.cursorManager?.destroy();
|
804
922
|
WindowManager.container = undefined;
|
923
|
+
WindowManager.wrapper = undefined;
|
924
|
+
WindowManager.sizer = undefined;
|
805
925
|
WindowManager.isCreated = false;
|
806
926
|
if (WindowManager.playground) {
|
807
927
|
WindowManager.playground.parentNode?.removeChild(WindowManager.playground);
|
808
928
|
}
|
809
929
|
WindowManager.params = undefined;
|
930
|
+
this._iframeBridge?.destroy();
|
931
|
+
this._iframeBridge = undefined;
|
810
932
|
log("Destroyed");
|
811
933
|
}
|
812
934
|
|
@@ -849,6 +971,7 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
849
971
|
}
|
850
972
|
|
851
973
|
public cleanCurrentScene(): void {
|
974
|
+
log("clean current scene");
|
852
975
|
this.focusedView?.cleanCurrentScene();
|
853
976
|
}
|
854
977
|
|
@@ -897,26 +1020,28 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
897
1020
|
}
|
898
1021
|
|
899
1022
|
public refresh() {
|
900
|
-
|
901
|
-
|
1023
|
+
this._refresh();
|
1024
|
+
this.appManager?.dispatchInternalEvent(Events.Refresh);
|
902
1025
|
}
|
903
|
-
|
904
|
-
/** @
|
1026
|
+
|
1027
|
+
/** @internal */
|
905
1028
|
public _refresh() {
|
906
1029
|
this.appManager?.mainViewProxy.rebind();
|
907
1030
|
if (WindowManager.container) {
|
908
1031
|
this.bindContainer(WindowManager.container);
|
909
1032
|
}
|
910
|
-
this.appManager?.refresher
|
1033
|
+
this.appManager?.refresher.refresh();
|
911
1034
|
}
|
912
1035
|
|
913
1036
|
public setContainerSizeRatio(ratio: number) {
|
914
|
-
if (!isNumber(ratio)) {
|
915
|
-
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
|
+
);
|
916
1041
|
}
|
917
1042
|
WindowManager.containerSizeRatio = ratio;
|
918
1043
|
this.containerSizeRatio = ratio;
|
919
|
-
|
1044
|
+
internalEmitter.emit("containerSizeRatioUpdate", ratio);
|
920
1045
|
}
|
921
1046
|
|
922
1047
|
private isDynamicPPT(scenes: SceneDefinition[]) {
|
@@ -944,7 +1069,19 @@ export class WindowManager extends InvisiblePlugin<WindowMangerAttributes> imple
|
|
944
1069
|
if (!this.attributes[Fields.Registered]) {
|
945
1070
|
this.safeSetAttributes({ [Fields.Registered]: {} });
|
946
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()");
|
947
1082
|
}
|
1083
|
+
this._iframeBridge || (this._iframeBridge = new IframeBridge(this, this.appManager));
|
1084
|
+
return this._iframeBridge;
|
948
1085
|
}
|
949
1086
|
}
|
950
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
|
+
}
|