@netless/fastboard-core 0.3.7 → 0.3.8

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/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { AddPageParams, MountParams, NetlessApp, WindowManager, PublicEvent, Reg
4
4
  export { AddPageParams, MountParams, NetlessApp, PublicEvent, WindowManager } from '@netless/window-manager';
5
5
  import { SyncedStore } from '@netless/synced-store';
6
6
  export { Diff, DiffOne, Storage, SyncedStore } from '@netless/synced-store';
7
- export { PreviewParams, default as SlideApp, Controller as SlideController, AppOptions as SlideOptions, SlidePreviewer, addHooks as addSlideHooks, previewSlide, apps as slideApps } from '@netless/app-slide';
7
+ export { PreviewParams, default as SlideApp, AppResult as SlideController, AppOptions as SlideOptions, SlidePreviewer, addHooks as addSlideHooks, previewSlide, apps as slideApps } from '@netless/app-slide';
8
8
 
9
9
  type Subscriber<T> = (value: T) => void;
10
10
  type Unsubscriber = () => void;
@@ -85,6 +85,29 @@ interface InsertDocsDynamic {
85
85
  readonly scenes?: SceneDefinition[];
86
86
  }
87
87
  type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;
88
+ interface ProjectorResponse {
89
+ uuid: string;
90
+ status: "Waiting" | "Converting" | "Finished" | "Fail";
91
+ type: "dynamic" | "static";
92
+ /** 0..100 */
93
+ convertedPercentage: number;
94
+ /** https://example.org/path/to/dynamicConvert, only when type=dynamic */
95
+ prefix?: string;
96
+ pageCount?: number;
97
+ /** {1:"{prefix}/{taskId}/preview/1.png"}, only when type=dynamic and preview=true */
98
+ previews?: Record<number, string>;
99
+ /** {prefix}/{taskId}/jsonOutput/note.json */
100
+ note?: string;
101
+ /** {1:{width,height,url}}, only when type=static */
102
+ images?: Record<number, {
103
+ width: number;
104
+ height: number;
105
+ url: string;
106
+ }>;
107
+ /** 20xxxxx */
108
+ errorCode?: string;
109
+ errorMessage?: string;
110
+ }
88
111
  type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;
89
112
  type RoomStateChanged = (diff: Partial<RoomState>) => void;
90
113
  /** App download progress. */
@@ -149,7 +172,6 @@ declare class FastboardApp<TEventData extends Record<string, any> = any> extends
149
172
  * How many pages are in the main view?
150
173
  */
151
174
  readonly sceneLength: Readable<number>;
152
- private _appsStatus;
153
175
  /**
154
176
  * Apps status.
155
177
  */
@@ -238,6 +260,11 @@ declare class FastboardApp<TEventData extends Record<string, any> = any> extends
238
260
  * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress
239
261
  */
240
262
  insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;
263
+ /**
264
+ * Insert PDF/PPTX from projector conversion result.
265
+ * @param response https://developer.netless.link/server-zh/home/server-projector#get-%E6%9F%A5%E8%AF%A2%E4%BB%BB%E5%8A%A1%E8%BD%AC%E6%8D%A2%E8%BF%9B%E5%BA%A6
266
+ */
267
+ insertDocs(filename: string, response: ProjectorResponse): Promise<string | undefined>;
241
268
  /**
242
269
  * Manual way.
243
270
  * @example
@@ -249,7 +276,6 @@ declare class FastboardApp<TEventData extends Record<string, any> = any> extends
249
276
  * })
250
277
  */
251
278
  insertDocs(params: InsertDocsParams): Promise<string | undefined>;
252
- private _insertDocsImpl;
253
279
  /**
254
280
  * Insert the Media Player app.
255
281
  */
@@ -333,7 +359,6 @@ declare class FastboardPlayer<TEventData extends Record<string, any> = any> exte
333
359
  * Will become true after buffering.
334
360
  */
335
361
  readonly canplay: Readable<boolean>;
336
- private _setPlaybackRate;
337
362
  /**
338
363
  * Playback speed, default `1`.
339
364
  */
@@ -406,4 +431,29 @@ declare function addPlayerListener<K extends keyof PlayerCallbacks>(player: Play
406
431
  declare function addViewListener<K extends keyof ViewCallbacks>(view: View, name: K, listener: (value: ViewCallbacks[K]) => void): () => void;
407
432
  declare function addManagerListener<K extends keyof PublicEvent>(manager: WindowManager, name: K, listener: (value: PublicEvent[K]) => void): () => void;
408
433
 
409
- export { Appliance, AppsConfig, AppsStatus, FastboardApp, FastboardOptions, FastboardPlayer, FastboardReplayOptions, InsertDocsDynamic, InsertDocsParams, InsertDocsStatic, PlayerPhase, Readable, RoomPhase, RoomStateChanged, SetMemberStateFn, Shape, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable, addManagerListener, addPlayerListener, addRoomListener, addViewListener, convertedFileToScene, createFastboard, genUID, getImageSize, makeSlideParams, readable, register, replayFastboard, version, warn, writable };
434
+ interface DocsEventOptions {
435
+ /** If provided, will dispatch to the specific app. Default to the focused app. */
436
+ appId?: string;
437
+ /** Used by `jumpToPage` event, range from 1 to total pages count. */
438
+ page?: number;
439
+ }
440
+ /**
441
+ * Send specific command to the static docs / slide app.
442
+ * Only works for apps that were created by `insertDocs()`.
443
+ *
444
+ * Returns false if failed to find the app or not writable.
445
+ *
446
+ * For static docs, `nextPage` equals to `nextStep`, as with `prevPage` and `prevStep`.
447
+ *
448
+ * @example
449
+ * ```js
450
+ * // send "next page" to the focused app
451
+ * dispatchDocsEvent(fastboard, "nextPage")
452
+ *
453
+ * // send "prev page" to some app
454
+ * dispatchDocsEvent(fastboard, "prevPage", {appId:"Slide-1a2b3c4d"})
455
+ * ```
456
+ */
457
+ declare function dispatchDocsEvent(fastboard: FastboardApp | WindowManager, event: "prevPage" | "nextPage" | "prevStep" | "nextStep" | "jumpToPage", options?: DocsEventOptions): boolean;
458
+
459
+ export { Appliance, AppsConfig, AppsStatus, DocsEventOptions, FastboardApp, FastboardOptions, FastboardPlayer, FastboardReplayOptions, InsertDocsDynamic, InsertDocsParams, InsertDocsStatic, PlayerPhase, ProjectorResponse, Readable, RoomPhase, RoomStateChanged, SetMemberStateFn, Shape, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable, addManagerListener, addPlayerListener, addRoomListener, addViewListener, convertedFileToScene, createFastboard, dispatchDocsEvent, genUID, getImageSize, makeSlideParams, readable, register, replayFastboard, version, warn, writable };
package/dist/index.js CHANGED
@@ -215,7 +215,7 @@ for (const kind in DefaultApps) {
215
215
  }
216
216
  }
217
217
  var register = windowManager.WindowManager.register.bind(windowManager.WindowManager);
218
- var version = "0.3.7";
218
+ var version = "0.3.8";
219
219
  if (typeof window !== "undefined") {
220
220
  let str = window.__netlessUA || "";
221
221
  str += ` ${"@netless/fastboard"}@${version} `;
@@ -414,7 +414,7 @@ var FastboardApp = class extends FastboardAppBase {
414
414
  return this._insertDocsImpl(arg1);
415
415
  } else if (arg2 && arg2.status !== "Finished") {
416
416
  throw new Error("FastboardApp cannot insert a converting doc.");
417
- } else if (arg2 && arg2.progress) {
417
+ } else if (arg2 && "progress" in arg2) {
418
418
  const title = arg1;
419
419
  const scenePath = `/${arg2.uuid}/${genUID()}`;
420
420
  const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);
@@ -424,6 +424,23 @@ var FastboardApp = class extends FastboardAppBase {
424
424
  } else {
425
425
  return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes: scenes1, title });
426
426
  }
427
+ } else if (arg2 && arg2.prefix) {
428
+ const title = arg1;
429
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
430
+ const taskId = arg2.uuid;
431
+ const url = arg2.prefix;
432
+ this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url });
433
+ } else if (arg2 && arg2.images) {
434
+ const title = arg1;
435
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
436
+ const scenes = [];
437
+ for (const name in arg2.images) {
438
+ const { width, height, url } = arg2.images[name];
439
+ scenes.push({ name, ppt: { width, height, src: url } });
440
+ }
441
+ this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title });
442
+ } else {
443
+ throw new Error("Invalid input: not found 'progress', 'prefix' nor 'images'");
427
444
  }
428
445
  }
