@netless/fastboard-core 0.2.12 → 0.3.0-canary.1

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/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "@netless/fastboard-core",
3
- "version": "0.2.12",
3
+ "version": "0.3.0-canary.1",
4
4
  "description": "A tiny wrapper of white-web-sdk and @netless/window-manager.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
7
7
  "src",
8
- "dist",
9
- "minimal.mjs",
10
- "minimal.ts"
8
+ "dist"
11
9
  ],
10
+ "repository": "netless-io/fastboard",
12
11
  "dependencies": {
13
12
  "@netless/app-slide": "^0.0.56"
14
13
  },
@@ -16,16 +15,12 @@
16
15
  "@netless/window-manager": ">=0.4.0",
17
16
  "white-web-sdk": ">=2.16.0"
18
17
  },
19
- "devDependencies": {
20
- "@netless/window-manager": "^0.4.11-canary.1",
21
- "tsup": "^5.12.0",
22
- "white-web-sdk": "^2.16.10"
23
- },
24
18
  "scripts": {
25
- "build": "tsup",
26
19
  "cleanup": "rimraf dist",
27
- "check": "tsc --noEmit"
20
+ "check": "tsc --noEmit",
21
+ "build": "tsup"
28
22
  },
29
23
  "module": "dist/index.mjs",
30
- "types": "dist/index.d.ts"
24
+ "types": "dist/index.d.ts",
25
+ "readme": "## @netless/fastboard-core\n\nA tiny wrapper of white-web-sdk and @netless/window-manager.\n\nUsed by [@netless/fastboard-ui](https://github.com/netless-io/fastboard/tree/main/packages/fastboard-ui).\n\n### License\n\nMIT @ [netless](https://github.com/netless-io)\n"
31
26
  }
@@ -1,11 +1,12 @@
1
1
  import type { RegisterParams } from "@netless/window-manager";
2
2
  import { WindowManager } from "@netless/window-manager";
3
+ import AppSlide from "@netless/app-slide";
3
4
 
4
5
  export interface AppsConfig {
5
6
  [kind: string]: Omit<RegisterParams, "kind">;
6
7
  }
7
8
 