429
446
  _insertDocsImpl(_a) {
@@ -664,7 +681,7 @@ async function replayFastboard(_a) {
664
681
  return new FastboardPlayer(sdk, player, manager, syncedStore$1);
665
682
  }
666
683
 
667
- // src/helpers/index.ts
684
+ // src/helpers/listen.ts
668
685
  function addRoomListener(room, name, listener) {
669
686
  room.callbacks.on(name, listener);
670
687
  return () => room.callbacks.off(name, listener);
@@ -681,6 +698,81 @@ function addManagerListener(manager, name, listener) {
681
698
  return manager.emitter.on(name, listener);
682
699
  }
683
700
 
701
+ // src/helpers/docs.ts
702
+ function dispatchDocsEvent(fastboard, event, options = {}) {
703
+ var _a, _b, _c;
704
+ const manager = "manager" in fastboard ? fastboard.manager : fastboard;
705
+ const appId = options.appId || manager.focused;
706
+ if (!appId) {
707
+ console.warn("not found " + (options.appId || "focused app"));
708
+ return false;
709
+ }
710
+ let page, input;
711
+ if (appId.startsWith("DocsViewer-")) {
712
+ const dom = (_b = (_a = manager.queryOne(appId)) == null ? void 0 : _a.box) == null ? void 0 : _b.$footer;
713
+ if (!dom) {
714
+ console.warn("not found app with id " + appId);
715
+ return false;
716
+ }
717
+ const click = (el) => {
718
+ el && el.dispatchEvent(new MouseEvent("click"));
719
+ };
720
+ switch (event) {
721
+ case "prevPage":
722
+ case "prevStep":
723
+ click(dom.querySelector('button[class$="btn-page-back"]'));
724
+ break;
725
+ case "nextPage":
726
+ case "nextStep":
727
+ click(dom.querySelector('button[class$="btn-page-next"]'));
728
+ break;
729
+ case "jumpToPage":
730
+ page = options.page;
731
+ input = dom.querySelector('input[class$="page-number-input"]');
732
+ if (!input || typeof page !== "number") {
733
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
734
+ return false;
735
+ }
736
+ input.value = "" + page;
737
+ input.dispatchEvent(new InputEvent("change"));
738
+ break;
739
+ default:
740
+ console.warn("unknown event " + event);
741
+ return false;
742
+ }
743
+ return true;
744
+ } else if (appId.startsWith("Slide-")) {
745
+ const app = (_c = manager.queryOne(appId)) == null ? void 0 : _c.appResult;
746
+ if (!app) {
747
+ console.warn("not found app with id " + appId);
748
+ return false;
749
+ }
750
+ switch (event) {
751
+ case "prevPage":
752
+ return app.prevPage();
753
+ case "nextPage":
754
+ return app.nextPage();
755
+ case "prevStep":
756
+ return app.prevStep();
757
+ case "nextStep":
758
+ return app.nextStep();
759
+ case "jumpToPage":
760
+ page = options.page;
761
+ if (typeof page !== "number") {
762
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
763
+ return false;
764
+ }
765
+ return app.jumpToPage(page);
766
+ default:
767
+ console.warn("unknown event " + event);
768
+ return false;
769
+ }
770
+ } else {
771
+ console.warn("not supported app " + appId);
772
+ return false;
773
+ }
774
+ }
775
+
684
776
  exports.SlideApp = SlideApp;
685
777
  Object.defineProperty(exports, 'addSlideHooks', {
686
778
  enumerable: true,
@@ -702,6 +794,7 @@ exports.addRoomListener = addRoomListener;
702
794
  exports.addViewListener = addViewListener;
703
795
  exports.convertedFileToScene = convertedFileToScene;
704
796
  exports.createFastboard = createFastboard;
797
+ exports.dispatchDocsEvent = dispatchDocsEvent;
705
798
  exports.genUID = genUID;
706
799
  exports.getImageSize = getImageSize;
707
800
  exports.makeSlideParams = makeSlideParams;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/store.ts","../src/utils/misc.ts","../src/utils/uid.ts","../src/utils/warn.ts","../src/impl/FastboardApp.ts","../src/internal.ts","../src/behaviors/index.ts","../src/impl/FastboardPlayer.ts","../src/helpers/index.ts"],"names":["WindowManager","SyncedStorePlugin","WhiteWebSdk"],"mappings":"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","sourcesContent":["// This is a simple mimic of svelte/store.\nexport type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\nexport type Updater<T> = (value: T) => T;\nexport type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;\n\nexport interface Readable<T> {\n readonly value: T;\n subscribe(this: void, run: Subscriber<T>): Unsubscriber;\n reaction(this: void, run: Subscriber<T>): Unsubscriber;\n}\n\nexport interface Writable<T> extends Readable<T> {\n set(this: void, value: T): void;\n update(this: void, updater: Updater<T>): void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noop() {}\n\nfunction safe_not_equal(a: unknown, b: unknown) {\n return a != a ? b == b : a !== b || (a && typeof a === \"object\") || typeof a === \"function\";\n}\n\nexport function readable<T>(value: T, start: StartStopNotifier<T> = noop): Readable<T> {\n let stop: Unsubscriber | undefined;\n const subscribers = new Set<Subscriber<T>>();\n function set(new_value: T) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) {\n for (const run of subscribers) {\n run(value);\n }\n }\n }\n }\n function subscribe(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n function reaction(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n return {\n get value() {\n return value;\n },\n subscribe,\n reaction,\n };\n}\n\nexport function writable<T>(value: T, start: StartStopNotifier<T> = noop, set: Subscriber<T>): Writable<T> {\n const internal = readable(value, start);\n return {\n get value() {\n return internal.value;\n },\n subscribe: internal.subscribe,\n reaction: internal.reaction,\n set,\n update(fn: Updater<T>) {\n set(fn(value));\n },\n };\n}\n","import type { ConvertedFile, SceneDefinition, Size } from \"white-web-sdk\";\n\nexport function getImageSize(url: string, fallback: Size) {\n return new Promise<Size>(resolve => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => resolve(fallback);\n img.src = url;\n });\n}\n\nexport function makeSlideParams(scenes: SceneDefinition[]) {\n const emptyScenes: SceneDefinition[] = [];\n let taskId = \"\";\n let url = \"\";\n\n // e.g. \"ppt(x)://cdn/prefix/dynamicConvert/{taskId}/1.slide\"\n const pptSrcRE = /^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\//;\n\n for (const { name, ppt } of scenes) {\n // make sure scenesWithoutPPT.length === scenes.length\n emptyScenes.push({ name });\n\n if (!ppt || !ppt.src.startsWith(\"ppt\")) continue;\n\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) continue;\n\n taskId = match.groups.taskId;\n url = `https${match.groups.prefix}`;\n break;\n }\n\n return { scenes: emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number): SceneDefinition {\n return {\n name: String(i + 1),\n ppt: {\n src: f.conversionFileUrl,\n width: f.width,\n height: f.height,\n previewURL: f.preview,\n },\n };\n}\n","// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 62; // SOUP.length\nconst ID_LEN = 20;\nconst reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);\n\nexport function genUID() {\n for (let i = 0; i < ID_LEN; i++) {\n reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);\n }\n return reusedIdCarrier.join(\"\");\n}\n","const warnings = {\n \"no-ppt-in-scenes\":\n \"You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`.\",\n} as const;\nconst warned = new Set<string>();\n\nexport function warn(id: keyof typeof warnings) {\n if (warned.has(id)) return;\n warned.add(id);\n console.warn(warnings[id]);\n}\n","import type { AddPageParams, PublicEvent, MountParams, NetlessApp } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n Rectangle,\n Room,\n RoomPhase as RoomPhaseEnum,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore, Storage, Diff, DiffOne } from \"@netless/synced-store\";\n\nimport { DefaultHotKeys, WhiteWebSdk, contentModeScale } from \"white-web-sdk\";\nimport { BuiltinApps, WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport {\n getImageSize,\n genUID,\n convertedFileToScene,\n makeSlideParams,\n readable,\n writable,\n warn,\n} from \"../utils\";\nimport { ensure_official_plugins, transform_app_status } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardAppBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {\n this._assertNotDestroyed();\n this.room.callbacks.on(name, listener);\n return () => this.room.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n /**\n * Destroy fastboard (disconnect from the whiteboard room).\n */\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\ntype RoomPhase = `${RoomPhaseEnum}`;\n\nexport type {\n AddPageParams,\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n MountParams,\n NetlessApp,\n PublicEvent,\n Rectangle,\n Room,\n RoomPhase,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n SyncedStore,\n Storage,\n Diff,\n DiffOne,\n ViewCallbacks,\n WhiteWebSdk,\n WhiteWebSdkConfiguration,\n WindowManager,\n};\n\n/** pencil, eraser, rectangle... */\nexport type Appliance = `${ApplianceNames}`;\n/** triangle, star... */\nexport type Shape = `${ShapeType}`;\n\n/** Params for static docs, they are rendered as many images. */\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** @example [{ name: '1', ppt: { src: 'url/to/ppt/1.png' } }] */\n readonly scenes: SceneDefinition[];\n /** Window title. */\n readonly title?: string;\n}\n\n/** Params for slides, they are rendered in @netless/app-slide with animations. */\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** Conversion task id, see https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress. */\n readonly taskId: string;\n /** Window title. */\n readonly title?: string;\n /** Where the slide resource placed. @default `https://convertcdn.netless.link/dynamicConvert` */\n readonly url?: string;\n /** @example [{ name: '1' }, { name: '2' }, { name: '3' }] */\n readonly scenes?: SceneDefinition[];\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;\n\nexport type RoomStateChanged = (diff: Partial<RoomState>) => void;\n\n/** App download progress. */\nexport interface AppsStatus {\n [kind: string]: {\n status: \"idle\" | \"loading\" | \"failed\";\n /** Exist if status is `failed`. */\n reason?: string;\n };\n}\n\nexport class FastboardApp<TEventData extends Record<string, any> = any> extends FastboardAppBase<TEventData> {\n /**\n * Render this app to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Is current room writable?\n */\n readonly writable = writable(\n this.room.isWritable,\n set => {\n set(this.room.isWritable);\n return this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable));\n },\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Is current room online?\n */\n readonly phase = readable<RoomPhase>(this.room.phase, set => {\n set(this.room.phase);\n return this._addRoomListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = readable(this.manager.boxState, set => {\n set(this.manager.boxState);\n return this._addManagerListener(\"boxStateChange\", set);\n });\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = readable(this.manager.focused, set => {\n set(this.manager.focused);\n return this._addManagerListener(\"focusedChange\", set);\n });\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = readable(this.manager.canRedoSteps, set => {\n set(this.manager.canRedoSteps);\n return this._addManagerListener(\"canRedoStepsChange\", set);\n });\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = readable(this.manager.canUndoSteps, set => {\n set(this.manager.canUndoSteps);\n return this._addManagerListener(\"canUndoStepsChange\", set);\n });\n\n /**\n * Current camera information of main view.\n *\n * Change the camera position by `app.moveCamera()`.\n */\n readonly camera = readable(this.manager.camera, set => {\n set(this.manager.camera);\n return this._addMainViewListener(\"onCameraUpdated\", set);\n });\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n *\n * Change the tool by `app.setAppliance()`.\n */\n readonly memberState = readable(this.room.state.memberState, set => {\n set(this.room.state.memberState);\n return this._addRoomListener(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m));\n });\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = writable(\n this.manager.mainViewSceneIndex,\n set => {\n set(this.manager.mainViewSceneIndex);\n return this._addManagerListener(\"mainViewSceneIndexChange\", set);\n },\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = readable(this.manager.mainViewScenesLength, set => {\n set(this.manager.mainViewScenesLength);\n return this._addManagerListener(\"mainViewScenesLengthChange\", set);\n });\n\n private _appsStatus: AppsStatus = {};\n /**\n * Apps status.\n */\n readonly appsStatus = readable<AppsStatus>({}, set =>\n this._addManagerListener(\"loadApp\", ({ kind, status, reason }) => {\n this._appsStatus[kind] = { status: transform_app_status(status), reason };\n set(this._appsStatus);\n })\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.redo();\n }\n\n /**\n * Move current main view's camera position.\n */\n moveCamera(camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }) {\n this._assertNotDestroyed();\n this.manager.moveCamera(camera);\n }\n\n /**\n * Move current main view's camera to include a rectangle.\n */\n moveCameraToContain(rectangle: Rectangle & { animationMode?: AnimationMode }) {\n this._assertNotDestroyed();\n this.manager.moveCameraToContain(rectangle);\n }\n\n /**\n * Delete all things on the main view.\n */\n cleanCurrentScene() {\n this._assertNotDestroyed();\n this.manager.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({\n currentApplianceName: appliance as ApplianceNames,\n shapeType: shape as ShapeType,\n });\n }\n\n /**\n * Set pencil and shape's thickness.\n */\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n /**\n * Set pencil and shape's color.\n */\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Set text size. Default is 16.\n */\n setTextSize(textSize: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textSize });\n }\n\n /**\n * Set text color.\n *\n * @example\n * setTextColor([0x66, 0xcc, 0xff])\n */\n setTextColor(textColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textColor });\n }\n\n /**\n * Goto previous page (the main whiteboard view).\n */\n prevPage() {\n this._assertNotDestroyed();\n return this.manager.prevPage();\n }\n\n /**\n * Goto next page (the main whiteboard view).\n */\n nextPage() {\n this._assertNotDestroyed();\n return this.manager.nextPage();\n }\n\n /**\n * Add one page to the main whiteboard view.\n *\n * @example\n * addPage({ after: true }) // add one page right after current one.\n * nextPage() // then, goto that page.\n */\n addPage(params?: AddPageParams) {\n this._assertNotDestroyed();\n return this.manager.addPage(params);\n }\n\n /**\n * Remove one page at given index or current page (by default).\n *\n * Requires `@netless/window-manager` >= 0.4.30.\n *\n * @example\n * removePage() // remove current page\n */\n removePage(index?: number) {\n this._assertNotDestroyed();\n return this.manager.removePage(index);\n }\n\n /**\n * Insert an image to the main view.\n *\n * @example\n * insertImage(\"https://i.imgur.com/CzXTtJV.jpg\")\n */\n async insertImage(url: string) {\n this._assertNotDestroyed();\n await this.manager.switchMainViewToWriter();\n\n const { divElement } = this.manager.mainView;\n const containerSize = {\n width: divElement?.scrollWidth || window.innerWidth,\n height: divElement?.scrollHeight || window.innerHeight,\n };\n\n // 1. shrink the image a little to fit container **width**\n const maxWidth = containerSize.width * 0.8;\n let { width, height } = await getImageSize(url, containerSize);\n const scale = Math.min(maxWidth / width, 1);\n const uuid = genUID();\n const { centerX, centerY } = this.manager.camera;\n width *= scale;\n height *= scale;\n this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });\n this.manager.mainView.completeImageUpload(uuid, url);\n\n // 2. move camera to fit image **height**\n width /= 0.8;\n height /= 0.8;\n const originX = centerX - width / 2;\n const originY = centerY - height / 2;\n this.manager.moveCameraToContain({ originX, originY, width, height });\n }\n\n /**\n * Insert PDF/PPTX from conversion result.\n * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress\n */\n insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;\n\n /**\n * Manual way.\n * @example\n * app.insertDocs({\n * fileType: 'pptx',\n * scenePath: `/pptx/${conversion.taskId}`,\n * taskId: conversion.taskId,\n * title: 'Title',\n * })\n */\n insertDocs(params: InsertDocsParams): Promise<string | undefined>;\n\n insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse) {\n this._assertNotDestroyed();\n if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"FastboardApp cannot insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);\n const { scenes, taskId, url } = makeSlideParams(scenes1);\n if (taskId && url) {\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, scenes, title, taskId, url });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes: scenes1, title });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n if (scenes && scenes[0].ppt) {\n warn(\"no-ppt-in-scenes\");\n }\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Media Player app.\n */\n insertMedia(title: string, src: string) {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: BuiltinApps.MediaPlayer,\n options: { title },\n attributes: { src },\n });\n }\n\n /**\n * Insert the Monaco Code Editor app.\n * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.\n */\n insertCodeEditor() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n /**\n * Insert the Countdown app.\n * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.\n */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n /**\n * Insert the GeoGebra app.\n * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<Omit<RoomCallbacks, \"onCanRedoStepsUpdate\" | \"onCanUndoStepsUpdate\">>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardApp instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * joinRoom: {\n * uid: unique_id,\n * uuid: import.meta.env.VITE_ROOM_UUID,\n * roomToken: import.meta.env.VITE_ROOM_TOKEN,\n * },\n * })\n */\nexport async function createFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys = joinRoomParams.hotKeys || {\n ...DefaultHotKeys,\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n };\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensure_official_plugins(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(room);\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n manager.mainView.setCameraBound({\n minContentMode: contentModeScale(0.3),\n maxContentMode: contentModeScale(3),\n });\n\n return new FastboardApp<TEventData>(sdk, room, manager, hotKeys, syncedStore);\n}\n","import type { JoinRoomParams, ReplayRoomParams } from \"white-web-sdk\";\nimport type { PublicEvent } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\n\nexport function ensure_official_plugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n const plugins = new Set(joinRoom.invisiblePlugins || []);\n plugins.add(WindowManager);\n plugins.add(SyncedStorePlugin);\n joinRoom.invisiblePlugins = [...plugins];\n return joinRoom;\n}\n\nexport function transform_app_status(status: PublicEvent[\"loadApp\"][\"status\"]) {\n return status === \"start\" ? \"loading\" : status === \"failed\" ? \"failed\" : \"idle\";\n}\n","import type { RegisterParams } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport SlideApp, { apps, addHooks, previewSlide } from \"@netless/app-slide\";\n\nexport type {\n AppOptions as SlideOptions,\n Controller as SlideController,\n PreviewParams,\n SlidePreviewer,\n} from \"@netless/app-slide\";\nexport { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };\n\nexport interface AppsConfig {\n [kind: string]: Omit<RegisterParams, \"kind\">;\n}\n\nconst DefaultApps: AppsConfig = {\n Monaco: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js\",\n },\n Countdown: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js\",\n },\n GeoGebra: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n },\n EmbeddedPage: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js\",\n },\n Plyr: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js\",\n },\n};\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: { debug: false },\n src: SlideApp,\n addHooks,\n});\n\nfor (const kind in DefaultApps) {\n if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {\n const options = DefaultApps[kind];\n WindowManager.register({ kind, ...options });\n }\n}\n\nexport const register = WindowManager.register.bind(WindowManager);\n\ndeclare let __NAME__: string, __VERSION__: string;\n\nexport const version = __VERSION__;\n\nif (typeof window !== \"undefined\") {\n let str = (window as { __netlessUA?: string }).__netlessUA || \"\";\n str += ` ${__NAME__}@${version} `;\n (window as { __netlessUA?: string }).__netlessUA = str;\n}\n","import type { MountParams, NetlessApp, PublicEvent } from \"@netless/window-manager\";\nimport type {\n Player,\n PlayerPhase as PlayerPhaseEnum,\n PlayerCallbacks,\n PlayerState,\n PlayerSeekingResult,\n ReplayRoomParams,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore } from \"@netless/synced-store\";\n\nimport { WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport { readable, writable } from \"../utils\";\nimport { ensure_official_plugins } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardPlayerBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly player: Player,\n readonly manager: WindowManager,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {\n this._assertNotDestroyed();\n this.player.callbacks.on(name, listener);\n return () => this.player.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.player.callbacks.off();\n }\n}\n\ntype PlayerPhase = `${PlayerPhaseEnum}`;\n\nexport type { PlayerPhase, PlayerSeekingResult };\n\nexport class FastboardPlayer<\n TEventData extends Record<string, any> = any\n> extends FastboardPlayerBase<TEventData> {\n /**\n * Render this player to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Player current time in milliseconds.\n */\n readonly currentTime = writable(\n this.player.progressTime,\n set => {\n set(this.player.progressTime);\n return this._addPlayerListener(\"onProgressTimeChanged\", set);\n },\n this.player.seekToProgressTime.bind(this.player)\n );\n\n /**\n * Player state, like \"is it playing?\".\n */\n readonly phase = readable<PlayerPhase>(this.player.phase, set => {\n set(this.player.phase);\n return this._addPlayerListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Will become true after buffering.\n */\n readonly canplay = readable(this.player.isPlayable, set => {\n set(this.player.isPlayable);\n return this._addPlayerListener(\"onIsPlayableChanged\", set);\n });\n\n private _setPlaybackRate!: (value: number) => void;\n /**\n * Playback speed, default `1`.\n */\n readonly playbackRate = writable(\n this.player.playbackSpeed,\n set => {\n this._setPlaybackRate = set;\n set(this.player.playbackSpeed);\n },\n value => {\n this.player.playbackSpeed = value;\n this._setPlaybackRate(value);\n }\n );\n\n /**\n * Playback duration in milliseconds.\n */\n readonly duration = readable(this.player.timeDuration, set => {\n set(this.player.timeDuration);\n });\n\n /**\n * Get state of room at that time, like \"who was in the room?\".\n */\n readonly state = readable<PlayerState>(this.player.state, set => {\n set(this.player.state);\n return this._addPlayerListener(\"onPlayerStateChanged\", () => set(this.player.state));\n });\n\n /**\n * Seek to some time in milliseconds.\n */\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n /**\n * Change player state to playing.\n */\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n /**\n * Change player state to paused.\n */\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n /**\n * Change player state to stopped.\n */\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n\n /**\n * Set playback speed, a shortcut for `speed.set(x)`.\n */\n setPlaybackRate(value: number) {\n this._assertNotDestroyed();\n this.playbackRate.set(value);\n }\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let player = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * replayRoom: {\n * room: \"room uuid\",\n * roomToken: \"NETLESSROOM_...\",\n * beginTimestamp: 1646619090394,\n * duration: 70448,\n * },\n * })\n */\nexport async function replayFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const player = await sdk.replayRoom(\n {\n ...ensure_official_plugins(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(player);\n\n const managerPromise = WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player,\n });\n\n player.play();\n const manager = await managerPromise;\n player.pause();\n await player.seekToProgressTime(0);\n\n return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);\n}\n","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from \"white-web-sdk\";\n\nexport function addRoomListener<K extends keyof RoomCallbacks>(\n room: Room,\n name: K,\n listener: RoomCallbacks[K]\n) {\n room.callbacks.on(name, listener);\n return () => room.callbacks.off(name, listener);\n}\n\nexport function addPlayerListener<K extends keyof PlayerCallbacks>(\n player: Player,\n name: K,\n listener: PlayerCallbacks[K]\n) {\n player.callbacks.on(name, listener);\n return () => player.callbacks.off(name, listener);\n}\n\nexport function addViewListener<K extends keyof ViewCallbacks>(\n view: View,\n name: K,\n listener: (value: ViewCallbacks[K]) => void\n) {\n view.callbacks.on(name, listener);\n return () => view.callbacks.off(name, listener);\n}\n\nexport function addManagerListener<K extends keyof PublicEvent>(\n manager: WindowManager,\n name: K,\n listener: (value: PublicEvent[K]) => void\n): () => void {\n return manager.emitter.on(name, listener);\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/store.ts","../src/utils/misc.ts","../src/utils/uid.ts","../src/utils/warn.ts","../src/impl/FastboardApp.ts","../src/internal.ts","../src/behaviors/index.ts","../src/impl/FastboardPlayer.ts","../src/helpers/listen.ts","../src/helpers/docs.ts"],"names":["WindowManager","SyncedStorePlugin","WhiteWebSdk"],"mappings":"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","sourcesContent":["// This is a simple mimic of svelte/store.\nexport type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\nexport type Updater<T> = (value: T) => T;\nexport type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;\n\nexport interface Readable<T> {\n readonly value: T;\n subscribe(this: void, run: Subscriber<T>): Unsubscriber;\n reaction(this: void, run: Subscriber<T>): Unsubscriber;\n}\n\nexport interface Writable<T> extends Readable<T> {\n set(this: void, value: T): void;\n update(this: void, updater: Updater<T>): void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noop() {}\n\nfunction safe_not_equal(a: unknown, b: unknown) {\n return a != a ? b == b : a !== b || (a && typeof a === \"object\") || typeof a === \"function\";\n}\n\nexport function readable<T>(value: T, start: StartStopNotifier<T> = noop): Readable<T> {\n let stop: Unsubscriber | undefined;\n const subscribers = new Set<Subscriber<T>>();\n function set(new_value: T) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) {\n for (const run of subscribers) {\n run(value);\n }\n }\n }\n }\n function subscribe(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n function reaction(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n return {\n get value() {\n return value;\n },\n subscribe,\n reaction,\n };\n}\n\nexport function writable<T>(value: T, start: StartStopNotifier<T> = noop, set: Subscriber<T>): Writable<T> {\n const internal = readable(value, start);\n return {\n get value() {\n return internal.value;\n },\n subscribe: internal.subscribe,\n reaction: internal.reaction,\n set,\n update(fn: Updater<T>) {\n set(fn(value));\n },\n };\n}\n","import type { ConvertedFile, SceneDefinition, Size } from \"white-web-sdk\";\n\nexport function getImageSize(url: string, fallback: Size) {\n return new Promise<Size>(resolve => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => resolve(fallback);\n img.src = url;\n });\n}\n\nexport function makeSlideParams(scenes: SceneDefinition[]) {\n const emptyScenes: SceneDefinition[] = [];\n let taskId = \"\";\n let url = \"\";\n\n // e.g. \"ppt(x)://cdn/prefix/dynamicConvert/{taskId}/1.slide\"\n const pptSrcRE = /^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\//;\n\n for (const { name, ppt } of scenes) {\n // make sure scenesWithoutPPT.length === scenes.length\n emptyScenes.push({ name });\n\n if (!ppt || !ppt.src.startsWith(\"ppt\")) continue;\n\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) continue;\n\n taskId = match.groups.taskId;\n url = `https${match.groups.prefix}`;\n break;\n }\n\n return { scenes: emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number): SceneDefinition {\n return {\n name: String(i + 1),\n ppt: {\n src: f.conversionFileUrl,\n width: f.width,\n height: f.height,\n previewURL: f.preview,\n },\n };\n}\n","// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 62; // SOUP.length\nconst ID_LEN = 20;\nconst reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);\n\nexport function genUID() {\n for (let i = 0; i < ID_LEN; i++) {\n reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);\n }\n return reusedIdCarrier.join(\"\");\n}\n","const warnings = {\n \"no-ppt-in-scenes\":\n \"You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`.\",\n} as const;\nconst warned = new Set<string>();\n\nexport function warn(id: keyof typeof warnings) {\n if (warned.has(id)) return;\n warned.add(id);\n console.warn(warnings[id]);\n}\n","import type { AddPageParams, PublicEvent, MountParams, NetlessApp } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n Rectangle,\n Room,\n RoomPhase as RoomPhaseEnum,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore, Storage, Diff, DiffOne } from \"@netless/synced-store\";\n\nimport { DefaultHotKeys, WhiteWebSdk, contentModeScale } from \"white-web-sdk\";\nimport { BuiltinApps, WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport {\n getImageSize,\n genUID,\n convertedFileToScene,\n makeSlideParams,\n readable,\n writable,\n warn,\n} from \"../utils\";\nimport { ensure_official_plugins, transform_app_status } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardAppBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {\n this._assertNotDestroyed();\n this.room.callbacks.on(name, listener);\n return () => this.room.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n /**\n * Destroy fastboard (disconnect from the whiteboard room).\n */\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\ntype RoomPhase = `${RoomPhaseEnum}`;\n\nexport type {\n AddPageParams,\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n MountParams,\n NetlessApp,\n PublicEvent,\n Rectangle,\n Room,\n RoomPhase,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n SyncedStore,\n Storage,\n Diff,\n DiffOne,\n ViewCallbacks,\n WhiteWebSdk,\n WhiteWebSdkConfiguration,\n WindowManager,\n};\n\n/** pencil, eraser, rectangle... */\nexport type Appliance = `${ApplianceNames}`;\n/** triangle, star... */\nexport type Shape = `${ShapeType}`;\n\n/** Params for static docs, they are rendered as many images. */\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** @example [{ name: '1', ppt: { src: 'url/to/ppt/1.png' } }] */\n readonly scenes: SceneDefinition[];\n /** Window title. */\n readonly title?: string;\n}\n\n/** Params for slides, they are rendered in @netless/app-slide with animations. */\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** Conversion task id, see https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress. */\n readonly taskId: string;\n /** Window title. */\n readonly title?: string;\n /** Where the slide resource placed. @default `https://convertcdn.netless.link/dynamicConvert` */\n readonly url?: string;\n /** @example [{ name: '1' }, { name: '2' }, { name: '3' }] */\n readonly scenes?: SceneDefinition[];\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport interface ProjectorResponse {\n uuid: string;\n status: \"Waiting\" | \"Converting\" | \"Finished\" | \"Fail\";\n type: \"dynamic\" | \"static\";\n /** 0..100 */\n convertedPercentage: number;\n /** https://example.org/path/to/dynamicConvert, only when type=dynamic */\n prefix?: string;\n pageCount?: number;\n /** {1:\"{prefix}/{taskId}/preview/1.png\"}, only when type=dynamic and preview=true */\n previews?: Record<number, string>;\n /** {prefix}/{taskId}/jsonOutput/note.json */\n note?: string;\n /** {1:{width,height,url}}, only when type=static */\n images?: Record<number, { width: number; height: number; url: string }>;\n /** 20xxxxx */\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;\n\nexport type RoomStateChanged = (diff: Partial<RoomState>) => void;\n\n/** App download progress. */\nexport interface AppsStatus {\n [kind: string]: {\n status: \"idle\" | \"loading\" | \"failed\";\n /** Exist if status is `failed`. */\n reason?: string;\n };\n}\n\nexport class FastboardApp<TEventData extends Record<string, any> = any> extends FastboardAppBase<TEventData> {\n /**\n * Render this app to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Is current room writable?\n */\n readonly writable = writable(\n this.room.isWritable,\n set => {\n set(this.room.isWritable);\n return this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable));\n },\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Is current room online?\n */\n readonly phase = readable<RoomPhase>(this.room.phase, set => {\n set(this.room.phase);\n return this._addRoomListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = readable(this.manager.boxState, set => {\n set(this.manager.boxState);\n return this._addManagerListener(\"boxStateChange\", set);\n });\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = readable(this.manager.focused, set => {\n set(this.manager.focused);\n return this._addManagerListener(\"focusedChange\", set);\n });\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = readable(this.manager.canRedoSteps, set => {\n set(this.manager.canRedoSteps);\n return this._addManagerListener(\"canRedoStepsChange\", set);\n });\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = readable(this.manager.canUndoSteps, set => {\n set(this.manager.canUndoSteps);\n return this._addManagerListener(\"canUndoStepsChange\", set);\n });\n\n /**\n * Current camera information of main view.\n *\n * Change the camera position by `app.moveCamera()`.\n */\n readonly camera = readable(this.manager.camera, set => {\n set(this.manager.camera);\n return this._addMainViewListener(\"onCameraUpdated\", set);\n });\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n *\n * Change the tool by `app.setAppliance()`.\n */\n readonly memberState = readable(this.room.state.memberState, set => {\n set(this.room.state.memberState);\n return this._addRoomListener(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m));\n });\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = writable(\n this.manager.mainViewSceneIndex,\n set => {\n set(this.manager.mainViewSceneIndex);\n return this._addManagerListener(\"mainViewSceneIndexChange\", set);\n },\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = readable(this.manager.mainViewScenesLength, set => {\n set(this.manager.mainViewScenesLength);\n return this._addManagerListener(\"mainViewScenesLengthChange\", set);\n });\n\n /** @internal */\n private _appsStatus: AppsStatus = {};\n /**\n * Apps status.\n */\n readonly appsStatus = readable<AppsStatus>({}, set =>\n this._addManagerListener(\"loadApp\", ({ kind, status, reason }) => {\n this._appsStatus[kind] = { status: transform_app_status(status), reason };\n set(this._appsStatus);\n })\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.redo();\n }\n\n /**\n * Move current main view's camera position.\n */\n moveCamera(camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }) {\n this._assertNotDestroyed();\n this.manager.moveCamera(camera);\n }\n\n /**\n * Move current main view's camera to include a rectangle.\n */\n moveCameraToContain(rectangle: Rectangle & { animationMode?: AnimationMode }) {\n this._assertNotDestroyed();\n this.manager.moveCameraToContain(rectangle);\n }\n\n /**\n * Delete all things on the main view.\n */\n cleanCurrentScene() {\n this._assertNotDestroyed();\n this.manager.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({\n currentApplianceName: appliance as ApplianceNames,\n shapeType: shape as ShapeType,\n });\n }\n\n /**\n * Set pencil and shape's thickness.\n */\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n /**\n * Set pencil and shape's color.\n */\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Set text size. Default is 16.\n */\n setTextSize(textSize: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textSize });\n }\n\n /**\n * Set text color.\n *\n * @example\n * setTextColor([0x66, 0xcc, 0xff])\n */\n setTextColor(textColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textColor });\n }\n\n /**\n * Goto previous page (the main whiteboard view).\n */\n prevPage() {\n this._assertNotDestroyed();\n return this.manager.prevPage();\n }\n\n /**\n * Goto next page (the main whiteboard view).\n */\n nextPage() {\n this._assertNotDestroyed();\n return this.manager.nextPage();\n }\n\n /**\n * Add one page to the main whiteboard view.\n *\n * @example\n * addPage({ after: true }) // add one page right after current one.\n * nextPage() // then, goto that page.\n */\n addPage(params?: AddPageParams) {\n this._assertNotDestroyed();\n return this.manager.addPage(params);\n }\n\n /**\n * Remove one page at given index or current page (by default).\n *\n * Requires `@netless/window-manager` >= 0.4.30.\n *\n * @example\n * removePage() // remove current page\n */\n removePage(index?: number) {\n this._assertNotDestroyed();\n return this.manager.removePage(index);\n }\n\n /**\n * Insert an image to the main view.\n *\n * @example\n * insertImage(\"https://i.imgur.com/CzXTtJV.jpg\")\n */\n async insertImage(url: string) {\n this._assertNotDestroyed();\n await this.manager.switchMainViewToWriter();\n\n const { divElement } = this.manager.mainView;\n const containerSize = {\n width: divElement?.scrollWidth || window.innerWidth,\n height: divElement?.scrollHeight || window.innerHeight,\n };\n\n // 1. shrink the image a little to fit container **width**\n const maxWidth = containerSize.width * 0.8;\n let { width, height } = await getImageSize(url, containerSize);\n const scale = Math.min(maxWidth / width, 1);\n const uuid = genUID();\n const { centerX, centerY } = this.manager.camera;\n width *= scale;\n height *= scale;\n this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });\n this.manager.mainView.completeImageUpload(uuid, url);\n\n // 2. move camera to fit image **height**\n width /= 0.8;\n height /= 0.8;\n const originX = centerX - width / 2;\n const originY = centerY - height / 2;\n this.manager.moveCameraToContain({ originX, originY, width, height });\n }\n\n /**\n * Insert PDF/PPTX from conversion result.\n * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress\n */\n insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;\n\n /**\n * Insert PDF/PPTX from projector conversion result.\n * @param response https://developer.netless.link/server-zh/home/server-projector#get-%E6%9F%A5%E8%AF%A2%E4%BB%BB%E5%8A%A1%E8%BD%AC%E6%8D%A2%E8%BF%9B%E5%BA%A6\n */\n insertDocs(filename: string, response: ProjectorResponse): Promise<string | undefined>;\n\n /**\n * Manual way.\n * @example\n * app.insertDocs({\n * fileType: 'pptx',\n * scenePath: `/pptx/${conversion.taskId}`,\n * taskId: conversion.taskId,\n * title: 'Title',\n * })\n */\n insertDocs(params: InsertDocsParams): Promise<string | undefined>;\n\n insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse | ProjectorResponse) {\n this._assertNotDestroyed();\n if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"FastboardApp cannot insert a converting doc.\");\n } else if (arg2 && \"progress\" in arg2) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);\n const { scenes, taskId, url } = makeSlideParams(scenes1);\n if (taskId && url) {\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, scenes, title, taskId, url });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes: scenes1, title });\n }\n } else if (arg2 && arg2.prefix) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const taskId = arg2.uuid;\n const url = arg2.prefix;\n this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url });\n } else if (arg2 && arg2.images) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes: SceneDefinition[] = [];\n for (const name in arg2.images) {\n const { width, height, url } = arg2.images[name];\n scenes.push({ name, ppt: { width, height, src: url } });\n }\n this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title });\n } else {\n throw new Error(\"Invalid input: not found 'progress', 'prefix' nor 'images'\");\n }\n }\n\n /** @internal */\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n if (scenes && scenes[0].ppt) {\n warn(\"no-ppt-in-scenes\");\n }\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Media Player app.\n */\n insertMedia(title: string, src: string) {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: BuiltinApps.MediaPlayer,\n options: { title },\n attributes: { src },\n });\n }\n\n /**\n * Insert the Monaco Code Editor app.\n * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.\n */\n insertCodeEditor() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n /**\n * Insert the Countdown app.\n * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.\n */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n /**\n * Insert the GeoGebra app.\n * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<Omit<RoomCallbacks, \"onCanRedoStepsUpdate\" | \"onCanUndoStepsUpdate\">>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardApp instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * joinRoom: {\n * uid: unique_id,\n * uuid: import.meta.env.VITE_ROOM_UUID,\n * roomToken: import.meta.env.VITE_ROOM_TOKEN,\n * },\n * })\n */\nexport async function createFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys = joinRoomParams.hotKeys || {\n ...DefaultHotKeys,\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n };\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensure_official_plugins(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(room);\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n manager.mainView.setCameraBound({\n minContentMode: contentModeScale(0.3),\n maxContentMode: contentModeScale(3),\n });\n\n return new FastboardApp<TEventData>(sdk, room, manager, hotKeys, syncedStore);\n}\n","import type { JoinRoomParams, ReplayRoomParams } from \"white-web-sdk\";\nimport type { PublicEvent } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\n\nexport function ensure_official_plugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n const plugins = new Set(joinRoom.invisiblePlugins || []);\n plugins.add(WindowManager);\n plugins.add(SyncedStorePlugin);\n joinRoom.invisiblePlugins = [...plugins];\n return joinRoom;\n}\n\nexport function transform_app_status(status: PublicEvent[\"loadApp\"][\"status\"]) {\n return status === \"start\" ? \"loading\" : status === \"failed\" ? \"failed\" : \"idle\";\n}\n","import type { RegisterParams } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport SlideApp, { apps, addHooks, previewSlide } from \"@netless/app-slide\";\n\nexport type {\n AppOptions as SlideOptions,\n AppResult as SlideController,\n PreviewParams,\n SlidePreviewer,\n} from \"@netless/app-slide\";\nexport { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };\n\nexport interface AppsConfig {\n [kind: string]: Omit<RegisterParams, \"kind\">;\n}\n\nconst DefaultApps: AppsConfig = {\n Monaco: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js\",\n },\n Countdown: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js\",\n },\n GeoGebra: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n },\n EmbeddedPage: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js\",\n },\n Plyr: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js\",\n },\n};\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: { debug: false },\n src: SlideApp,\n addHooks,\n});\n\nfor (const kind in DefaultApps) {\n if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {\n const options = DefaultApps[kind];\n WindowManager.register({ kind, ...options });\n }\n}\n\nexport const register = WindowManager.register.bind(WindowManager);\n\ndeclare let __NAME__: string, __VERSION__: string;\n\nexport const version = __VERSION__;\n\nif (typeof window !== \"undefined\") {\n let str = (window as { __netlessUA?: string }).__netlessUA || \"\";\n str += ` ${__NAME__}@${version} `;\n (window as { __netlessUA?: string }).__netlessUA = str;\n}\n","import type { MountParams, NetlessApp, PublicEvent } from \"@netless/window-manager\";\nimport type {\n Player,\n PlayerPhase as PlayerPhaseEnum,\n PlayerCallbacks,\n PlayerState,\n PlayerSeekingResult,\n ReplayRoomParams,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore } from \"@netless/synced-store\";\n\nimport { WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport { readable, writable } from \"../utils\";\nimport { ensure_official_plugins } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardPlayerBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly player: Player,\n readonly manager: WindowManager,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {\n this._assertNotDestroyed();\n this.player.callbacks.on(name, listener);\n return () => this.player.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.player.callbacks.off();\n }\n}\n\ntype PlayerPhase = `${PlayerPhaseEnum}`;\n\nexport type { PlayerPhase, PlayerSeekingResult };\n\nexport class FastboardPlayer<\n TEventData extends Record<string, any> = any\n> extends FastboardPlayerBase<TEventData> {\n /**\n * Render this player to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Player current time in milliseconds.\n */\n readonly currentTime = writable(\n this.player.progressTime,\n set => {\n set(this.player.progressTime);\n return this._addPlayerListener(\"onProgressTimeChanged\", set);\n },\n this.player.seekToProgressTime.bind(this.player)\n );\n\n /**\n * Player state, like \"is it playing?\".\n */\n readonly phase = readable<PlayerPhase>(this.player.phase, set => {\n set(this.player.phase);\n return this._addPlayerListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Will become true after buffering.\n */\n readonly canplay = readable(this.player.isPlayable, set => {\n set(this.player.isPlayable);\n return this._addPlayerListener(\"onIsPlayableChanged\", set);\n });\n\n /** @internal */\n private _setPlaybackRate!: (value: number) => void;\n /**\n * Playback speed, default `1`.\n */\n readonly playbackRate = writable(\n this.player.playbackSpeed,\n set => {\n this._setPlaybackRate = set;\n set(this.player.playbackSpeed);\n },\n value => {\n this.player.playbackSpeed = value;\n this._setPlaybackRate(value);\n }\n );\n\n /**\n * Playback duration in milliseconds.\n */\n readonly duration = readable(this.player.timeDuration, set => {\n set(this.player.timeDuration);\n });\n\n /**\n * Get state of room at that time, like \"who was in the room?\".\n */\n readonly state = readable<PlayerState>(this.player.state, set => {\n set(this.player.state);\n return this._addPlayerListener(\"onPlayerStateChanged\", () => set(this.player.state));\n });\n\n /**\n * Seek to some time in milliseconds.\n */\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n /**\n * Change player state to playing.\n */\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n /**\n * Change player state to paused.\n */\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n /**\n * Change player state to stopped.\n */\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n\n /**\n * Set playback speed, a shortcut for `speed.set(x)`.\n */\n setPlaybackRate(value: number) {\n this._assertNotDestroyed();\n this.playbackRate.set(value);\n }\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let player = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * replayRoom: {\n * room: \"room uuid\",\n * roomToken: \"NETLESSROOM_...\",\n * beginTimestamp: 1646619090394,\n * duration: 70448,\n * },\n * })\n */\nexport async function replayFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const player = await sdk.replayRoom(\n {\n ...ensure_official_plugins(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(player);\n\n const managerPromise = WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player,\n });\n\n player.play();\n const manager = await managerPromise;\n player.pause();\n await player.seekToProgressTime(0);\n\n return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);\n}\n","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from \"white-web-sdk\";\n\nexport function addRoomListener<K extends keyof RoomCallbacks>(\n room: Room,\n name: K,\n listener: RoomCallbacks[K]\n) {\n room.callbacks.on(name, listener);\n return () => room.callbacks.off(name, listener);\n}\n\nexport function addPlayerListener<K extends keyof PlayerCallbacks>(\n player: Player,\n name: K,\n listener: PlayerCallbacks[K]\n) {\n player.callbacks.on(name, listener);\n return () => player.callbacks.off(name, listener);\n}\n\nexport function addViewListener<K extends keyof ViewCallbacks>(\n view: View,\n name: K,\n listener: (value: ViewCallbacks[K]) => void\n) {\n view.callbacks.on(name, listener);\n return () => view.callbacks.off(name, listener);\n}\n\nexport function addManagerListener<K extends keyof PublicEvent>(\n manager: WindowManager,\n name: K,\n listener: (value: PublicEvent[K]) => void\n): () => void {\n return manager.emitter.on(name, listener);\n}\n","import type { AppResult } from \"@netless/app-slide\";\nimport type { FastboardApp, WindowManager } from \"../impl\";\n\nexport interface DocsEventOptions {\n /** If provided, will dispatch to the specific app. Default to the focused app. */\n appId?: string;\n /** Used by `jumpToPage` event, range from 1 to total pages count. */\n page?: number;\n}\n\n/**\n * Send specific command to the static docs / slide app.\n * Only works for apps that were created by `insertDocs()`.\n *\n * Returns false if failed to find the app or not writable.\n *\n * For static docs, `nextPage` equals to `nextStep`, as with `prevPage` and `prevStep`.\n *\n * @example\n * ```js\n * // send \"next page\" to the focused app\n * dispatchDocsEvent(fastboard, \"nextPage\")\n *\n * // send \"prev page\" to some app\n * dispatchDocsEvent(fastboard, \"prevPage\", {appId:\"Slide-1a2b3c4d\"})\n * ```\n */\nexport function dispatchDocsEvent(\n fastboard: FastboardApp | WindowManager,\n event: \"prevPage\" | \"nextPage\" | \"prevStep\" | \"nextStep\" | \"jumpToPage\",\n options: DocsEventOptions = {}\n): boolean {\n const manager = \"manager\" in fastboard ? fastboard.manager : fastboard;\n\n const appId = options.appId || manager.focused;\n if (!appId) {\n console.warn(\"not found \" + (options.appId || \"focused app\"));\n return false;\n }\n\n let page: number | undefined, input: HTMLInputElement | null;\n\n // Click the DOM elements for static docs\n if (appId.startsWith(\"DocsViewer-\")) {\n const dom = manager.queryOne(appId)?.box?.$footer;\n if (!dom) {\n console.warn(\"not found app with id \" + appId);\n return false;\n }\n\n const click = (el: Element | null) => {\n el && el.dispatchEvent(new MouseEvent(\"click\"));\n };\n\n switch (event) {\n case \"prevPage\":\n case \"prevStep\":\n click(dom.querySelector('button[class$=\"btn-page-back\"]'));\n break;\n case \"nextPage\":\n case \"nextStep\":\n click(dom.querySelector('button[class$=\"btn-page-next\"]'));\n break;\n case \"jumpToPage\":\n page = options.page;\n input = dom.querySelector('input[class$=\"page-number-input\"]');\n if (!input || typeof page !== \"number\") {\n console.warn(\"failed to jump\" + (page ? \" to page \" + page : \"\"));\n return false;\n }\n input.value = \"\" + page;\n input.dispatchEvent(new InputEvent(\"change\"));\n break;\n default:\n console.warn(\"unknown event \" + event);\n return false;\n }\n\n return true;\n }\n\n // Check controller for slide docs\n else if (appId.startsWith(\"Slide-\")) {\n const app = manager.queryOne(appId)?.appResult as unknown as AppResult | undefined;\n if (!app) {\n console.warn(\"not found app with id \" + appId);\n return false;\n }\n\n switch (event) {\n case \"prevPage\":\n return app.prevPage();\n case \"nextPage\":\n return app.nextPage();\n case \"prevStep\":\n return app.prevStep();\n case \"nextStep\":\n return app.nextStep();\n case \"jumpToPage\":\n page = options.page;\n if (typeof page !== \"number\") {\n console.warn(\"failed to jump\" + (page ? \" to page \" + page : \"\"));\n return false;\n }\n return app.jumpToPage(page);\n default:\n console.warn(\"unknown event \" + event);\n return false;\n }\n }\n\n // No support for any other kind\n else {\n console.warn(\"not supported app \" + appId);\n return false;\n }\n}\n"]}
package/dist/index.mjs CHANGED
@@ -214,7 +214,7 @@ for (const kind in DefaultApps) {
214
214
  }
215
215
  }
216
216
  var register = WindowManager.register.bind(WindowManager);
217
- var version = "0.3.7";
217
+ var version = "0.3.8";
218
218
  if (typeof window !== "undefined") {
219
219
  let str = window.__netlessUA || "";
220
220
  str += ` ${"@netless/fastboard"}@${version} `;
@@ -413,7 +413,7 @@ var FastboardApp = class extends FastboardAppBase {
413
413
  return this._insertDocsImpl(arg1);
414
414
  } else if (arg2 && arg2.status !== "Finished") {
415
415
  throw new Error("FastboardApp cannot insert a converting doc.");
416
- } else if (arg2 && arg2.progress) {
416
+ } else if (arg2 && "progress" in arg2) {
417
417
  const title = arg1;
418
418
  const scenePath = `/${arg2.uuid}/${genUID()}`;
419
419
  const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);
@@ -423,6 +423,23 @@ var FastboardApp = class extends FastboardAppBase {
423
423
  } else {
424
424
  return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes: scenes1, title });
425
425
  }
426
+ } else if (arg2 && arg2.prefix) {
427
+ const title = arg1;
428
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
429
+ const taskId = arg2.uuid;
430
+ const url = arg2.prefix;
431
+ this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url });
432
+ } else if (arg2 && arg2.images) {
433
+ const title = arg1;
434
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
435
+ const scenes = [];
436
+ for (const name in arg2.images) {
437
+ const { width, height, url } = arg2.images[name];
438
+ scenes.push({ name, ppt: { width, height, src: url } });
439
+ }
440
+ this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title });
441
+ } else {
442
+ throw new Error("Invalid input: not found 'progress', 'prefix' nor 'images'");
426
443
  }