8
- export const DefaultApps: AppsConfig = {
9
+ const DefaultApps: AppsConfig = {
9
10
  Monaco: {
10
11
  src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.12/dist/main.iife.js",
11
12
  },
@@ -27,6 +28,12 @@ export const DefaultApps: AppsConfig = {
27
28
  },
28
29
  };
29
30
 
31
+ WindowManager.register({
32
+ kind: "Slide",
33
+ appOptions: { debug: false },
34
+ src: AppSlide,
35
+ });
36
+
30
37
  for (const kind in DefaultApps) {
31
38
  if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {
32
39
  const options = DefaultApps[kind];
@@ -1,26 +1,37 @@
1
- import type { PublicEvent, WindowManager } from "@netless/window-manager";
1
+ import type { AddPageParams, PublicEvent, MountParams } from "@netless/window-manager";
2
2
  import type {
3
3
  AnimationMode,
4
4
  ApplianceNames,
5
5
  Camera,
6
6
  Color,
7
7
  ConversionResponse,
8
+ HotKey,
8
9
  HotKeys,
10
+ JoinRoomParams,
9
11
  MemberState,
10
12
  Rectangle,
11
13
  Room,
14
+ RoomPhase as RoomPhaseEnum,
12
15
  RoomCallbacks,
13
16
  RoomState,
14
17
  SceneDefinition,
15
18
  ShapeType,
16
19
  ViewCallbacks,
17
- WhiteWebSdk,
20
+ WhiteWebSdkConfiguration,
18
21
  } from "white-web-sdk";
19
- import type { FastboardDisposer, FastboardInternalValue } from "../helpers/value";
20
22
 
21
- import { BuiltinApps } from "@netless/window-manager";
22
- import { convertedFileToScene, genUID, getImageSize, makeSlideParams } from "../helpers/utils";
23
- import { createValue } from "../helpers/value";
23
+ import { DefaultHotKeys, WhiteWebSdk, contentModeScale } from "white-web-sdk";
24
+ import { BuiltinApps, WindowManager } from "@netless/window-manager";
25
+ import {
26
+ getImageSize,
27
+ genUID,
28
+ convertedFileToScene,
29
+ makeSlideParams,
30
+ readable,
31
+ writable,
32
+ warn,
33
+ } from "../utils";
34
+ import { ensure_window_manager, transform_app_status } from "../internal";
24
35
 
25
36
  class FastboardAppBase {
26
37
  public constructor(
@@ -30,48 +41,72 @@ class FastboardAppBase {
30
41
  readonly hotKeys: Partial<HotKeys>
31
42
  ) {}
32
43
 
33
- protected readonly _disposers: FastboardDisposer[] = [];
34
44
  protected _destroyed = false;
35
45
  protected _assertNotDestroyed() {
36
46
  if (this._destroyed) {
37
- throw new Error("[FastboardApp] Can not call any method on destroyed FastboardApp.");
47
+ throw new Error("FastboardApp has been destroyed");
38
48
  }
39
49
  }
40
50
 
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- protected createValue: typeof createValue = (...args: [any, any]): any => {
43
- const value = createValue(...args);
44
- this._disposers.push((value as FastboardInternalValue<unknown>).dispose);
45
- return value;
46
- };
47
-
48
- protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {
51
+ protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {
49
52
  this._assertNotDestroyed();
50
53
  this.room.callbacks.on(name, listener);
51
54
  return () => this.room.callbacks.off(name, listener);
52
55
  }
53
56
 
54
- protected _addManagerListener<K extends keyof PublicEvent>(name: K, set: (value: PublicEvent[K]) => void) {
57
+ protected _addManagerListener<K extends keyof PublicEvent>(
58
+ name: K,
59
+ listener: (value: PublicEvent[K]) => void
60
+ ) {
55
61
  this._assertNotDestroyed();
56
- this.manager.emitter.on(name, set);
57
- return () => this.manager.emitter.off(name, set);
62
+ this.manager.emitter.on(name, listener);
63
+ return () => this.manager.emitter.off(name, listener);
58
64
  }
59
65
 
60
- protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {
66
+ protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {
61
67
  this._assertNotDestroyed();
62
68
  this.manager.mainView.callbacks.on(name, listener);
63
69
  return () => this.manager.mainView.callbacks.off(name, listener);
64
70
  }
65
71
 
66
72
  public destroy() {
67
- this._disposers.forEach(dispose => dispose());
68
- this._disposers.length = 0;
69
73
  this._destroyed = true;
70
74
  this.manager.destroy();
71
75
  return this.room.disconnect();
72
76
  }
73
77
  }
74
78
 
79
+ type RoomPhase = `${RoomPhaseEnum}`;
80
+
81
+ export type {
82
+ AddPageParams,
83
+ AnimationMode,
84
+ ApplianceNames,
85
+ Camera,
86
+ Color,
87
+ ConversionResponse,
88
+ HotKey,
89
+ HotKeys,
90
+ JoinRoomParams,
91
+ MemberState,
92
+ MountParams,
93
+ PublicEvent,
94
+ Rectangle,
95
+ Room,
96
+ RoomPhase,
97
+ RoomCallbacks,
98
+ RoomState,
99
+ SceneDefinition,
100
+ ShapeType,
101
+ ViewCallbacks,
102
+ WhiteWebSdk,
103
+ WhiteWebSdkConfiguration,
104
+ WindowManager,
105
+ };
106
+
107
+ export type Appliance = `${ApplianceNames}`;
108
+ export type Shape = `${ShapeType}`;
109
+
75
110
  export interface InsertDocsStatic {
76
111
  readonly fileType: "pdf";
77
112
  readonly scenePath: string;
@@ -122,7 +157,7 @@ export class FastboardApp extends FastboardAppBase {
122
157
  /**
123
158
  * Is current room writable?
124
159
  */
125
- readonly writable = this.createValue(
160
+ readonly writable = writable(
126
161
  this.room.isWritable,
127
162
  set => this._addRoomListener("onEnableWriteNowChanged", () => set(this.room.isWritable)),
128
163
  this.room.setWritable.bind(this.room)
@@ -131,50 +166,50 @@ export class FastboardApp extends FastboardAppBase {
131
166
  /**
132
167
  * Current window-manager's windows' state (is it maximized?).
133
168
  */
134
- readonly boxState = this.createValue(this.manager.boxState, set =>
135
- this._addManagerListener("boxStateChange", set)
136
- );
169
+ readonly boxState = readable(this.manager.boxState, set => this._addManagerListener("boxStateChange", set));
137
170
 
138
171
  /**
139
172
  * Current window-manager's focused app's id.
140
173
  * @example "HelloWorld-1A2b3C4d"
141
174
  */
142
- readonly focusedApp = this.createValue(this.manager.focused, set =>
143
- this._addManagerListener("focusedChange", set)
144
- );
175
+ readonly focusedApp = readable(this.manager.focused, set => this._addManagerListener("focusedChange", set));
145
176
 
146
177
  /**
147
178
  * How many times can I call `app.redo()`?
148
179
  */
149
- readonly canRedoSteps = this.createValue(this.manager.canRedoSteps, set =>
180
+ readonly canRedoSteps = readable(this.manager.canRedoSteps, set =>
150
181
  this._addManagerListener("canRedoStepsChange", set)
151
182
  );
152
183
 
153
184
  /**
154
185
  * How many times can I call `app.undo()`?
155
186
  */
156
- readonly canUndoSteps = this.createValue(this.manager.canUndoSteps, set =>
187
+ readonly canUndoSteps = readable(this.manager.canUndoSteps, set =>
157
188
  this._addManagerListener("canUndoStepsChange", set)
158
189
  );
159
190
 
160
191
  /**
161
192
  * Current camera information of main view.
193
+ *
194
+ * Change the camera position by `app.moveCamera()`.
162
195
  */
163
- readonly camera = this.createValue(this.manager.mainView.camera, set =>
196
+ readonly camera = readable(this.manager.mainView.camera, set =>
164
197
  this._addMainViewListener("onCameraUpdated", set)
165
198
  );
166
199
 
167
200
  /**
168
201
  * Current tool's info, like "is using pencil?", "what color?".
202
+ *
203
+ * Change the tool by `app.setAppliance()`.
169
204
  */
170
- readonly memberState = this.createValue(this.room.state.memberState, set =>
205
+ readonly memberState = readable(this.room.state.memberState, set =>
171
206
  this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m))
172
207
  );
173
208
 
174
209
  /**
175
210
  * 0..n-1, current index of main view scenes.
176
211
  */
177
- readonly sceneIndex = this.createValue(
212
+ readonly sceneIndex = writable(
178
213
  this.manager.mainViewSceneIndex,
179
214
  set => this._addManagerListener("mainViewSceneIndexChange", set),
180
215
  this.manager.setMainViewSceneIndex.bind(this.manager)
@@ -183,7 +218,7 @@ export class FastboardApp extends FastboardAppBase {
183
218
  /**
184
219
  * How many pages are in the main view?
185
220
  */
186
- readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>
221
+ readonly sceneLength = readable(this.manager.mainViewScenesLength, set =>
187
222
  this._addManagerListener("mainViewScenesLengthChange", set)
188
223
  );
189
224
 
@@ -191,12 +226,9 @@ export class FastboardApp extends FastboardAppBase {
191
226
  /**
192
227
  * Apps status.
193
228
  */
194
- readonly appsStatus = this.createValue<AppsStatus>({}, set =>
229
+ readonly appsStatus = readable<AppsStatus>({}, set =>
195
230
  this._addManagerListener("loadApp", ({ kind, status, reason }) => {
196
- this._appsStatus[kind] = {
197
- status: status === "start" ? "loading" : status === "failed" ? "failed" : "idle",
198
- reason,
199
- };
231
+ this._appsStatus[kind] = { status: transform_app_status(status), reason };
200
232
  set(this._appsStatus);
201
233
  })
202
234
  );
@@ -206,7 +238,7 @@ export class FastboardApp extends FastboardAppBase {
206
238
  */
207
239
  undo() {
208
240
  this._assertNotDestroyed();
209
- this.manager.mainView.undo();
241
+ this.manager.undo();
210
242
  }
211
243
 
212
244
  /**
@@ -214,7 +246,7 @@ export class FastboardApp extends FastboardAppBase {
214
246
  */
215
247
  redo() {
216
248
  this._assertNotDestroyed();
217
- this.manager.mainView.redo();
249
+ this.manager.redo();
218
250
  }
219
251
 
220
252
  /**
@@ -244,9 +276,12 @@ export class FastboardApp extends FastboardAppBase {
244
276
  /**
245
277
  * Set current tool, like "pencil".
246
278
  */
247
- setAppliance(appliance: ApplianceNames, shape?: ShapeType) {
279
+ setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {
248
280
  this._assertNotDestroyed();
249
- this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });
281
+ this.manager.mainView.setMemberState({
282
+ currentApplianceName: appliance as ApplianceNames,
283
+ shapeType: shape as ShapeType,
284
+ });
250
285
  }
251
286
 
252
287
  setStrokeWidth(strokeWidth: number) {
@@ -259,6 +294,21 @@ export class FastboardApp extends FastboardAppBase {
259
294
  this.manager.mainView.setMemberState({ strokeColor });
260
295
  }
261
296
 
297
+ prevPage() {
298
+ this._assertNotDestroyed();
299
+ return this.manager.prevPage();
300
+ }
301
+
302
+ nextPage() {
303
+ this._assertNotDestroyed();
304
+ return this.manager.nextPage();
305
+ }
306
+
307
+ addPage(params?: AddPageParams) {
308
+ this._assertNotDestroyed();
309
+ return this.manager.addPage(params);
310
+ }
311
+
262
312
  /**
263
313
  * Insert an image to the main view.
264
314
  */
@@ -310,19 +360,20 @@ export class FastboardApp extends FastboardAppBase {
310
360
  insertDocs(params: InsertDocsParams): Promise<string | undefined>;
311
361
 
312
362
  insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse) {
363
+ this._assertNotDestroyed();
313
364
  if (typeof arg1 === "object" && "fileType" in arg1) {
314
365
  return this._insertDocsImpl(arg1);
315
366
  } else if (arg2 && arg2.status !== "Finished") {
316
- throw new Error("[FastboardApp] Can not insert a converting doc.");
367
+ throw new Error("FastboardApp cannot insert a converting doc.");
317
368
  } else if (arg2 && arg2.progress) {
318
- const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);
369
+ const title = arg1;
319
370
  const scenePath = `/${arg2.uuid}/${genUID()}`;
320
- const { emptyScenes, taskId, url } = makeSlideParams(scenes);
371
+ const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);
372
+ const { scenes, taskId, url } = makeSlideParams(scenes1);
321
373
  if (taskId && url) {
322
- const title = arg1;
323
- return this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url, scenes: emptyScenes });
374
+ return this._insertDocsImpl({ fileType: "pptx", scenePath, scenes, title, taskId, url });
324
375
  } else {
325
- return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title: arg1 });
376
+ return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes: scenes1, title });
326
377
  }
327
378
  }
328
379
  }
@@ -336,6 +387,9 @@ export class FastboardApp extends FastboardAppBase {
336
387
  options: { scenePath, title, scenes },
337
388
  });
338
389
  case "pptx":
390
+ if (scenes && scenes[0].ppt) {
391
+ warn("no-ppt-in-scenes");
392
+ }
339
393
  return this.manager.addApp({
340
394
  kind: "Slide",
341
395
  options: { scenePath, title, scenes },
@@ -389,3 +443,78 @@ export class FastboardApp extends FastboardAppBase {
389
443
  });
390
444
  }
391
445
  }
446
+
447
+ export interface FastboardOptions {
448
+ sdkConfig: Omit<WhiteWebSdkConfiguration, "useMobXState"> & {
449
+ region: NonNullable<WhiteWebSdkConfiguration["region"]>;
450
+ };
451
+ joinRoom: Omit<JoinRoomParams, "useMultiViews" | "disableNewPencil" | "disableMagixEventDispatchLimit"> & {
452
+ callbacks?: Partial<RoomCallbacks>;
453
+ };
454
+ managerConfig?: Omit<MountParams, "room">;
455
+ }
456
+
457
+ /**
458
+ * Create a FastboardApp instance.
459
+ * @example
460
+ * let app = await createFastboard({
461
+ * sdkConfig: {
462
+ * appIdentifier: import.meta.env.VITE_APPID,
463
+ * region: 'cn-hz',
464
+ * },
465
+ * joinRoom: {
466
+ * uid: unique_id,
467
+ * uuid: import.meta.env.VITE_ROOM_UUID,
468
+ * roomToken: import.meta.env.VITE_ROOM_TOKEN,
469
+ * },
470
+ * })
471
+ */
472
+ export async function createFastboard({
473
+ sdkConfig,
474
+ joinRoom: { callbacks, ...joinRoomParams },
475
+ managerConfig,
476
+ }: FastboardOptions) {
477
+ const sdk = new WhiteWebSdk({
478
+ ...sdkConfig,
479
+ useMobXState: true,
480
+ });
481
+
482
+ const hotKeys: Partial<HotKeys> = {
483
+ ...DefaultHotKeys,
484
+ changeToSelector: "s",
485
+ changeToLaserPointer: "z",
486
+ changeToPencil: "p",
487
+ changeToRectangle: "r",
488
+ changeToEllipse: "c",
489
+ changeToEraser: "e",
490
+ changeToText: "t",
491
+ changeToStraight: "l",
492
+ changeToArrow: "a",
493
+ changeToHand: "h",
494
+ };
495
+
496
+ const room = await sdk.joinRoom(
497
+ {
498
+ floatBar: true,
499
+ hotKeys,
500
+ ...ensure_window_manager(joinRoomParams),
501
+ useMultiViews: true,
502
+ disableNewPencil: false,
503
+ disableMagixEventDispatchLimit: true,
504
+ },
505
+ callbacks
506
+ );
507
+
508
+ const manager = await WindowManager.mount({
509
+ cursor: true,
510
+ ...managerConfig,
511
+ room,
512
+ });
513
+
514
+ manager.mainView.setCameraBound({
515
+ minContentMode: contentModeScale(0.3),
516
+ maxContentMode: contentModeScale(3),
517
+ });
518
+
519
+ return new FastboardApp(sdk, room, manager, hotKeys);
520
+ }
@@ -0,0 +1,203 @@
1
+ import type { MountParams, PublicEvent } from "@netless/window-manager";
2
+ import type {
3
+ Player,
4
+ PlayerPhase as PlayerPhaseEnum,
5
+ PlayerCallbacks,
6
+ PlayerState,
7
+ PlayerSeekingResult,
8
+ ReplayRoomParams,
9
+ ViewCallbacks,
10
+ WhiteWebSdkConfiguration,
11
+ } from "white-web-sdk";
12
+
13
+ import { WhiteWebSdk } from "white-web-sdk";
14
+ import { WindowManager } from "@netless/window-manager";
15
+ import { readable, writable } from "../utils";
16
+ import { ensure_window_manager } from "../internal";
17
+
18
+ class FastboardPlayerBase {
19
+ public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}
20
+
21
+ protected _destroyed = false;
22
+ protected _assertNotDestroyed() {
23
+ if (this._destroyed) {
24
+ throw new Error("FastboardApp has been destroyed");
25
+ }
26
+ }
27
+
28
+ protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {
29
+ this._assertNotDestroyed();
30
+ this.player.callbacks.on(name, listener);
31
+ return () => this.player.callbacks.off(name, listener);
32
+ }
33
+
34
+ protected _addManagerListener<K extends keyof PublicEvent>(
35
+ name: K,
36
+ listener: (value: PublicEvent[K]) => void
37
+ ) {
38
+ this._assertNotDestroyed();
39
+ this.manager.emitter.on(name, listener);
40
+ return () => this.manager.emitter.off(name, listener);
41
+ }
42
+
43
+ protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {
44
+ this._assertNotDestroyed();
45
+ this.manager.mainView.callbacks.on(name, listener);
46
+ return () => this.manager.mainView.callbacks.off(name, listener);
47
+ }
48
+
49
+ public destroy() {
50
+ this._destroyed = true;
51
+ this.manager.destroy();
52
+ return this.player.callbacks.off();
53
+ }
54
+ }
55
+
56
+ type PlayerPhase = `${PlayerPhaseEnum}`;
57
+
58
+ export type { PlayerPhase, PlayerSeekingResult };
59
+
60
+ export class FastboardPlayer extends FastboardPlayerBase {
61
+ /**
62
+ * Render this player to some DOM.
63
+ */
64
+ bindContainer(container: HTMLElement) {
65
+ this._assertNotDestroyed();
66
+ this.manager.bindContainer(container);
67
+ }
68
+
69
+ /**
70
+ * Move window-manager's collector to some place.
71
+ */
72
+ bindCollector(container: HTMLElement) {
73
+ this._assertNotDestroyed();
74
+ this.manager.bindCollectorContainer(container);
75
+ }
76
+
77
+ readonly currentTime = writable(
78
+ this.player.progressTime,
79
+ set => this._addPlayerListener("onProgressTimeChanged", set),
80
+ this.player.seekToProgressTime.bind(this.player)
81
+ );
82
+
83
+ readonly phase = readable<PlayerPhase>(this.player.phase, set =>
84
+ this._addPlayerListener("onPhaseChanged", set)
85
+ );
86
+
87
+ readonly canplay = readable(this.player.isPlayable, set =>
88
+ this._addPlayerListener("onIsPlayableChanged", set)
89
+ );
90
+
91
+ private _setSpeed!: (value: number) => void;
92
+ readonly speed = writable(
93
+ this.player.playbackSpeed,
94
+ set => {
95
+ this._setSpeed = set;
96
+ },
97
+ value => {
98
+ this.player.playbackSpeed = value;
99
+ this._setSpeed(value);
100
+ }
101
+ );
102
+
103
+ private _setReady!: (value: boolean) => void;
104
+ readonly ready = readable(false, set => {
105
+ this._setReady = set;
106
+ });
107
+
108
+ private _setDuration!: (value: number) => void;
109
+ readonly duration = readable(0, set => {
110
+ this._setDuration = set;
111
+ });
112
+
113
+ readonly state = readable<PlayerState | null>(null, set => {
114
+ const update = () => set(this.player.state);
115
+ this.player.callbacks.once("onLoadFirstFrame", () => {
116
+ this._setDuration(this.player.timeDuration);
117
+ this._setReady(true);
118
+ update();
119
+ });
120
+ return this._addPlayerListener("onPlayerStateChanged", update);
121
+ });
122
+
123
+ seek(timestamp: number) {
124
+ this._assertNotDestroyed();
125
+ return this.player.seekToProgressTime(timestamp);
126
+ }
127
+
128
+ play() {
129
+ this._assertNotDestroyed();
130
+ this.player.play();
131
+ }
132
+
133
+ pause() {
134
+ this._assertNotDestroyed();
135
+ this.player.pause();
136
+ }
137
+
138
+ stop() {
139
+ this._assertNotDestroyed();
140
+ this.player.stop();
141
+ }
142
+
143
+ setSpeed(value: number) {
144
+ this._assertNotDestroyed();
145
+ this.speed.set(value);
146
+ }
147
+ }
148
+
149
+ export interface FastboardReplayOptions {
150
+ sdkConfig: Omit<WhiteWebSdkConfiguration, "useMobXState"> & {
151
+ region: NonNullable<WhiteWebSdkConfiguration["region"]>;
152
+ };
153
+ replayRoom: Omit<ReplayRoomParams, "useMultiViews"> & {
154
+ callbacks?: Partial<PlayerCallbacks>;
155
+ };
156
+ managerConfig?: Omit<MountParams, "room">;
157
+ }
158
+
159
+ /**
160
+ * Create a FastboardApp instance.
161
+ * @example
162
+ * let player = await replayFastboard({
163
+ * sdkConfig: {
164
+ * appIdentifier: import.meta.env.VITE_APPID,
165
+ * region: 'cn-hz',
166
+ * },
167
+ * replayRoom: {
168
+ * uid: unique_id,
169
+ * uuid: import.meta.env.VITE_ROOM_UUID,
170
+ * roomToken: import.meta.env.VITE_ROOM_TOKEN,
171
+ * },
172
+ * })
173
+ */
174
+ export async function replayFastboard({
175
+ sdkConfig,
176
+ replayRoom: { callbacks, ...replayRoomParams },
177
+ managerConfig,
178
+ }: FastboardReplayOptions) {
179
+ const sdk = new WhiteWebSdk({
180
+ ...sdkConfig,
181
+ useMobXState: true,
182
+ });
183
+
184
+ const player = await sdk.replayRoom(
185
+ {
186
+ ...ensure_window_manager(replayRoomParams),
187
+ useMultiViews: true,
188
+ },
189
+ callbacks
190
+ );
191
+
192
+ const managerPromise = WindowManager.mount({
193
+ cursor: true,
194
+ ...managerConfig,
195
+ room: player,
196
+ });
197
+
198
+ player.play();
199
+ const manager = await managerPromise;
200
+ player.pause();
201
+
202
+ return new FastboardPlayer(sdk, player, manager);
203
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./FastboardApp";
2
+ export * from "./FastboardPlayer";
3
+
4
+ import "../behaviors";
package/src/index.ts CHANGED
@@ -1,3 +1,2 @@
1
- export * from "./minimal";
2
-
3
- import "./behaviors/register-slide";
1
+ export * from "./utils";
2
+ export * from "./impl";
@@ -0,0 +1,14 @@
1
+ import type { JoinRoomParams, ReplayRoomParams } from "white-web-sdk";
2
+ import type { PublicEvent } from "@netless/window-manager";
3
+ import { WindowManager } from "@netless/window-manager";
4
+
5
+ export function ensure_window_manager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {
6
+ if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {
7
+ joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];
8
+ }
9
+ return joinRoom;
10
+ }
11
+
12
+ export function transform_app_status(status: PublicEvent["loadApp"]["status"]) {
13
+ return status === "start" ? "loading" : status === "failed" ? "failed" : "idle";
14
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./store";
2
+ export * from "./misc";
3
+ export * from "./uid";
4
+ export * from "./warn";