427
444
  }
428
445
  _insertDocsImpl(_a) {
@@ -663,7 +680,7 @@ async function replayFastboard(_a) {
663
680
  return new FastboardPlayer(sdk, player, manager, syncedStore);
664
681
  }
665
682
 
666
- // src/helpers/index.ts
683
+ // src/helpers/listen.ts
667
684
  function addRoomListener(room, name, listener) {
668
685
  room.callbacks.on(name, listener);
669
686
  return () => room.callbacks.off(name, listener);
@@ -680,6 +697,81 @@ function addManagerListener(manager, name, listener) {
680
697
  return manager.emitter.on(name, listener);
681
698
  }
682
699
 
683
- export { FastboardApp, FastboardPlayer, addManagerListener, addPlayerListener, addRoomListener, addViewListener, convertedFileToScene, createFastboard, genUID, getImageSize, makeSlideParams, readable, register, replayFastboard, version, warn, writable };
700
+ // src/helpers/docs.ts
701
+ function dispatchDocsEvent(fastboard, event, options = {}) {
702
+ var _a, _b, _c;
703
+ const manager = "manager" in fastboard ? fastboard.manager : fastboard;
704
+ const appId = options.appId || manager.focused;
705
+ if (!appId) {
706
+ console.warn("not found " + (options.appId || "focused app"));
707
+ return false;
708
+ }
709
+ let page, input;
710
+ if (appId.startsWith("DocsViewer-")) {
711
+ const dom = (_b = (_a = manager.queryOne(appId)) == null ? void 0 : _a.box) == null ? void 0 : _b.$footer;
712
+ if (!dom) {
713
+ console.warn("not found app with id " + appId);
714
+ return false;
715
+ }
716
+ const click = (el) => {
717
+ el && el.dispatchEvent(new MouseEvent("click"));
718
+ };
719
+ switch (event) {
720
+ case "prevPage":
721
+ case "prevStep":
722
+ click(dom.querySelector('button[class$="btn-page-back"]'));
723
+ break;
724
+ case "nextPage":
725
+ case "nextStep":
726
+ click(dom.querySelector('button[class$="btn-page-next"]'));
727
+ break;
728
+ case "jumpToPage":
729
+ page = options.page;
730
+ input = dom.querySelector('input[class$="page-number-input"]');
731
+ if (!input || typeof page !== "number") {
732
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
733
+ return false;
734
+ }
735
+ input.value = "" + page;
736
+ input.dispatchEvent(new InputEvent("change"));
737
+ break;
738
+ default:
739
+ console.warn("unknown event " + event);
740
+ return false;
741
+ }
742
+ return true;
743
+ } else if (appId.startsWith("Slide-")) {
744
+ const app = (_c = manager.queryOne(appId)) == null ? void 0 : _c.appResult;
745
+ if (!app) {
746
+ console.warn("not found app with id " + appId);
747
+ return false;
748
+ }
749
+ switch (event) {
750
+ case "prevPage":
751
+ return app.prevPage();
752
+ case "nextPage":
753
+ return app.nextPage();
754
+ case "prevStep":
755
+ return app.prevStep();
756
+ case "nextStep":
757
+ return app.nextStep();
758
+ case "jumpToPage":
759
+ page = options.page;
760
+ if (typeof page !== "number") {
761
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
762
+ return false;
763
+ }
764
+ return app.jumpToPage(page);
765
+ default:
766
+ console.warn("unknown event " + event);
767
+ return false;
768
+ }
769
+ } else {
770
+ console.warn("not supported app " + appId);
771
+ return false;
772
+ }
773
+ }
774
+
775
+ export { FastboardApp, FastboardPlayer, addManagerListener, addPlayerListener, addRoomListener, addViewListener, convertedFileToScene, createFastboard, dispatchDocsEvent, genUID, getImageSize, makeSlideParams, readable, register, replayFastboard, version, warn, writable };
684
776
  //# sourceMappingURL=out.js.map
685
777
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/store.ts","../src/utils/misc.ts","../src/utils/uid.ts","../src/utils/warn.ts","../src/impl/FastboardApp.ts","../src/internal.ts","../src/behaviors/index.ts","../src/impl/FastboardPlayer.ts","../src/helpers/index.ts"],"names":["WindowManager","SyncedStorePlugin","WhiteWebSdk"],"mappings":"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","sourcesContent":["// This is a simple mimic of svelte/store.\nexport type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\nexport type Updater<T> = (value: T) => T;\nexport type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;\n\nexport interface Readable<T> {\n readonly value: T;\n subscribe(this: void, run: Subscriber<T>): Unsubscriber;\n reaction(this: void, run: Subscriber<T>): Unsubscriber;\n}\n\nexport interface Writable<T> extends Readable<T> {\n set(this: void, value: T): void;\n update(this: void, updater: Updater<T>): void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noop() {}\n\nfunction safe_not_equal(a: unknown, b: unknown) {\n return a != a ? b == b : a !== b || (a && typeof a === \"object\") || typeof a === \"function\";\n}\n\nexport function readable<T>(value: T, start: StartStopNotifier<T> = noop): Readable<T> {\n let stop: Unsubscriber | undefined;\n const subscribers = new Set<Subscriber<T>>();\n function set(new_value: T) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) {\n for (const run of subscribers) {\n run(value);\n }\n }\n }\n }\n function subscribe(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n function reaction(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n return {\n get value() {\n return value;\n },\n subscribe,\n reaction,\n };\n}\n\nexport function writable<T>(value: T, start: StartStopNotifier<T> = noop, set: Subscriber<T>): Writable<T> {\n const internal = readable(value, start);\n return {\n get value() {\n return internal.value;\n },\n subscribe: internal.subscribe,\n reaction: internal.reaction,\n set,\n update(fn: Updater<T>) {\n set(fn(value));\n },\n };\n}\n","import type { ConvertedFile, SceneDefinition, Size } from \"white-web-sdk\";\n\nexport function getImageSize(url: string, fallback: Size) {\n return new Promise<Size>(resolve => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => resolve(fallback);\n img.src = url;\n });\n}\n\nexport function makeSlideParams(scenes: SceneDefinition[]) {\n const emptyScenes: SceneDefinition[] = [];\n let taskId = \"\";\n let url = \"\";\n\n // e.g. \"ppt(x)://cdn/prefix/dynamicConvert/{taskId}/1.slide\"\n const pptSrcRE = /^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\//;\n\n for (const { name, ppt } of scenes) {\n // make sure scenesWithoutPPT.length === scenes.length\n emptyScenes.push({ name });\n\n if (!ppt || !ppt.src.startsWith(\"ppt\")) continue;\n\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) continue;\n\n taskId = match.groups.taskId;\n url = `https${match.groups.prefix}`;\n break;\n }\n\n return { scenes: emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number): SceneDefinition {\n return {\n name: String(i + 1),\n ppt: {\n src: f.conversionFileUrl,\n width: f.width,\n height: f.height,\n previewURL: f.preview,\n },\n };\n}\n","// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 62; // SOUP.length\nconst ID_LEN = 20;\nconst reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);\n\nexport function genUID() {\n for (let i = 0; i < ID_LEN; i++) {\n reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);\n }\n return reusedIdCarrier.join(\"\");\n}\n","const warnings = {\n \"no-ppt-in-scenes\":\n \"You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`.\",\n} as const;\nconst warned = new Set<string>();\n\nexport function warn(id: keyof typeof warnings) {\n if (warned.has(id)) return;\n warned.add(id);\n console.warn(warnings[id]);\n}\n","import type { AddPageParams, PublicEvent, MountParams, NetlessApp } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n Rectangle,\n Room,\n RoomPhase as RoomPhaseEnum,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore, Storage, Diff, DiffOne } from \"@netless/synced-store\";\n\nimport { DefaultHotKeys, WhiteWebSdk, contentModeScale } from \"white-web-sdk\";\nimport { BuiltinApps, WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport {\n getImageSize,\n genUID,\n convertedFileToScene,\n makeSlideParams,\n readable,\n writable,\n warn,\n} from \"../utils\";\nimport { ensure_official_plugins, transform_app_status } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardAppBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {\n this._assertNotDestroyed();\n this.room.callbacks.on(name, listener);\n return () => this.room.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n /**\n * Destroy fastboard (disconnect from the whiteboard room).\n */\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\ntype RoomPhase = `${RoomPhaseEnum}`;\n\nexport type {\n AddPageParams,\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n MountParams,\n NetlessApp,\n PublicEvent,\n Rectangle,\n Room,\n RoomPhase,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n SyncedStore,\n Storage,\n Diff,\n DiffOne,\n ViewCallbacks,\n WhiteWebSdk,\n WhiteWebSdkConfiguration,\n WindowManager,\n};\n\n/** pencil, eraser, rectangle... */\nexport type Appliance = `${ApplianceNames}`;\n/** triangle, star... */\nexport type Shape = `${ShapeType}`;\n\n/** Params for static docs, they are rendered as many images. */\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** @example [{ name: '1', ppt: { src: 'url/to/ppt/1.png' } }] */\n readonly scenes: SceneDefinition[];\n /** Window title. */\n readonly title?: string;\n}\n\n/** Params for slides, they are rendered in @netless/app-slide with animations. */\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** Conversion task id, see https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress. */\n readonly taskId: string;\n /** Window title. */\n readonly title?: string;\n /** Where the slide resource placed. @default `https://convertcdn.netless.link/dynamicConvert` */\n readonly url?: string;\n /** @example [{ name: '1' }, { name: '2' }, { name: '3' }] */\n readonly scenes?: SceneDefinition[];\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;\n\nexport type RoomStateChanged = (diff: Partial<RoomState>) => void;\n\n/** App download progress. */\nexport interface AppsStatus {\n [kind: string]: {\n status: \"idle\" | \"loading\" | \"failed\";\n /** Exist if status is `failed`. */\n reason?: string;\n };\n}\n\nexport class FastboardApp<TEventData extends Record<string, any> = any> extends FastboardAppBase<TEventData> {\n /**\n * Render this app to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Is current room writable?\n */\n readonly writable = writable(\n this.room.isWritable,\n set => {\n set(this.room.isWritable);\n return this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable));\n },\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Is current room online?\n */\n readonly phase = readable<RoomPhase>(this.room.phase, set => {\n set(this.room.phase);\n return this._addRoomListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = readable(this.manager.boxState, set => {\n set(this.manager.boxState);\n return this._addManagerListener(\"boxStateChange\", set);\n });\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = readable(this.manager.focused, set => {\n set(this.manager.focused);\n return this._addManagerListener(\"focusedChange\", set);\n });\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = readable(this.manager.canRedoSteps, set => {\n set(this.manager.canRedoSteps);\n return this._addManagerListener(\"canRedoStepsChange\", set);\n });\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = readable(this.manager.canUndoSteps, set => {\n set(this.manager.canUndoSteps);\n return this._addManagerListener(\"canUndoStepsChange\", set);\n });\n\n /**\n * Current camera information of main view.\n *\n * Change the camera position by `app.moveCamera()`.\n */\n readonly camera = readable(this.manager.camera, set => {\n set(this.manager.camera);\n return this._addMainViewListener(\"onCameraUpdated\", set);\n });\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n *\n * Change the tool by `app.setAppliance()`.\n */\n readonly memberState = readable(this.room.state.memberState, set => {\n set(this.room.state.memberState);\n return this._addRoomListener(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m));\n });\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = writable(\n this.manager.mainViewSceneIndex,\n set => {\n set(this.manager.mainViewSceneIndex);\n return this._addManagerListener(\"mainViewSceneIndexChange\", set);\n },\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = readable(this.manager.mainViewScenesLength, set => {\n set(this.manager.mainViewScenesLength);\n return this._addManagerListener(\"mainViewScenesLengthChange\", set);\n });\n\n private _appsStatus: AppsStatus = {};\n /**\n * Apps status.\n */\n readonly appsStatus = readable<AppsStatus>({}, set =>\n this._addManagerListener(\"loadApp\", ({ kind, status, reason }) => {\n this._appsStatus[kind] = { status: transform_app_status(status), reason };\n set(this._appsStatus);\n })\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.redo();\n }\n\n /**\n * Move current main view's camera position.\n */\n moveCamera(camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }) {\n this._assertNotDestroyed();\n this.manager.moveCamera(camera);\n }\n\n /**\n * Move current main view's camera to include a rectangle.\n */\n moveCameraToContain(rectangle: Rectangle & { animationMode?: AnimationMode }) {\n this._assertNotDestroyed();\n this.manager.moveCameraToContain(rectangle);\n }\n\n /**\n * Delete all things on the main view.\n */\n cleanCurrentScene() {\n this._assertNotDestroyed();\n this.manager.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({\n currentApplianceName: appliance as ApplianceNames,\n shapeType: shape as ShapeType,\n });\n }\n\n /**\n * Set pencil and shape's thickness.\n */\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n /**\n * Set pencil and shape's color.\n */\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Set text size. Default is 16.\n */\n setTextSize(textSize: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textSize });\n }\n\n /**\n * Set text color.\n *\n * @example\n * setTextColor([0x66, 0xcc, 0xff])\n */\n setTextColor(textColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textColor });\n }\n\n /**\n * Goto previous page (the main whiteboard view).\n */\n prevPage() {\n this._assertNotDestroyed();\n return this.manager.prevPage();\n }\n\n /**\n * Goto next page (the main whiteboard view).\n */\n nextPage() {\n this._assertNotDestroyed();\n return this.manager.nextPage();\n }\n\n /**\n * Add one page to the main whiteboard view.\n *\n * @example\n * addPage({ after: true }) // add one page right after current one.\n * nextPage() // then, goto that page.\n */\n addPage(params?: AddPageParams) {\n this._assertNotDestroyed();\n return this.manager.addPage(params);\n }\n\n /**\n * Remove one page at given index or current page (by default).\n *\n * Requires `@netless/window-manager` >= 0.4.30.\n *\n * @example\n * removePage() // remove current page\n */\n removePage(index?: number) {\n this._assertNotDestroyed();\n return this.manager.removePage(index);\n }\n\n /**\n * Insert an image to the main view.\n *\n * @example\n * insertImage(\"https://i.imgur.com/CzXTtJV.jpg\")\n */\n async insertImage(url: string) {\n this._assertNotDestroyed();\n await this.manager.switchMainViewToWriter();\n\n const { divElement } = this.manager.mainView;\n const containerSize = {\n width: divElement?.scrollWidth || window.innerWidth,\n height: divElement?.scrollHeight || window.innerHeight,\n };\n\n // 1. shrink the image a little to fit container **width**\n const maxWidth = containerSize.width * 0.8;\n let { width, height } = await getImageSize(url, containerSize);\n const scale = Math.min(maxWidth / width, 1);\n const uuid = genUID();\n const { centerX, centerY } = this.manager.camera;\n width *= scale;\n height *= scale;\n this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });\n this.manager.mainView.completeImageUpload(uuid, url);\n\n // 2. move camera to fit image **height**\n width /= 0.8;\n height /= 0.8;\n const originX = centerX - width / 2;\n const originY = centerY - height / 2;\n this.manager.moveCameraToContain({ originX, originY, width, height });\n }\n\n /**\n * Insert PDF/PPTX from conversion result.\n * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress\n */\n insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;\n\n /**\n * Manual way.\n * @example\n * app.insertDocs({\n * fileType: 'pptx',\n * scenePath: `/pptx/${conversion.taskId}`,\n * taskId: conversion.taskId,\n * title: 'Title',\n * })\n */\n insertDocs(params: InsertDocsParams): Promise<string | undefined>;\n\n insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse) {\n this._assertNotDestroyed();\n if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"FastboardApp cannot insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);\n const { scenes, taskId, url } = makeSlideParams(scenes1);\n if (taskId && url) {\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, scenes, title, taskId, url });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes: scenes1, title });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n if (scenes && scenes[0].ppt) {\n warn(\"no-ppt-in-scenes\");\n }\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Media Player app.\n */\n insertMedia(title: string, src: string) {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: BuiltinApps.MediaPlayer,\n options: { title },\n attributes: { src },\n });\n }\n\n /**\n * Insert the Monaco Code Editor app.\n * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.\n */\n insertCodeEditor() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n /**\n * Insert the Countdown app.\n * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.\n */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n /**\n * Insert the GeoGebra app.\n * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<Omit<RoomCallbacks, \"onCanRedoStepsUpdate\" | \"onCanUndoStepsUpdate\">>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardApp instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * joinRoom: {\n * uid: unique_id,\n * uuid: import.meta.env.VITE_ROOM_UUID,\n * roomToken: import.meta.env.VITE_ROOM_TOKEN,\n * },\n * })\n */\nexport async function createFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys = joinRoomParams.hotKeys || {\n ...DefaultHotKeys,\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n };\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensure_official_plugins(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(room);\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n manager.mainView.setCameraBound({\n minContentMode: contentModeScale(0.3),\n maxContentMode: contentModeScale(3),\n });\n\n return new FastboardApp<TEventData>(sdk, room, manager, hotKeys, syncedStore);\n}\n","import type { JoinRoomParams, ReplayRoomParams } from \"white-web-sdk\";\nimport type { PublicEvent } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\n\nexport function ensure_official_plugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n const plugins = new Set(joinRoom.invisiblePlugins || []);\n plugins.add(WindowManager);\n plugins.add(SyncedStorePlugin);\n joinRoom.invisiblePlugins = [...plugins];\n return joinRoom;\n}\n\nexport function transform_app_status(status: PublicEvent[\"loadApp\"][\"status\"]) {\n return status === \"start\" ? \"loading\" : status === \"failed\" ? \"failed\" : \"idle\";\n}\n","import type { RegisterParams } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport SlideApp, { apps, addHooks, previewSlide } from \"@netless/app-slide\";\n\nexport type {\n AppOptions as SlideOptions,\n Controller as SlideController,\n PreviewParams,\n SlidePreviewer,\n} from \"@netless/app-slide\";\nexport { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };\n\nexport interface AppsConfig {\n [kind: string]: Omit<RegisterParams, \"kind\">;\n}\n\nconst DefaultApps: AppsConfig = {\n Monaco: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js\",\n },\n Countdown: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js\",\n },\n GeoGebra: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n },\n EmbeddedPage: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js\",\n },\n Plyr: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js\",\n },\n};\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: { debug: false },\n src: SlideApp,\n addHooks,\n});\n\nfor (const kind in DefaultApps) {\n if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {\n const options = DefaultApps[kind];\n WindowManager.register({ kind, ...options });\n }\n}\n\nexport const register = WindowManager.register.bind(WindowManager);\n\ndeclare let __NAME__: string, __VERSION__: string;\n\nexport const version = __VERSION__;\n\nif (typeof window !== \"undefined\") {\n let str = (window as { __netlessUA?: string }).__netlessUA || \"\";\n str += ` ${__NAME__}@${version} `;\n (window as { __netlessUA?: string }).__netlessUA = str;\n}\n","import type { MountParams, NetlessApp, PublicEvent } from \"@netless/window-manager\";\nimport type {\n Player,\n PlayerPhase as PlayerPhaseEnum,\n PlayerCallbacks,\n PlayerState,\n PlayerSeekingResult,\n ReplayRoomParams,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore } from \"@netless/synced-store\";\n\nimport { WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport { readable, writable } from \"../utils\";\nimport { ensure_official_plugins } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardPlayerBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly player: Player,\n readonly manager: WindowManager,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {\n this._assertNotDestroyed();\n this.player.callbacks.on(name, listener);\n return () => this.player.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.player.callbacks.off();\n }\n}\n\ntype PlayerPhase = `${PlayerPhaseEnum}`;\n\nexport type { PlayerPhase, PlayerSeekingResult };\n\nexport class FastboardPlayer<\n TEventData extends Record<string, any> = any\n> extends FastboardPlayerBase<TEventData> {\n /**\n * Render this player to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Player current time in milliseconds.\n */\n readonly currentTime = writable(\n this.player.progressTime,\n set => {\n set(this.player.progressTime);\n return this._addPlayerListener(\"onProgressTimeChanged\", set);\n },\n this.player.seekToProgressTime.bind(this.player)\n );\n\n /**\n * Player state, like \"is it playing?\".\n */\n readonly phase = readable<PlayerPhase>(this.player.phase, set => {\n set(this.player.phase);\n return this._addPlayerListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Will become true after buffering.\n */\n readonly canplay = readable(this.player.isPlayable, set => {\n set(this.player.isPlayable);\n return this._addPlayerListener(\"onIsPlayableChanged\", set);\n });\n\n private _setPlaybackRate!: (value: number) => void;\n /**\n * Playback speed, default `1`.\n */\n readonly playbackRate = writable(\n this.player.playbackSpeed,\n set => {\n this._setPlaybackRate = set;\n set(this.player.playbackSpeed);\n },\n value => {\n this.player.playbackSpeed = value;\n this._setPlaybackRate(value);\n }\n );\n\n /**\n * Playback duration in milliseconds.\n */\n readonly duration = readable(this.player.timeDuration, set => {\n set(this.player.timeDuration);\n });\n\n /**\n * Get state of room at that time, like \"who was in the room?\".\n */\n readonly state = readable<PlayerState>(this.player.state, set => {\n set(this.player.state);\n return this._addPlayerListener(\"onPlayerStateChanged\", () => set(this.player.state));\n });\n\n /**\n * Seek to some time in milliseconds.\n */\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n /**\n * Change player state to playing.\n */\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n /**\n * Change player state to paused.\n */\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n /**\n * Change player state to stopped.\n */\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n\n /**\n * Set playback speed, a shortcut for `speed.set(x)`.\n */\n setPlaybackRate(value: number) {\n this._assertNotDestroyed();\n this.playbackRate.set(value);\n }\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let player = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * replayRoom: {\n * room: \"room uuid\",\n * roomToken: \"NETLESSROOM_...\",\n * beginTimestamp: 1646619090394,\n * duration: 70448,\n * },\n * })\n */\nexport async function replayFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const player = await sdk.replayRoom(\n {\n ...ensure_official_plugins(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(player);\n\n const managerPromise = WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player,\n });\n\n player.play();\n const manager = await managerPromise;\n player.pause();\n await player.seekToProgressTime(0);\n\n return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);\n}\n","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from \"white-web-sdk\";\n\nexport function addRoomListener<K extends keyof RoomCallbacks>(\n room: Room,\n name: K,\n listener: RoomCallbacks[K]\n) {\n room.callbacks.on(name, listener);\n return () => room.callbacks.off(name, listener);\n}\n\nexport function addPlayerListener<K extends keyof PlayerCallbacks>(\n player: Player,\n name: K,\n listener: PlayerCallbacks[K]\n) {\n player.callbacks.on(name, listener);\n return () => player.callbacks.off(name, listener);\n}\n\nexport function addViewListener<K extends keyof ViewCallbacks>(\n view: View,\n name: K,\n listener: (value: ViewCallbacks[K]) => void\n) {\n view.callbacks.on(name, listener);\n return () => view.callbacks.off(name, listener);\n}\n\nexport function addManagerListener<K extends keyof PublicEvent>(\n manager: WindowManager,\n name: K,\n listener: (value: PublicEvent[K]) => void\n): () => void {\n return manager.emitter.on(name, listener);\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/store.ts","../src/utils/misc.ts","../src/utils/uid.ts","../src/utils/warn.ts","../src/impl/FastboardApp.ts","../src/internal.ts","../src/behaviors/index.ts","../src/impl/FastboardPlayer.ts","../src/helpers/listen.ts","../src/helpers/docs.ts"],"names":["WindowManager","SyncedStorePlugin","WhiteWebSdk"],"mappings":"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","sourcesContent":["// This is a simple mimic of svelte/store.\nexport type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\nexport type Updater<T> = (value: T) => T;\nexport type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;\n\nexport interface Readable<T> {\n readonly value: T;\n subscribe(this: void, run: Subscriber<T>): Unsubscriber;\n reaction(this: void, run: Subscriber<T>): Unsubscriber;\n}\n\nexport interface Writable<T> extends Readable<T> {\n set(this: void, value: T): void;\n update(this: void, updater: Updater<T>): void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noop() {}\n\nfunction safe_not_equal(a: unknown, b: unknown) {\n return a != a ? b == b : a !== b || (a && typeof a === \"object\") || typeof a === \"function\";\n}\n\nexport function readable<T>(value: T, start: StartStopNotifier<T> = noop): Readable<T> {\n let stop: Unsubscriber | undefined;\n const subscribers = new Set<Subscriber<T>>();\n function set(new_value: T) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) {\n for (const run of subscribers) {\n run(value);\n }\n }\n }\n }\n function subscribe(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n function reaction(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n return {\n get value() {\n return value;\n },\n subscribe,\n reaction,\n };\n}\n\nexport function writable<T>(value: T, start: StartStopNotifier<T> = noop, set: Subscriber<T>): Writable<T> {\n const internal = readable(value, start);\n return {\n get value() {\n return internal.value;\n },\n subscribe: internal.subscribe,\n reaction: internal.reaction,\n set,\n update(fn: Updater<T>) {\n set(fn(value));\n },\n };\n}\n","import type { ConvertedFile, SceneDefinition, Size } from \"white-web-sdk\";\n\nexport function getImageSize(url: string, fallback: Size) {\n return new Promise<Size>(resolve => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => resolve(fallback);\n img.src = url;\n });\n}\n\nexport function makeSlideParams(scenes: SceneDefinition[]) {\n const emptyScenes: SceneDefinition[] = [];\n let taskId = \"\";\n let url = \"\";\n\n // e.g. \"ppt(x)://cdn/prefix/dynamicConvert/{taskId}/1.slide\"\n const pptSrcRE = /^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\//;\n\n for (const { name, ppt } of scenes) {\n // make sure scenesWithoutPPT.length === scenes.length\n emptyScenes.push({ name });\n\n if (!ppt || !ppt.src.startsWith(\"ppt\")) continue;\n\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) continue;\n\n taskId = match.groups.taskId;\n url = `https${match.groups.prefix}`;\n break;\n }\n\n return { scenes: emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number): SceneDefinition {\n return {\n name: String(i + 1),\n ppt: {\n src: f.conversionFileUrl,\n width: f.width,\n height: f.height,\n previewURL: f.preview,\n },\n };\n}\n","// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 62; // SOUP.length\nconst ID_LEN = 20;\nconst reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);\n\nexport function genUID() {\n for (let i = 0; i < ID_LEN; i++) {\n reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);\n }\n return reusedIdCarrier.join(\"\");\n}\n","const warnings = {\n \"no-ppt-in-scenes\":\n \"You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`.\",\n} as const;\nconst warned = new Set<string>();\n\nexport function warn(id: keyof typeof warnings) {\n if (warned.has(id)) return;\n warned.add(id);\n console.warn(warnings[id]);\n}\n","import type { AddPageParams, PublicEvent, MountParams, NetlessApp } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n Rectangle,\n Room,\n RoomPhase as RoomPhaseEnum,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore, Storage, Diff, DiffOne } from \"@netless/synced-store\";\n\nimport { DefaultHotKeys, WhiteWebSdk, contentModeScale } from \"white-web-sdk\";\nimport { BuiltinApps, WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport {\n getImageSize,\n genUID,\n convertedFileToScene,\n makeSlideParams,\n readable,\n writable,\n warn,\n} from \"../utils\";\nimport { ensure_official_plugins, transform_app_status } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardAppBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {\n this._assertNotDestroyed();\n this.room.callbacks.on(name, listener);\n return () => this.room.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n /**\n * Destroy fastboard (disconnect from the whiteboard room).\n */\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\ntype RoomPhase = `${RoomPhaseEnum}`;\n\nexport type {\n AddPageParams,\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n MountParams,\n NetlessApp,\n PublicEvent,\n Rectangle,\n Room,\n RoomPhase,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n SyncedStore,\n Storage,\n Diff,\n DiffOne,\n ViewCallbacks,\n WhiteWebSdk,\n WhiteWebSdkConfiguration,\n WindowManager,\n};\n\n/** pencil, eraser, rectangle... */\nexport type Appliance = `${ApplianceNames}`;\n/** triangle, star... */\nexport type Shape = `${ShapeType}`;\n\n/** Params for static docs, they are rendered as many images. */\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** @example [{ name: '1', ppt: { src: 'url/to/ppt/1.png' } }] */\n readonly scenes: SceneDefinition[];\n /** Window title. */\n readonly title?: string;\n}\n\n/** Params for slides, they are rendered in @netless/app-slide with animations. */\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** Conversion task id, see https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress. */\n readonly taskId: string;\n /** Window title. */\n readonly title?: string;\n /** Where the slide resource placed. @default `https://convertcdn.netless.link/dynamicConvert` */\n readonly url?: string;\n /** @example [{ name: '1' }, { name: '2' }, { name: '3' }] */\n readonly scenes?: SceneDefinition[];\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport interface ProjectorResponse {\n uuid: string;\n status: \"Waiting\" | \"Converting\" | \"Finished\" | \"Fail\";\n type: \"dynamic\" | \"static\";\n /** 0..100 */\n convertedPercentage: number;\n /** https://example.org/path/to/dynamicConvert, only when type=dynamic */\n prefix?: string;\n pageCount?: number;\n /** {1:\"{prefix}/{taskId}/preview/1.png\"}, only when type=dynamic and preview=true */\n previews?: Record<number, string>;\n /** {prefix}/{taskId}/jsonOutput/note.json */\n note?: string;\n /** {1:{width,height,url}}, only when type=static */\n images?: Record<number, { width: number; height: number; url: string }>;\n /** 20xxxxx */\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;\n\nexport type RoomStateChanged = (diff: Partial<RoomState>) => void;\n\n/** App download progress. */\nexport interface AppsStatus {\n [kind: string]: {\n status: \"idle\" | \"loading\" | \"failed\";\n /** Exist if status is `failed`. */\n reason?: string;\n };\n}\n\nexport class FastboardApp<TEventData extends Record<string, any> = any> extends FastboardAppBase<TEventData> {\n /**\n * Render this app to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Is current room writable?\n */\n readonly writable = writable(\n this.room.isWritable,\n set => {\n set(this.room.isWritable);\n return this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable));\n },\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Is current room online?\n */\n readonly phase = readable<RoomPhase>(this.room.phase, set => {\n set(this.room.phase);\n return this._addRoomListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = readable(this.manager.boxState, set => {\n set(this.manager.boxState);\n return this._addManagerListener(\"boxStateChange\", set);\n });\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = readable(this.manager.focused, set => {\n set(this.manager.focused);\n return this._addManagerListener(\"focusedChange\", set);\n });\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = readable(this.manager.canRedoSteps, set => {\n set(this.manager.canRedoSteps);\n return this._addManagerListener(\"canRedoStepsChange\", set);\n });\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = readable(this.manager.canUndoSteps, set => {\n set(this.manager.canUndoSteps);\n return this._addManagerListener(\"canUndoStepsChange\", set);\n });\n\n /**\n * Current camera information of main view.\n *\n * Change the camera position by `app.moveCamera()`.\n */\n readonly camera = readable(this.manager.camera, set => {\n set(this.manager.camera);\n return this._addMainViewListener(\"onCameraUpdated\", set);\n });\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n *\n * Change the tool by `app.setAppliance()`.\n */\n readonly memberState = readable(this.room.state.memberState, set => {\n set(this.room.state.memberState);\n return this._addRoomListener(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m));\n });\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = writable(\n this.manager.mainViewSceneIndex,\n set => {\n set(this.manager.mainViewSceneIndex);\n return this._addManagerListener(\"mainViewSceneIndexChange\", set);\n },\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = readable(this.manager.mainViewScenesLength, set => {\n set(this.manager.mainViewScenesLength);\n return this._addManagerListener(\"mainViewScenesLengthChange\", set);\n });\n\n /** @internal */\n private _appsStatus: AppsStatus = {};\n /**\n * Apps status.\n */\n readonly appsStatus = readable<AppsStatus>({}, set =>\n this._addManagerListener(\"loadApp\", ({ kind, status, reason }) => {\n this._appsStatus[kind] = { status: transform_app_status(status), reason };\n set(this._appsStatus);\n })\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.redo();\n }\n\n /**\n * Move current main view's camera position.\n */\n moveCamera(camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }) {\n this._assertNotDestroyed();\n this.manager.moveCamera(camera);\n }\n\n /**\n * Move current main view's camera to include a rectangle.\n */\n moveCameraToContain(rectangle: Rectangle & { animationMode?: AnimationMode }) {\n this._assertNotDestroyed();\n this.manager.moveCameraToContain(rectangle);\n }\n\n /**\n * Delete all things on the main view.\n */\n cleanCurrentScene() {\n this._assertNotDestroyed();\n this.manager.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({\n currentApplianceName: appliance as ApplianceNames,\n shapeType: shape as ShapeType,\n });\n }\n\n /**\n * Set pencil and shape's thickness.\n */\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n /**\n * Set pencil and shape's color.\n */\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Set text size. Default is 16.\n */\n setTextSize(textSize: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textSize });\n }\n\n /**\n * Set text color.\n *\n * @example\n * setTextColor([0x66, 0xcc, 0xff])\n */\n setTextColor(textColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textColor });\n }\n\n /**\n * Goto previous page (the main whiteboard view).\n */\n prevPage() {\n this._assertNotDestroyed();\n return this.manager.prevPage();\n }\n\n /**\n * Goto next page (the main whiteboard view).\n */\n nextPage() {\n this._assertNotDestroyed();\n return this.manager.nextPage();\n }\n\n /**\n * Add one page to the main whiteboard view.\n *\n * @example\n * addPage({ after: true }) // add one page right after current one.\n * nextPage() // then, goto that page.\n */\n addPage(params?: AddPageParams) {\n this._assertNotDestroyed();\n return this.manager.addPage(params);\n }\n\n /**\n * Remove one page at given index or current page (by default).\n *\n * Requires `@netless/window-manager` >= 0.4.30.\n *\n * @example\n * removePage() // remove current page\n */\n removePage(index?: number) {\n this._assertNotDestroyed();\n return this.manager.removePage(index);\n }\n\n /**\n * Insert an image to the main view.\n *\n * @example\n * insertImage(\"https://i.imgur.com/CzXTtJV.jpg\")\n */\n async insertImage(url: string) {\n this._assertNotDestroyed();\n await this.manager.switchMainViewToWriter();\n\n const { divElement } = this.manager.mainView;\n const containerSize = {\n width: divElement?.scrollWidth || window.innerWidth,\n height: divElement?.scrollHeight || window.innerHeight,\n };\n\n // 1. shrink the image a little to fit container **width**\n const maxWidth = containerSize.width * 0.8;\n let { width, height } = await getImageSize(url, containerSize);\n const scale = Math.min(maxWidth / width, 1);\n const uuid = genUID();\n const { centerX, centerY } = this.manager.camera;\n width *= scale;\n height *= scale;\n this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });\n this.manager.mainView.completeImageUpload(uuid, url);\n\n // 2. move camera to fit image **height**\n width /= 0.8;\n height /= 0.8;\n const originX = centerX - width / 2;\n const originY = centerY - height / 2;\n this.manager.moveCameraToContain({ originX, originY, width, height });\n }\n\n /**\n * Insert PDF/PPTX from conversion result.\n * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress\n */\n insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;\n\n /**\n * Insert PDF/PPTX from projector conversion result.\n * @param response https://developer.netless.link/server-zh/home/server-projector#get-%E6%9F%A5%E8%AF%A2%E4%BB%BB%E5%8A%A1%E8%BD%AC%E6%8D%A2%E8%BF%9B%E5%BA%A6\n */\n insertDocs(filename: string, response: ProjectorResponse): Promise<string | undefined>;\n\n /**\n * Manual way.\n * @example\n * app.insertDocs({\n * fileType: 'pptx',\n * scenePath: `/pptx/${conversion.taskId}`,\n * taskId: conversion.taskId,\n * title: 'Title',\n * })\n */\n insertDocs(params: InsertDocsParams): Promise<string | undefined>;\n\n insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse | ProjectorResponse) {\n this._assertNotDestroyed();\n if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"FastboardApp cannot insert a converting doc.\");\n } else if (arg2 && \"progress\" in arg2) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);\n const { scenes, taskId, url } = makeSlideParams(scenes1);\n if (taskId && url) {\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, scenes, title, taskId, url });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes: scenes1, title });\n }\n } else if (arg2 && arg2.prefix) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const taskId = arg2.uuid;\n const url = arg2.prefix;\n this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url });\n } else if (arg2 && arg2.images) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes: SceneDefinition[] = [];\n for (const name in arg2.images) {\n const { width, height, url } = arg2.images[name];\n scenes.push({ name, ppt: { width, height, src: url } });\n }\n this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title });\n } else {\n throw new Error(\"Invalid input: not found 'progress', 'prefix' nor 'images'\");\n }\n }\n\n /** @internal */\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n if (scenes && scenes[0].ppt) {\n warn(\"no-ppt-in-scenes\");\n }\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Media Player app.\n */\n insertMedia(title: string, src: string) {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: BuiltinApps.MediaPlayer,\n options: { title },\n attributes: { src },\n });\n }\n\n /**\n * Insert the Monaco Code Editor app.\n * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.\n */\n insertCodeEditor() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n /**\n * Insert the Countdown app.\n * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.\n */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n /**\n * Insert the GeoGebra app.\n * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<Omit<RoomCallbacks, \"onCanRedoStepsUpdate\" | \"onCanUndoStepsUpdate\">>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardApp instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * joinRoom: {\n * uid: unique_id,\n * uuid: import.meta.env.VITE_ROOM_UUID,\n * roomToken: import.meta.env.VITE_ROOM_TOKEN,\n * },\n * })\n */\nexport async function createFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys = joinRoomParams.hotKeys || {\n ...DefaultHotKeys,\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n };\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensure_official_plugins(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(room);\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n manager.mainView.setCameraBound({\n minContentMode: contentModeScale(0.3),\n maxContentMode: contentModeScale(3),\n });\n\n return new FastboardApp<TEventData>(sdk, room, manager, hotKeys, syncedStore);\n}\n","import type { JoinRoomParams, ReplayRoomParams } from \"white-web-sdk\";\nimport type { PublicEvent } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\n\nexport function ensure_official_plugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n const plugins = new Set(joinRoom.invisiblePlugins || []);\n plugins.add(WindowManager);\n plugins.add(SyncedStorePlugin);\n joinRoom.invisiblePlugins = [...plugins];\n return joinRoom;\n}\n\nexport function transform_app_status(status: PublicEvent[\"loadApp\"][\"status\"]) {\n return status === \"start\" ? \"loading\" : status === \"failed\" ? \"failed\" : \"idle\";\n}\n","import type { RegisterParams } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport SlideApp, { apps, addHooks, previewSlide } from \"@netless/app-slide\";\n\nexport type {\n AppOptions as SlideOptions,\n AppResult as SlideController,\n PreviewParams,\n SlidePreviewer,\n} from \"@netless/app-slide\";\nexport { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };\n\nexport interface AppsConfig {\n [kind: string]: Omit<RegisterParams, \"kind\">;\n}\n\nconst DefaultApps: AppsConfig = {\n Monaco: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js\",\n },\n Countdown: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js\",\n },\n GeoGebra: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n },\n EmbeddedPage: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js\",\n },\n Plyr: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js\",\n },\n};\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: { debug: false },\n src: SlideApp,\n addHooks,\n});\n\nfor (const kind in DefaultApps) {\n if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {\n const options = DefaultApps[kind];\n WindowManager.register({ kind, ...options });\n }\n}\n\nexport const register = WindowManager.register.bind(WindowManager);\n\ndeclare let __NAME__: string, __VERSION__: string;\n\nexport const version = __VERSION__;\n\nif (typeof window !== \"undefined\") {\n let str = (window as { __netlessUA?: string }).__netlessUA || \"\";\n str += ` ${__NAME__}@${version} `;\n (window as { __netlessUA?: string }).__netlessUA = str;\n}\n","import type { MountParams, NetlessApp, PublicEvent } from \"@netless/window-manager\";\nimport type {\n Player,\n PlayerPhase as PlayerPhaseEnum,\n PlayerCallbacks,\n PlayerState,\n PlayerSeekingResult,\n ReplayRoomParams,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore } from \"@netless/synced-store\";\n\nimport { WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport { readable, writable } from \"../utils\";\nimport { ensure_official_plugins } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardPlayerBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly player: Player,\n readonly manager: WindowManager,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {\n this._assertNotDestroyed();\n this.player.callbacks.on(name, listener);\n return () => this.player.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.player.callbacks.off();\n }\n}\n\ntype PlayerPhase = `${PlayerPhaseEnum}`;\n\nexport type { PlayerPhase, PlayerSeekingResult };\n\nexport class FastboardPlayer<\n TEventData extends Record<string, any> = any\n> extends FastboardPlayerBase<TEventData> {\n /**\n * Render this player to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Player current time in milliseconds.\n */\n readonly currentTime = writable(\n this.player.progressTime,\n set => {\n set(this.player.progressTime);\n return this._addPlayerListener(\"onProgressTimeChanged\", set);\n },\n this.player.seekToProgressTime.bind(this.player)\n );\n\n /**\n * Player state, like \"is it playing?\".\n */\n readonly phase = readable<PlayerPhase>(this.player.phase, set => {\n set(this.player.phase);\n return this._addPlayerListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Will become true after buffering.\n */\n readonly canplay = readable(this.player.isPlayable, set => {\n set(this.player.isPlayable);\n return this._addPlayerListener(\"onIsPlayableChanged\", set);\n });\n\n /** @internal */\n private _setPlaybackRate!: (value: number) => void;\n /**\n * Playback speed, default `1`.\n */\n readonly playbackRate = writable(\n this.player.playbackSpeed,\n set => {\n this._setPlaybackRate = set;\n set(this.player.playbackSpeed);\n },\n value => {\n this.player.playbackSpeed = value;\n this._setPlaybackRate(value);\n }\n );\n\n /**\n * Playback duration in milliseconds.\n */\n readonly duration = readable(this.player.timeDuration, set => {\n set(this.player.timeDuration);\n });\n\n /**\n * Get state of room at that time, like \"who was in the room?\".\n */\n readonly state = readable<PlayerState>(this.player.state, set => {\n set(this.player.state);\n return this._addPlayerListener(\"onPlayerStateChanged\", () => set(this.player.state));\n });\n\n /**\n * Seek to some time in milliseconds.\n */\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n /**\n * Change player state to playing.\n */\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n /**\n * Change player state to paused.\n */\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n /**\n * Change player state to stopped.\n */\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n\n /**\n * Set playback speed, a shortcut for `speed.set(x)`.\n */\n setPlaybackRate(value: number) {\n this._assertNotDestroyed();\n this.playbackRate.set(value);\n }\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let player = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * replayRoom: {\n * room: \"room uuid\",\n * roomToken: \"NETLESSROOM_...\",\n * beginTimestamp: 1646619090394,\n * duration: 70448,\n * },\n * })\n */\nexport async function replayFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const player = await sdk.replayRoom(\n {\n ...ensure_official_plugins(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(player);\n\n const managerPromise = WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player,\n });\n\n player.play();\n const manager = await managerPromise;\n player.pause();\n await player.seekToProgressTime(0);\n\n return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);\n}\n","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from \"white-web-sdk\";\n\nexport function addRoomListener<K extends keyof RoomCallbacks>(\n room: Room,\n name: K,\n listener: RoomCallbacks[K]\n) {\n room.callbacks.on(name, listener);\n return () => room.callbacks.off(name, listener);\n}\n\nexport function addPlayerListener<K extends keyof PlayerCallbacks>(\n player: Player,\n name: K,\n listener: PlayerCallbacks[K]\n) {\n player.callbacks.on(name, listener);\n return () => player.callbacks.off(name, listener);\n}\n\nexport function addViewListener<K extends keyof ViewCallbacks>(\n view: View,\n name: K,\n listener: (value: ViewCallbacks[K]) => void\n) {\n view.callbacks.on(name, listener);\n return () => view.callbacks.off(name, listener);\n}\n\nexport function addManagerListener<K extends keyof PublicEvent>(\n manager: WindowManager,\n name: K,\n listener: (value: PublicEvent[K]) => void\n): () => void {\n return manager.emitter.on(name, listener);\n}\n","import type { AppResult } from \"@netless/app-slide\";\nimport type { FastboardApp, WindowManager } from \"../impl\";\n\nexport interface DocsEventOptions {\n /** If provided, will dispatch to the specific app. Default to the focused app. */\n appId?: string;\n /** Used by `jumpToPage` event, range from 1 to total pages count. */\n page?: number;\n}\n\n/**\n * Send specific command to the static docs / slide app.\n * Only works for apps that were created by `insertDocs()`.\n *\n * Returns false if failed to find the app or not writable.\n *\n * For static docs, `nextPage` equals to `nextStep`, as with `prevPage` and `prevStep`.\n *\n * @example\n * ```js\n * // send \"next page\" to the focused app\n * dispatchDocsEvent(fastboard, \"nextPage\")\n *\n * // send \"prev page\" to some app\n * dispatchDocsEvent(fastboard, \"prevPage\", {appId:\"Slide-1a2b3c4d\"})\n * ```\n */\nexport function dispatchDocsEvent(\n fastboard: FastboardApp | WindowManager,\n event: \"prevPage\" | \"nextPage\" | \"prevStep\" | \"nextStep\" | \"jumpToPage\",\n options: DocsEventOptions = {}\n): boolean {\n const manager = \"manager\" in fastboard ? fastboard.manager : fastboard;\n\n const appId = options.appId || manager.focused;\n if (!appId) {\n console.warn(\"not found \" + (options.appId || \"focused app\"));\n return false;\n }\n\n let page: number | undefined, input: HTMLInputElement | null;\n\n // Click the DOM elements for static docs\n if (appId.startsWith(\"DocsViewer-\")) {\n const dom = manager.queryOne(appId)?.box?.$footer;\n if (!dom) {\n console.warn(\"not found app with id \" + appId);\n return false;\n }\n\n const click = (el: Element | null) => {\n el && el.dispatchEvent(new MouseEvent(\"click\"));\n };\n\n switch (event) {\n case \"prevPage\":\n case \"prevStep\":\n click(dom.querySelector('button[class$=\"btn-page-back\"]'));\n break;\n case \"nextPage\":\n case \"nextStep\":\n click(dom.querySelector('button[class$=\"btn-page-next\"]'));\n break;\n case \"jumpToPage\":\n page = options.page;\n input = dom.querySelector('input[class$=\"page-number-input\"]');\n if (!input || typeof page !== \"number\") {\n console.warn(\"failed to jump\" + (page ? \" to page \" + page : \"\"));\n return false;\n }\n input.value = \"\" + page;\n input.dispatchEvent(new InputEvent(\"change\"));\n break;\n default:\n console.warn(\"unknown event \" + event);\n return false;\n }\n\n return true;\n }\n\n // Check controller for slide docs\n else if (appId.startsWith(\"Slide-\")) {\n const app = manager.queryOne(appId)?.appResult as unknown as AppResult | undefined;\n if (!app) {\n console.warn(\"not found app with id \" + appId);\n return false;\n }\n\n switch (event) {\n case \"prevPage\":\n return app.prevPage();\n case \"nextPage\":\n return app.nextPage();\n case \"prevStep\":\n return app.prevStep();\n case \"nextStep\":\n return app.nextStep();\n case \"jumpToPage\":\n page = options.page;\n if (typeof page !== \"number\") {\n console.warn(\"failed to jump\" + (page ? \" to page \" + page : \"\"));\n return false;\n }\n return app.jumpToPage(page);\n default:\n console.warn(\"unknown event \" + event);\n return false;\n }\n }\n\n // No support for any other kind\n else {\n console.warn(\"not supported app \" + appId);\n return false;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/fastboard-core",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "A tiny wrapper of white-web-sdk and @netless/window-manager.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -9,7 +9,7 @@
9
9
  ],
10
10
  "repository": "netless-io/fastboard",
11
11
  "dependencies": {
12
- "@netless/app-slide": "^0.2.8",
12
+ "@netless/app-slide": "^0.2.28",
13
13
  "@netless/synced-store": "^2.0.7"
14
14
  },
15
15
  "peerDependencies": {
@@ -17,7 +17,7 @@
17
17
  "white-web-sdk": ">=2.16.0"
18
18
  },
19
19
  "devDependencies": {
20
- "white-web-sdk": "^2.16.38"
20
+ "white-web-sdk": "^2.16.40"
21
21
  },
22
22
  "scripts": {
23
23
  "cleanup": "rimraf dist",
@@ -4,7 +4,7 @@ import SlideApp, { apps, addHooks, previewSlide } from "@netless/app-slide";
4
4
 
5
5
  export type {
6
6
  AppOptions as SlideOptions,
7
- Controller as SlideController,
7
+ AppResult as SlideController,
8
8
  PreviewParams,
9
9
  SlidePreviewer,
10
10
  } from "@netless/app-slide";
@@ -0,0 +1,117 @@
1
+ import type { AppResult } from "@netless/app-slide";
2
+ import type { FastboardApp, WindowManager } from "../impl";
3
+
4
+ export interface DocsEventOptions {
5
+ /** If provided, will dispatch to the specific app. Default to the focused app. */
6
+ appId?: string;
7
+ /** Used by `jumpToPage` event, range from 1 to total pages count. */
8
+ page?: number;
9
+ }
10
+
11
+ /**
12
+ * Send specific command to the static docs / slide app.
13
+ * Only works for apps that were created by `insertDocs()`.
14
+ *
15
+ * Returns false if failed to find the app or not writable.
16
+ *
17
+ * For static docs, `nextPage` equals to `nextStep`, as with `prevPage` and `prevStep`.
18
+ *
19
+ * @example
20
+ * ```js
21
+ * // send "next page" to the focused app
22
+ * dispatchDocsEvent(fastboard, "nextPage")
23
+ *
24
+ * // send "prev page" to some app
25
+ * dispatchDocsEvent(fastboard, "prevPage", {appId:"Slide-1a2b3c4d"})
26
+ * ```
27
+ */
28
+ export function dispatchDocsEvent(
29
+ fastboard: FastboardApp | WindowManager,
30
+ event: "prevPage" | "nextPage" | "prevStep" | "nextStep" | "jumpToPage",
31
+ options: DocsEventOptions = {}
32
+ ): boolean {
33
+ const manager = "manager" in fastboard ? fastboard.manager : fastboard;
34
+
35
+ const appId = options.appId || manager.focused;
36
+ if (!appId) {
37
+ console.warn("not found " + (options.appId || "focused app"));
38
+ return false;
39
+ }
40
+
41
+ let page: number | undefined, input: HTMLInputElement | null;
42
+
43
+ // Click the DOM elements for static docs
44
+ if (appId.startsWith("DocsViewer-")) {
45
+ const dom = manager.queryOne(appId)?.box?.$footer;
46
+ if (!dom) {
47
+ console.warn("not found app with id " + appId);
48
+ return false;
49
+ }
50
+
51
+ const click = (el: Element | null) => {
52
+ el && el.dispatchEvent(new MouseEvent("click"));
53
+ };
54
+
55
+ switch (event) {
56
+ case "prevPage":
57
+ case "prevStep":
58
+ click(dom.querySelector('button[class$="btn-page-back"]'));
59
+ break;
60
+ case "nextPage":
61
+ case "nextStep":
62
+ click(dom.querySelector('button[class$="btn-page-next"]'));
63
+ break;
64
+ case "jumpToPage":
65
+ page = options.page;
66
+ input = dom.querySelector('input[class$="page-number-input"]');
67
+ if (!input || typeof page !== "number") {
68
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
69
+ return false;
70
+ }
71
+ input.value = "" + page;
72
+ input.dispatchEvent(new InputEvent("change"));
73
+ break;
74
+ default:
75
+ console.warn("unknown event " + event);
76
+ return false;
77
+ }
78
+
79
+ return true;
80
+ }
81
+
82
+ // Check controller for slide docs
83
+ else if (appId.startsWith("Slide-")) {
84
+ const app = manager.queryOne(appId)?.appResult as unknown as AppResult | undefined;
85
+ if (!app) {
86
+ console.warn("not found app with id " + appId);
87
+ return false;
88
+ }
89
+
90
+ switch (event) {
91
+ case "prevPage":
92
+ return app.prevPage();
93
+ case "nextPage":
94
+ return app.nextPage();
95
+ case "prevStep":
96
+ return app.prevStep();
97
+ case "nextStep":
98
+ return app.nextStep();
99
+ case "jumpToPage":
100
+ page = options.page;
101
+ if (typeof page !== "number") {
102
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
103
+ return false;
104
+ }
105
+ return app.jumpToPage(page);
106
+ default:
107
+ console.warn("unknown event " + event);
108
+ return false;
109
+ }
110
+ }
111
+
112
+ // No support for any other kind
113
+ else {
114
+ console.warn("not supported app " + appId);
115
+ return false;
116
+ }
117
+ }
@@ -1,37 +1,2 @@
1
- import type { PublicEvent, WindowManager } from "@netless/window-manager";
2
- import type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from "white-web-sdk";
3
-
4
- export function addRoomListener<K extends keyof RoomCallbacks>(
5
- room: Room,
6
- name: K,
7
- listener: RoomCallbacks[K]
8
- ) {
9
- room.callbacks.on(name, listener);
10
- return () => room.callbacks.off(name, listener);
11
- }
12
-
13
- export function addPlayerListener<K extends keyof PlayerCallbacks>(
14
- player: Player,
15
- name: K,
16
- listener: PlayerCallbacks[K]
17
- ) {
18
- player.callbacks.on(name, listener);
19
- return () => player.callbacks.off(name, listener);
20
- }
21
-
22
- export function addViewListener<K extends keyof ViewCallbacks>(
23
- view: View,
24
- name: K,
25
- listener: (value: ViewCallbacks[K]) => void
26
- ) {
27
- view.callbacks.on(name, listener);
28
- return () => view.callbacks.off(name, listener);
29
- }
30
-
31
- export function addManagerListener<K extends keyof PublicEvent>(
32
- manager: WindowManager,
33
- name: K,
34
- listener: (value: PublicEvent[K]) => void
35
- ): () => void {
36
- return manager.emitter.on(name, listener);
37
- }
1
+ export * from "./listen";
2
+ export * from "./docs";
@@ -0,0 +1,37 @@
1
+ import type { PublicEvent, WindowManager } from "@netless/window-manager";
2
+ import type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from "white-web-sdk";
3
+
4
+ export function addRoomListener<K extends keyof RoomCallbacks>(
5
+ room: Room,
6
+ name: K,
7
+ listener: RoomCallbacks[K]
8
+ ) {
9
+ room.callbacks.on(name, listener);
10
+ return () => room.callbacks.off(name, listener);
11
+ }
12
+
13
+ export function addPlayerListener<K extends keyof PlayerCallbacks>(
14
+ player: Player,
15
+ name: K,
16
+ listener: PlayerCallbacks[K]
17
+ ) {
18
+ player.callbacks.on(name, listener);
19
+ return () => player.callbacks.off(name, listener);
20
+ }
21
+
22
+ export function addViewListener<K extends keyof ViewCallbacks>(
23
+ view: View,
24
+ name: K,
25
+ listener: (value: ViewCallbacks[K]) => void
26
+ ) {
27
+ view.callbacks.on(name, listener);
28
+ return () => view.callbacks.off(name, listener);
29
+ }
30
+
31
+ export function addManagerListener<K extends keyof PublicEvent>(
32
+ manager: WindowManager,
33
+ name: K,
34
+ listener: (value: PublicEvent[K]) => void
35
+ ): () => void {
36
+ return manager.emitter.on(name, listener);
37
+ }
@@ -149,6 +149,26 @@ export interface InsertDocsDynamic {
149
149
 
150
150
  export type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;
151
151
 
152
+ export interface ProjectorResponse {
153
+ uuid: string;
154
+ status: "Waiting" | "Converting" | "Finished" | "Fail";
155
+ type: "dynamic" | "static";
156
+ /** 0..100 */
157
+ convertedPercentage: number;
158
+ /** https://example.org/path/to/dynamicConvert, only when type=dynamic */
159
+ prefix?: string;
160
+ pageCount?: number;
161
+ /** {1:"{prefix}/{taskId}/preview/1.png"}, only when type=dynamic and preview=true */
162
+ previews?: Record<number, string>;
163
+ /** {prefix}/{taskId}/jsonOutput/note.json */
164
+ note?: string;
165
+ /** {1:{width,height,url}}, only when type=static */
166
+ images?: Record<number, { width: number; height: number; url: string }>;
167
+ /** 20xxxxx */
168
+ errorCode?: string;
169
+ errorMessage?: string;
170
+ }
171
+
152
172
  export type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;
153
173
 
154
174
  export type RoomStateChanged = (diff: Partial<RoomState>) => void;
@@ -272,6 +292,7 @@ export class FastboardApp<TEventData extends Record<string, any> = any> extends
272
292
  return this._addManagerListener("mainViewScenesLengthChange", set);
273
293
  });
274
294
 
295
+ /** @internal */
275
296
  private _appsStatus: AppsStatus = {};
276
297
  /**
277
298
  * Apps status.
@@ -451,6 +472,12 @@ export class FastboardApp<TEventData extends Record<string, any> = any> extends
451
472
  */
452
473
  insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;
453
474
 
475
+ /**
476
+ * Insert PDF/PPTX from projector conversion result.
477
+ * @param response https://developer.netless.link/server-zh/home/server-projector#get-%E6%9F%A5%E8%AF%A2%E4%BB%BB%E5%8A%A1%E8%BD%AC%E6%8D%A2%E8%BF%9B%E5%BA%A6
478
+ */
479
+ insertDocs(filename: string, response: ProjectorResponse): Promise<string | undefined>;
480
+
454
481
  /**
455
482
  * Manual way.
456
483
  * @example
@@ -463,13 +490,13 @@ export class FastboardApp<TEventData extends Record<string, any> = any> extends
463
490
  */
464
491
  insertDocs(params: InsertDocsParams): Promise<string | undefined>;
465
492
 
466
- insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse) {
493
+ insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse | ProjectorResponse) {
467
494
  this._assertNotDestroyed();
468
495
  if (typeof arg1 === "object" && "fileType" in arg1) {
469
496
  return this._insertDocsImpl(arg1);
470
497
  } else if (arg2 && arg2.status !== "Finished") {
471
498
  throw new Error("FastboardApp cannot insert a converting doc.");
472
- } else if (arg2 && arg2.progress) {
499
+ } else if (arg2 && "progress" in arg2) {
473
500
  const title = arg1;
474
501
  const scenePath = `/${arg2.uuid}/${genUID()}`;
475
502
  const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);
@@ -479,9 +506,27 @@ export class FastboardApp<TEventData extends Record<string, any> = any> extends
479
506
  } else {
480
507
  return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes: scenes1, title });
481
508
  }
509
+ } else if (arg2 && arg2.prefix) {
510
+ const title = arg1;
511
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
512
+ const taskId = arg2.uuid;
513
+ const url = arg2.prefix;
514
+ this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url });
515
+ } else if (arg2 && arg2.images) {
516
+ const title = arg1;
517
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
518
+ const scenes: SceneDefinition[] = [];
519
+ for (const name in arg2.images) {
520
+ const { width, height, url } = arg2.images[name];
521
+ scenes.push({ name, ppt: { width, height, src: url } });
522
+ }
523
+ this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title });
524
+ } else {
525
+ throw new Error("Invalid input: not found 'progress', 'prefix' nor 'images'");
482
526
  }
483
527
  }
484
528
 
529
+ /** @internal */
485
530
  private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {
486
531
  this._assertNotDestroyed();
487
532
  switch (fileType) {
@@ -112,6 +112,7 @@ export class FastboardPlayer<
112
112
  return this._addPlayerListener("onIsPlayableChanged", set);
113
113
  });
114
114
 
115
+ /** @internal */
115
116
  private _setPlaybackRate!: (value: number) => void;
116
117
  /**
117
118
  * Playback speed, default `1`.