@netless/fastboard-core 0.2.1 → 0.2.5

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.
@@ -202,10 +202,10 @@ var FastboardApp = class extends FastboardAppBase {
202
202
  this.writable = this.createValue(this.room.isWritable, (set) => this._addRoomListener("onEnableWriteNowChanged", () => set(this.room.isWritable)), this.room.setWritable.bind(this.room));
203
203
  this.boxState = this.createValue(this.manager.boxState, (set) => this._addManagerListener("boxStateChange", set));
204
204
  this.focusedApp = this.createValue(this.manager.focused, (set) => this._addManagerListener("focusedChange", set));
205
- this.canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, (set) => this._addMainViewListener("onCanRedoStepsUpdate", set));
206
- this.canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, (set) => this._addMainViewListener("onCanUndoStepsUpdate", set));
207
- this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set), this.manager.moveCamera.bind(this.manager));
208
- this.memberState = this.createValue(this.room.state.memberState, (set) => this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m)), this.manager.mainView.setMemberState.bind(this.manager.mainView));
205
+ this.canRedoSteps = this.createValue(this.manager.canRedoSteps, (set) => this._addManagerListener("canRedoStepsChange", set));
206
+ this.canUndoSteps = this.createValue(this.manager.canUndoSteps, (set) => this._addManagerListener("canUndoStepsChange", set));
207
+ this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set));
208
+ this.memberState = this.createValue(this.room.state.memberState, (set) => this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m)));
209
209
  this.sceneIndex = this.createValue(this.manager.mainViewSceneIndex, (set) => this._addManagerListener("mainViewSceneIndexChange", set), this.manager.setMainViewSceneIndex.bind(this.manager));
210
210
  this.sceneLength = this.createValue(this.manager.mainViewScenesLength, (set) => this._addManagerListener("mainViewScenesLengthChange", set));
211
211
  }
@@ -235,7 +235,7 @@ var FastboardApp = class extends FastboardAppBase {
235
235
  }
236
236
  cleanCurrentScene() {
237
237
  this._assertNotDestroyed();
238
- this.manager.mainView.cleanCurrentScene();
238
+ this.manager.cleanCurrentScene();
239
239
  }
240
240
  setAppliance(appliance, shape) {
241
241
  this._assertNotDestroyed();
@@ -488,4 +488,4 @@ export {
488
488
  createFastboard,
489
489
  replayFastboard
490
490
  };
491
- //# sourceMappingURL=chunk-QSMPKHJQ.mjs.map
491
+ //# sourceMappingURL=chunk-EFXKTCHG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/minimal.ts","../src/behaviors/register-apps.ts","../src/helpers/utils.ts","../src/impl/app.ts","../src/helpers/emitter.ts","../src/helpers/value.ts","../src/impl/player.ts"],"sourcesContent":["import type {\n Displayer,\n HotKeys,\n JoinRoomParams,\n PlayerCallbacks,\n ReplayRoomParams,\n Room,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { MountParams } from \"@netless/window-manager\";\n\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport { ensureWindowManager } from \"./helpers/utils\";\nimport { FastboardApp } from \"./impl/app\";\nimport { FastboardPlayer } from \"./impl/player\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./helpers/value\";\n\nexport type { FastboardApp };\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\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 * },\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({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys: Partial<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 const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensureWindowManager(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n return new FastboardApp(sdk, room, manager, hotKeys);\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let app = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * },\n * replayRoom: {\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 replayFastboard({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const player = await sdk.replayRoom(\n {\n ...ensureWindowManager(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player as Displayer as Room,\n });\n\n return new FastboardPlayer(sdk, player, manager);\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Monaco\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"Countdown\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"GeoGebra\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-geogebra@latest/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","import type { ConvertedFile, JoinRoomParams, ReplayRoomParams, SceneDefinition, Size } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nexport function noop() {\n /* noop */\n}\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\")) {\n continue;\n }\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) {\n continue;\n }\n taskId = match.groups.taskId;\n url = \"https\" + match.groups.prefix;\n break;\n }\n\n return { emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number) {\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\nexport function ensureWindowManager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {\n joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];\n }\n return joinRoom;\n}\n\n// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"!#%()*+,-./:;=?@[]^_`{|}~\" + \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 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","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKeys,\n MemberState,\n Rectangle,\n Room,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdk,\n} from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"../helpers/utils\";\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardAppBase {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>\n ) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardApp] Can not call any method on destroyed FastboardApp.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\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\nexport class FastboardApp extends FastboardAppBase {\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 = this.createValue(\n this.room.isWritable,\n set => this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable)),\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = this.createValue(this.manager.boxState, set =>\n this._addManagerListener(\"boxStateChange\", set)\n );\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = this.createValue(this.manager.focused, set =>\n this._addManagerListener(\"focusedChange\", set)\n );\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = this.createValue(this.manager.canRedoSteps, set =>\n this._addManagerListener(\"canRedoStepsChange\", set)\n );\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = this.createValue(this.manager.canUndoSteps, set =>\n this._addManagerListener(\"canUndoStepsChange\", set)\n );\n\n /**\n * Current camera information of main view.\n */\n readonly camera = this.createValue(this.manager.mainView.camera, set =>\n this._addMainViewListener(\"onCameraUpdated\", set)\n );\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n */\n readonly memberState = this.createValue(this.room.state.memberState, set =>\n 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 = this.createValue(\n this.manager.mainViewSceneIndex,\n set => this._addManagerListener(\"mainViewSceneIndexChange\", set),\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>\n this._addManagerListener(\"mainViewScenesLengthChange\", set)\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.mainView.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.mainView.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, shape?: ShapeType) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });\n }\n\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Insert an image to the main view.\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 if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"[FastboardApp] Can not insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const { emptyScenes, taskId, url } = makeSlideParams(scenes);\n if (taskId && url) {\n const title = arg1;\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url, scenes: emptyScenes });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title: arg1 });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Monaco Code Editor app.\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 */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\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 GeoGebra app.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n","export type FastboardListener<T> = (event: T) => void;\n\nexport class FastboardEmitter<T> {\n listeners = new Set<FastboardListener<T>>();\n\n get length(): number {\n return this.listeners.size;\n }\n\n dispatch(message: T) {\n this.listeners.forEach(callback => callback(message));\n }\n\n addListener(listener: FastboardListener<T>) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: FastboardListener<T>) {\n this.listeners.delete(listener);\n }\n}\n","import { FastboardEmitter } from \"./emitter\";\nimport { noop } from \"./utils\";\n\nexport type FastboardDisposer = () => void;\n\nexport interface FastboardReadable<T> {\n readonly value: T;\n subscribe(callback: (value: T) => void): FastboardDisposer;\n reaction(callback: (value: T) => void): FastboardDisposer;\n}\n\nexport interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {\n setValue: SetFn;\n}\n\nexport interface FastboardInternalValue<T> extends FastboardWritable<T> {\n dispose: FastboardDisposer;\n}\n\n/**\n * Create a readonly, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * })\n */\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void\n): FastboardReadable<T>;\n\n/**\n * Create a writable, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * }, (newValue) => {\n * manager.setMainViewSceneIndex(newValue)\n * })\n */\nexport function createValue<T, SetFn = (value: T) => void>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n set: (value: T) => void\n): FastboardWritable<T, SetFn>;\n\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n setValue: (value: T) => void = noop\n): FastboardInternalValue<T> {\n const emitter = new FastboardEmitter<T>();\n\n function set(newValue: T) {\n emitter.dispatch((value = newValue));\n }\n\n const dispose = effect(set) || noop;\n\n function subscribe(callback: (value: T) => void) {\n emitter.addListener(callback);\n callback(value);\n return () => emitter.removeListener(callback);\n }\n\n function reaction(callback: (value: T) => void) {\n emitter.addListener(callback);\n return () => emitter.removeListener(callback);\n }\n\n return { value, subscribe, reaction, setValue, dispose };\n}\n","import type { Player, PlayerCallbacks, PlayerState, ViewCallbacks, WhiteWebSdk } from \"white-web-sdk\";\nimport type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardPlayerBase {\n public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardPlayer] Can not call any method on destroyed FastboardPlayer.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks, T = PlayerCallbacks[K]>(\n name: K,\n listener: T\n ) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n this.player.callbacks.off();\n }\n}\n\nexport class FastboardPlayer extends FastboardPlayerBase {\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 readonly currentTime = this.createValue(\n this.player.progressTime,\n set => this._addPlayerListener(\"onProgressTimeChanged\", set),\n this.player.seekToProgressTime.bind(this.player)\n );\n\n readonly phase = this.createValue(this.player.phase, set => this._addPlayerListener(\"onPhaseChanged\", set));\n\n readonly canplay = this.createValue(this.player.isPlayable, set =>\n this._addPlayerListener(\"onIsPlayableChanged\", set)\n );\n\n private _setSpeed!: (value: number) => void;\n readonly speed = this.createValue(\n this.player.playbackSpeed,\n set => {\n this._setSpeed = set;\n },\n value => {\n this.player.playbackSpeed = value;\n this._setSpeed(value);\n }\n );\n\n readonly state = this.createValue<PlayerState | null>(null, set => {\n const update = () => set(this.player.state);\n const dispose1 = this._addPlayerListener(\"onLoadFirstFrame\", update);\n const dispose2 = this._addPlayerListener(\"onPlayerStateChanged\", update);\n return () => (dispose1(), dispose2());\n });\n\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -245,10 +245,10 @@ var FastboardApp = class extends FastboardAppBase {
245
245
  this.writable = this.createValue(this.room.isWritable, (set) => this._addRoomListener("onEnableWriteNowChanged", () => set(this.room.isWritable)), this.room.setWritable.bind(this.room));
246
246
  this.boxState = this.createValue(this.manager.boxState, (set) => this._addManagerListener("boxStateChange", set));
247
247
  this.focusedApp = this.createValue(this.manager.focused, (set) => this._addManagerListener("focusedChange", set));
248
- this.canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, (set) => this._addMainViewListener("onCanRedoStepsUpdate", set));
249
- this.canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, (set) => this._addMainViewListener("onCanUndoStepsUpdate", set));
250
- this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set), this.manager.moveCamera.bind(this.manager));
251
- this.memberState = this.createValue(this.room.state.memberState, (set) => this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m)), this.manager.mainView.setMemberState.bind(this.manager.mainView));
248
+ this.canRedoSteps = this.createValue(this.manager.canRedoSteps, (set) => this._addManagerListener("canRedoStepsChange", set));
249
+ this.canUndoSteps = this.createValue(this.manager.canUndoSteps, (set) => this._addManagerListener("canUndoStepsChange", set));
250
+ this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set));
251
+ this.memberState = this.createValue(this.room.state.memberState, (set) => this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m)));
252
252
  this.sceneIndex = this.createValue(this.manager.mainViewSceneIndex, (set) => this._addManagerListener("mainViewSceneIndexChange", set), this.manager.setMainViewSceneIndex.bind(this.manager));
253
253
  this.sceneLength = this.createValue(this.manager.mainViewScenesLength, (set) => this._addManagerListener("mainViewScenesLengthChange", set));
254
254
  }
@@ -278,7 +278,7 @@ var FastboardApp = class extends FastboardAppBase {
278
278
  }
279
279
  cleanCurrentScene() {
280
280
  this._assertNotDestroyed();
281
- this.manager.mainView.cleanCurrentScene();
281
+ this.manager.cleanCurrentScene();
282
282
  }
283
283
  setAppliance(appliance, shape) {
284
284
  this._assertNotDestroyed();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/behaviors/register-slide.ts","../src/minimal.ts","../src/behaviors/register-apps.ts","../src/helpers/utils.ts","../src/impl/app.ts","../src/helpers/emitter.ts","../src/helpers/value.ts","../src/impl/player.ts"],"sourcesContent":["import \"./behaviors/register-slide\";\n\nexport * from \"./minimal\";\n","import { WindowManager } from \"@netless/window-manager\";\nimport AppSlide from \"@netless/app-slide\";\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: {\n // turn on to show debug controller\n debug: false,\n },\n src: AppSlide,\n});\n","import type {\n Displayer,\n HotKeys,\n JoinRoomParams,\n PlayerCallbacks,\n ReplayRoomParams,\n Room,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { MountParams } from \"@netless/window-manager\";\n\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport { ensureWindowManager } from \"./helpers/utils\";\nimport { FastboardApp } from \"./impl/app\";\nimport { FastboardPlayer } from \"./impl/player\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./helpers/value\";\n\nexport type { FastboardApp };\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\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 * },\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({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys: Partial<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 const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensureWindowManager(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n return new FastboardApp(sdk, room, manager, hotKeys);\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\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 replayFastboard({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const player = await sdk.replayRoom(\n {\n ...ensureWindowManager(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player as Displayer as Room,\n });\n\n return new FastboardPlayer(sdk, player, manager);\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Monaco\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"Countdown\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"GeoGebra\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-geogebra@latest/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","import type { ConvertedFile, JoinRoomParams, ReplayRoomParams, SceneDefinition, Size } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nexport function noop() {\n /* noop */\n}\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\")) {\n continue;\n }\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) {\n continue;\n }\n taskId = match.groups.taskId;\n url = \"https\" + match.groups.prefix;\n break;\n }\n\n return { emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number) {\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\nexport function ensureWindowManager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {\n joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];\n }\n return joinRoom;\n}\n\n// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"!#%()*+,-./:;=?@[]^_`{|}~\" + \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 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","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKeys,\n MemberState,\n Rectangle,\n Room,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdk,\n} from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"../helpers/utils\";\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardAppBase {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>\n ) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardApp] Can not call any method on destroyed FastboardApp.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\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\nexport class FastboardApp extends FastboardAppBase {\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 = this.createValue(\n this.room.isWritable,\n set => this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable)),\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = this.createValue(this.manager.boxState, set =>\n this._addManagerListener(\"boxStateChange\", set)\n );\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = this.createValue(this.manager.focused, set =>\n this._addManagerListener(\"focusedChange\", set)\n );\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, set =>\n this._addMainViewListener(\"onCanRedoStepsUpdate\", set)\n );\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, set =>\n this._addMainViewListener(\"onCanUndoStepsUpdate\", set)\n );\n\n /**\n * Current camera information of main view.\n */\n readonly camera = this.createValue(\n this.manager.mainView.camera,\n set => this._addMainViewListener(\"onCameraUpdated\", set),\n this.manager.moveCamera.bind(this.manager)\n );\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n */\n readonly memberState = this.createValue<MemberState, SetMemberStateFn>(\n this.room.state.memberState,\n set =>\n this._addRoomListener<\"onRoomStateChanged\", RoomStateChanged>(\n \"onRoomStateChanged\",\n ({ memberState: m }) => m && set(m)\n ),\n this.manager.mainView.setMemberState.bind(this.manager.mainView)\n );\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = this.createValue(\n this.manager.mainViewSceneIndex,\n set => this._addManagerListener(\"mainViewSceneIndexChange\", set),\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>\n this._addManagerListener(\"mainViewScenesLengthChange\", set)\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.mainView.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.mainView.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.mainView.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames, shape?: ShapeType) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });\n }\n\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Insert an image to the main view.\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 if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"[FastboardApp] Can not insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const { emptyScenes, taskId, url } = makeSlideParams(scenes);\n if (taskId && url) {\n const title = arg1;\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url, scenes: emptyScenes });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title: arg1 });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Monaco Code Editor app.\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 */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\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 GeoGebra app.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n","export type FastboardListener<T> = (event: T) => void;\n\nexport class FastboardEmitter<T> {\n listeners = new Set<FastboardListener<T>>();\n\n get length(): number {\n return this.listeners.size;\n }\n\n dispatch(message: T) {\n this.listeners.forEach(callback => callback(message));\n }\n\n addListener(listener: FastboardListener<T>) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: FastboardListener<T>) {\n this.listeners.delete(listener);\n }\n}\n","import { FastboardEmitter } from \"./emitter\";\nimport { noop } from \"./utils\";\n\nexport type FastboardDisposer = () => void;\n\nexport interface FastboardReadable<T> {\n readonly value: T;\n subscribe(callback: (value: T) => void): FastboardDisposer;\n reaction(callback: (value: T) => void): FastboardDisposer;\n}\n\nexport interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {\n setValue: SetFn;\n}\n\nexport interface FastboardInternalValue<T> extends FastboardWritable<T> {\n dispose: FastboardDisposer;\n}\n\n/**\n * Create a readonly, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * })\n */\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void\n): FastboardReadable<T>;\n\n/**\n * Create a writable, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * }, (newValue) => {\n * manager.setMainViewSceneIndex(newValue)\n * })\n */\nexport function createValue<T, SetFn = (value: T) => void>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n set: (value: T) => void\n): FastboardWritable<T, SetFn>;\n\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n setValue: (value: T) => void = noop\n): FastboardInternalValue<T> {\n const emitter = new FastboardEmitter<T>();\n\n function set(newValue: T) {\n emitter.dispatch((value = newValue));\n }\n\n const dispose = effect(set) || noop;\n\n function subscribe(callback: (value: T) => void) {\n emitter.addListener(callback);\n callback(value);\n return () => emitter.removeListener(callback);\n }\n\n function reaction(callback: (value: T) => void) {\n emitter.addListener(callback);\n return () => emitter.removeListener(callback);\n }\n\n return { value, subscribe, reaction, setValue, dispose };\n}\n","import type { Player, PlayerCallbacks, PlayerState, ViewCallbacks, WhiteWebSdk } from \"white-web-sdk\";\nimport type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardPlayerBase {\n public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardPlayer] Can not call any method on destroyed FastboardPlayer.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks, T = PlayerCallbacks[K]>(\n name: K,\n listener: T\n ) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n this.player.callbacks.off();\n }\n}\n\nexport class FastboardPlayer extends FastboardPlayerBase {\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 readonly currentTime = this.createValue(\n this.player.progressTime,\n set => this._addPlayerListener(\"onProgressTimeChanged\", set),\n this.player.seekToProgressTime.bind(this.player)\n );\n\n readonly phase = this.createValue(this.player.phase, set => this._addPlayerListener(\"onPhaseChanged\", set));\n\n readonly canplay = this.createValue(this.player.isPlayable, set =>\n this._addPlayerListener(\"onIsPlayableChanged\", set)\n );\n\n private _setSpeed!: (value: number) => void;\n readonly speed = this.createValue(\n this.player.playbackSpeed,\n set => {\n this._setSpeed = set;\n },\n value => {\n this.player.playbackSpeed = value;\n this._setSpeed(value);\n }\n );\n\n readonly state = this.createValue<PlayerState | null>(null, set => {\n const update = () => set(this.player.state);\n const dispose1 = this._addPlayerListener(\"onLoadFirstFrame\", update);\n const dispose2 = this._addPlayerListener(\"onPlayerStateChanged\", update);\n return () => (dispose1(), dispose2());\n });\n\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/behaviors/register-slide.ts","../src/minimal.ts","../src/behaviors/register-apps.ts","../src/helpers/utils.ts","../src/impl/app.ts","../src/helpers/emitter.ts","../src/helpers/value.ts","../src/impl/player.ts"],"sourcesContent":["import \"./behaviors/register-slide\";\n\nexport * from \"./minimal\";\n","import { WindowManager } from \"@netless/window-manager\";\nimport AppSlide from \"@netless/app-slide\";\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: {\n // turn on to show debug controller\n debug: false,\n },\n src: AppSlide,\n});\n","import type {\n Displayer,\n HotKeys,\n JoinRoomParams,\n PlayerCallbacks,\n ReplayRoomParams,\n Room,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { MountParams } from \"@netless/window-manager\";\n\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport { ensureWindowManager } from \"./helpers/utils\";\nimport { FastboardApp } from \"./impl/app\";\nimport { FastboardPlayer } from \"./impl/player\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./helpers/value\";\n\nexport type { FastboardApp };\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\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 * },\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({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys: Partial<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 const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensureWindowManager(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n return new FastboardApp(sdk, room, manager, hotKeys);\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let app = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * },\n * replayRoom: {\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 replayFastboard({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const player = await sdk.replayRoom(\n {\n ...ensureWindowManager(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player as Displayer as Room,\n });\n\n return new FastboardPlayer(sdk, player, manager);\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Monaco\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"Countdown\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"GeoGebra\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-geogebra@latest/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","import type { ConvertedFile, JoinRoomParams, ReplayRoomParams, SceneDefinition, Size } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nexport function noop() {\n /* noop */\n}\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\")) {\n continue;\n }\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) {\n continue;\n }\n taskId = match.groups.taskId;\n url = \"https\" + match.groups.prefix;\n break;\n }\n\n return { emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number) {\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\nexport function ensureWindowManager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {\n joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];\n }\n return joinRoom;\n}\n\n// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"!#%()*+,-./:;=?@[]^_`{|}~\" + \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 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","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKeys,\n MemberState,\n Rectangle,\n Room,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdk,\n} from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"../helpers/utils\";\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardAppBase {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>\n ) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardApp] Can not call any method on destroyed FastboardApp.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\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\nexport class FastboardApp extends FastboardAppBase {\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 = this.createValue(\n this.room.isWritable,\n set => this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable)),\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = this.createValue(this.manager.boxState, set =>\n this._addManagerListener(\"boxStateChange\", set)\n );\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = this.createValue(this.manager.focused, set =>\n this._addManagerListener(\"focusedChange\", set)\n );\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = this.createValue(this.manager.canRedoSteps, set =>\n this._addManagerListener(\"canRedoStepsChange\", set)\n );\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = this.createValue(this.manager.canUndoSteps, set =>\n this._addManagerListener(\"canUndoStepsChange\", set)\n );\n\n /**\n * Current camera information of main view.\n */\n readonly camera = this.createValue(this.manager.mainView.camera, set =>\n this._addMainViewListener(\"onCameraUpdated\", set)\n );\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n */\n readonly memberState = this.createValue(this.room.state.memberState, set =>\n 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 = this.createValue(\n this.manager.mainViewSceneIndex,\n set => this._addManagerListener(\"mainViewSceneIndexChange\", set),\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>\n this._addManagerListener(\"mainViewScenesLengthChange\", set)\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.mainView.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.mainView.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, shape?: ShapeType) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });\n }\n\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Insert an image to the main view.\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 if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"[FastboardApp] Can not insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const { emptyScenes, taskId, url } = makeSlideParams(scenes);\n if (taskId && url) {\n const title = arg1;\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url, scenes: emptyScenes });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title: arg1 });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Monaco Code Editor app.\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 */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\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 GeoGebra app.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n","export type FastboardListener<T> = (event: T) => void;\n\nexport class FastboardEmitter<T> {\n listeners = new Set<FastboardListener<T>>();\n\n get length(): number {\n return this.listeners.size;\n }\n\n dispatch(message: T) {\n this.listeners.forEach(callback => callback(message));\n }\n\n addListener(listener: FastboardListener<T>) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: FastboardListener<T>) {\n this.listeners.delete(listener);\n }\n}\n","import { FastboardEmitter } from \"./emitter\";\nimport { noop } from \"./utils\";\n\nexport type FastboardDisposer = () => void;\n\nexport interface FastboardReadable<T> {\n readonly value: T;\n subscribe(callback: (value: T) => void): FastboardDisposer;\n reaction(callback: (value: T) => void): FastboardDisposer;\n}\n\nexport interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {\n setValue: SetFn;\n}\n\nexport interface FastboardInternalValue<T> extends FastboardWritable<T> {\n dispose: FastboardDisposer;\n}\n\n/**\n * Create a readonly, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * })\n */\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void\n): FastboardReadable<T>;\n\n/**\n * Create a writable, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * }, (newValue) => {\n * manager.setMainViewSceneIndex(newValue)\n * })\n */\nexport function createValue<T, SetFn = (value: T) => void>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n set: (value: T) => void\n): FastboardWritable<T, SetFn>;\n\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n setValue: (value: T) => void = noop\n): FastboardInternalValue<T> {\n const emitter = new FastboardEmitter<T>();\n\n function set(newValue: T) {\n emitter.dispatch((value = newValue));\n }\n\n const dispose = effect(set) || noop;\n\n function subscribe(callback: (value: T) => void) {\n emitter.addListener(callback);\n callback(value);\n return () => emitter.removeListener(callback);\n }\n\n function reaction(callback: (value: T) => void) {\n emitter.addListener(callback);\n return () => emitter.removeListener(callback);\n }\n\n return { value, subscribe, reaction, setValue, dispose };\n}\n","import type { Player, PlayerCallbacks, PlayerState, ViewCallbacks, WhiteWebSdk } from \"white-web-sdk\";\nimport type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardPlayerBase {\n public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardPlayer] Can not call any method on destroyed FastboardPlayer.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks, T = PlayerCallbacks[K]>(\n name: K,\n listener: T\n ) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n this.player.callbacks.off();\n }\n}\n\nexport class FastboardPlayer extends FastboardPlayerBase {\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 readonly currentTime = this.createValue(\n this.player.progressTime,\n set => this._addPlayerListener(\"onProgressTimeChanged\", set),\n this.player.seekToProgressTime.bind(this.player)\n );\n\n readonly phase = this.createValue(this.player.phase, set => this._addPlayerListener(\"onPhaseChanged\", set));\n\n readonly canplay = this.createValue(this.player.isPlayable, set =>\n this._addPlayerListener(\"onIsPlayableChanged\", set)\n );\n\n private _setSpeed!: (value: number) => void;\n readonly speed = this.createValue(\n this.player.playbackSpeed,\n set => {\n this._setSpeed = set;\n },\n value => {\n this.player.playbackSpeed = value;\n this._setSpeed(value);\n }\n );\n\n readonly state = this.createValue<PlayerState | null>(null, set => {\n const update = () => set(this.player.state);\n const dispose1 = this._addPlayerListener(\"onLoadFirstFrame\", update);\n const dispose2 = this._addPlayerListener(\"onPlayerStateChanged\", update);\n return () => (dispose1(), dispose2());\n });\n\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createFastboard,
3
3
  replayFastboard
4
- } from "./chunk-QSMPKHJQ.mjs";
4
+ } from "./chunk-EFXKTCHG.mjs";
5
5
 
6
6
  // src/behaviors/register-slide.ts
7
7
  import { WindowManager } from "@netless/window-manager";
package/dist/minimal.js CHANGED
@@ -227,10 +227,10 @@ var FastboardApp = class extends FastboardAppBase {
227
227
  this.writable = this.createValue(this.room.isWritable, (set) => this._addRoomListener("onEnableWriteNowChanged", () => set(this.room.isWritable)), this.room.setWritable.bind(this.room));
228
228
  this.boxState = this.createValue(this.manager.boxState, (set) => this._addManagerListener("boxStateChange", set));
229
229
  this.focusedApp = this.createValue(this.manager.focused, (set) => this._addManagerListener("focusedChange", set));
230
- this.canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, (set) => this._addMainViewListener("onCanRedoStepsUpdate", set));
231
- this.canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, (set) => this._addMainViewListener("onCanUndoStepsUpdate", set));
232
- this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set), this.manager.moveCamera.bind(this.manager));
233
- this.memberState = this.createValue(this.room.state.memberState, (set) => this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m)), this.manager.mainView.setMemberState.bind(this.manager.mainView));
230
+ this.canRedoSteps = this.createValue(this.manager.canRedoSteps, (set) => this._addManagerListener("canRedoStepsChange", set));
231
+ this.canUndoSteps = this.createValue(this.manager.canUndoSteps, (set) => this._addManagerListener("canUndoStepsChange", set));
232
+ this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set));
233
+ this.memberState = this.createValue(this.room.state.memberState, (set) => this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m)));
234
234
  this.sceneIndex = this.createValue(this.manager.mainViewSceneIndex, (set) => this._addManagerListener("mainViewSceneIndexChange", set), this.manager.setMainViewSceneIndex.bind(this.manager));
235
235
  this.sceneLength = this.createValue(this.manager.mainViewScenesLength, (set) => this._addManagerListener("mainViewScenesLengthChange", set));
236
236
  }
@@ -260,7 +260,7 @@ var FastboardApp = class extends FastboardAppBase {
260
260
  }
261
261
  cleanCurrentScene() {
262
262
  this._assertNotDestroyed();
263
- this.manager.mainView.cleanCurrentScene();
263
+ this.manager.cleanCurrentScene();
264
264
  }
265
265
  setAppliance(appliance, shape) {
266
266
  this._assertNotDestroyed();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/minimal.ts","../src/behaviors/register-apps.ts","../src/helpers/utils.ts","../src/impl/app.ts","../src/helpers/emitter.ts","../src/helpers/value.ts","../src/impl/player.ts"],"sourcesContent":["import type {\n Displayer,\n HotKeys,\n JoinRoomParams,\n PlayerCallbacks,\n ReplayRoomParams,\n Room,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { MountParams } from \"@netless/window-manager\";\n\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport { ensureWindowManager } from \"./helpers/utils\";\nimport { FastboardApp } from \"./impl/app\";\nimport { FastboardPlayer } from \"./impl/player\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./helpers/value\";\n\nexport type { FastboardApp };\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\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 * },\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({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys: Partial<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 const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensureWindowManager(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n return new FastboardApp(sdk, room, manager, hotKeys);\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\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 replayFastboard({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const player = await sdk.replayRoom(\n {\n ...ensureWindowManager(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player as Displayer as Room,\n });\n\n return new FastboardPlayer(sdk, player, manager);\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Monaco\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"Countdown\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"GeoGebra\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-geogebra@latest/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","import type { ConvertedFile, JoinRoomParams, ReplayRoomParams, SceneDefinition, Size } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nexport function noop() {\n /* noop */\n}\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\")) {\n continue;\n }\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) {\n continue;\n }\n taskId = match.groups.taskId;\n url = \"https\" + match.groups.prefix;\n break;\n }\n\n return { emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number) {\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\nexport function ensureWindowManager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {\n joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];\n }\n return joinRoom;\n}\n\n// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"!#%()*+,-./:;=?@[]^_`{|}~\" + \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 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","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKeys,\n MemberState,\n Rectangle,\n Room,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdk,\n} from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"../helpers/utils\";\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardAppBase {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>\n ) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardApp] Can not call any method on destroyed FastboardApp.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\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\nexport class FastboardApp extends FastboardAppBase {\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 = this.createValue(\n this.room.isWritable,\n set => this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable)),\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = this.createValue(this.manager.boxState, set =>\n this._addManagerListener(\"boxStateChange\", set)\n );\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = this.createValue(this.manager.focused, set =>\n this._addManagerListener(\"focusedChange\", set)\n );\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, set =>\n this._addMainViewListener(\"onCanRedoStepsUpdate\", set)\n );\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, set =>\n this._addMainViewListener(\"onCanUndoStepsUpdate\", set)\n );\n\n /**\n * Current camera information of main view.\n */\n readonly camera = this.createValue(\n this.manager.mainView.camera,\n set => this._addMainViewListener(\"onCameraUpdated\", set),\n this.manager.moveCamera.bind(this.manager)\n );\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n */\n readonly memberState = this.createValue<MemberState, SetMemberStateFn>(\n this.room.state.memberState,\n set =>\n this._addRoomListener<\"onRoomStateChanged\", RoomStateChanged>(\n \"onRoomStateChanged\",\n ({ memberState: m }) => m && set(m)\n ),\n this.manager.mainView.setMemberState.bind(this.manager.mainView)\n );\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = this.createValue(\n this.manager.mainViewSceneIndex,\n set => this._addManagerListener(\"mainViewSceneIndexChange\", set),\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>\n this._addManagerListener(\"mainViewScenesLengthChange\", set)\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.mainView.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.mainView.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.mainView.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames, shape?: ShapeType) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });\n }\n\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Insert an image to the main view.\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 if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"[FastboardApp] Can not insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const { emptyScenes, taskId, url } = makeSlideParams(scenes);\n if (taskId && url) {\n const title = arg1;\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url, scenes: emptyScenes });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title: arg1 });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Monaco Code Editor app.\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 */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\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 GeoGebra app.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n","export type FastboardListener<T> = (event: T) => void;\n\nexport class FastboardEmitter<T> {\n listeners = new Set<FastboardListener<T>>();\n\n get length(): number {\n return this.listeners.size;\n }\n\n dispatch(message: T) {\n this.listeners.forEach(callback => callback(message));\n }\n\n addListener(listener: FastboardListener<T>) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: FastboardListener<T>) {\n this.listeners.delete(listener);\n }\n}\n","import { FastboardEmitter } from \"./emitter\";\nimport { noop } from \"./utils\";\n\nexport type FastboardDisposer = () => void;\n\nexport interface FastboardReadable<T> {\n readonly value: T;\n subscribe(callback: (value: T) => void): FastboardDisposer;\n reaction(callback: (value: T) => void): FastboardDisposer;\n}\n\nexport interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {\n setValue: SetFn;\n}\n\nexport interface FastboardInternalValue<T> extends FastboardWritable<T> {\n dispose: FastboardDisposer;\n}\n\n/**\n * Create a readonly, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * })\n */\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void\n): FastboardReadable<T>;\n\n/**\n * Create a writable, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * }, (newValue) => {\n * manager.setMainViewSceneIndex(newValue)\n * })\n */\nexport function createValue<T, SetFn = (value: T) => void>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n set: (value: T) => void\n): FastboardWritable<T, SetFn>;\n\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n setValue: (value: T) => void = noop\n): FastboardInternalValue<T> {\n const emitter = new FastboardEmitter<T>();\n\n function set(newValue: T) {\n emitter.dispatch((value = newValue));\n }\n\n const dispose = effect(set) || noop;\n\n function subscribe(callback: (value: T) => void) {\n emitter.addListener(callback);\n callback(value);\n return () => emitter.removeListener(callback);\n }\n\n function reaction(callback: (value: T) => void) {\n emitter.addListener(callback);\n return () => emitter.removeListener(callback);\n }\n\n return { value, subscribe, reaction, setValue, dispose };\n}\n","import type { Player, PlayerCallbacks, PlayerState, ViewCallbacks, WhiteWebSdk } from \"white-web-sdk\";\nimport type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardPlayerBase {\n public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardPlayer] Can not call any method on destroyed FastboardPlayer.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks, T = PlayerCallbacks[K]>(\n name: K,\n listener: T\n ) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n this.player.callbacks.off();\n }\n}\n\nexport class FastboardPlayer extends FastboardPlayerBase {\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 readonly currentTime = this.createValue(\n this.player.progressTime,\n set => this._addPlayerListener(\"onProgressTimeChanged\", set),\n this.player.seekToProgressTime.bind(this.player)\n );\n\n readonly phase = this.createValue(this.player.phase, set => this._addPlayerListener(\"onPhaseChanged\", set));\n\n readonly canplay = this.createValue(this.player.isPlayable, set =>\n this._addPlayerListener(\"onIsPlayableChanged\", set)\n );\n\n private _setSpeed!: (value: number) => void;\n readonly speed = this.createValue(\n this.player.playbackSpeed,\n set => {\n this._setSpeed = set;\n },\n value => {\n this.player.playbackSpeed = value;\n this._setSpeed(value);\n }\n );\n\n readonly state = this.createValue<PlayerState | null>(null, set => {\n const update = () => set(this.player.state);\n const dispose1 = this._addPlayerListener(\"onLoadFirstFrame\", update);\n const dispose2 = this._addPlayerListener(\"onPlayerStateChanged\", update);\n return () => (dispose1(), dispose2());\n });\n\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/minimal.ts","../src/behaviors/register-apps.ts","../src/helpers/utils.ts","../src/impl/app.ts","../src/helpers/emitter.ts","../src/helpers/value.ts","../src/impl/player.ts"],"sourcesContent":["import type {\n Displayer,\n HotKeys,\n JoinRoomParams,\n PlayerCallbacks,\n ReplayRoomParams,\n Room,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { MountParams } from \"@netless/window-manager\";\n\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport { ensureWindowManager } from \"./helpers/utils\";\nimport { FastboardApp } from \"./impl/app\";\nimport { FastboardPlayer } from \"./impl/player\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./helpers/value\";\n\nexport type { FastboardApp };\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\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 * },\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({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys: Partial<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 const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensureWindowManager(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n return new FastboardApp(sdk, room, manager, hotKeys);\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let app = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * },\n * replayRoom: {\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 replayFastboard({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const player = await sdk.replayRoom(\n {\n ...ensureWindowManager(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player as Displayer as Room,\n });\n\n return new FastboardPlayer(sdk, player, manager);\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Monaco\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"Countdown\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"GeoGebra\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-geogebra@latest/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","import type { ConvertedFile, JoinRoomParams, ReplayRoomParams, SceneDefinition, Size } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nexport function noop() {\n /* noop */\n}\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\")) {\n continue;\n }\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) {\n continue;\n }\n taskId = match.groups.taskId;\n url = \"https\" + match.groups.prefix;\n break;\n }\n\n return { emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number) {\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\nexport function ensureWindowManager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {\n joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];\n }\n return joinRoom;\n}\n\n// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"!#%()*+,-./:;=?@[]^_`{|}~\" + \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 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","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKeys,\n MemberState,\n Rectangle,\n Room,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdk,\n} from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"../helpers/utils\";\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardAppBase {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>\n ) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardApp] Can not call any method on destroyed FastboardApp.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\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\nexport class FastboardApp extends FastboardAppBase {\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 = this.createValue(\n this.room.isWritable,\n set => this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable)),\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = this.createValue(this.manager.boxState, set =>\n this._addManagerListener(\"boxStateChange\", set)\n );\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = this.createValue(this.manager.focused, set =>\n this._addManagerListener(\"focusedChange\", set)\n );\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = this.createValue(this.manager.canRedoSteps, set =>\n this._addManagerListener(\"canRedoStepsChange\", set)\n );\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = this.createValue(this.manager.canUndoSteps, set =>\n this._addManagerListener(\"canUndoStepsChange\", set)\n );\n\n /**\n * Current camera information of main view.\n */\n readonly camera = this.createValue(this.manager.mainView.camera, set =>\n this._addMainViewListener(\"onCameraUpdated\", set)\n );\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n */\n readonly memberState = this.createValue(this.room.state.memberState, set =>\n 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 = this.createValue(\n this.manager.mainViewSceneIndex,\n set => this._addManagerListener(\"mainViewSceneIndexChange\", set),\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>\n this._addManagerListener(\"mainViewScenesLengthChange\", set)\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.mainView.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.mainView.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, shape?: ShapeType) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });\n }\n\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Insert an image to the main view.\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 if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"[FastboardApp] Can not insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const { emptyScenes, taskId, url } = makeSlideParams(scenes);\n if (taskId && url) {\n const title = arg1;\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url, scenes: emptyScenes });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title: arg1 });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Monaco Code Editor app.\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 */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\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 GeoGebra app.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n","export type FastboardListener<T> = (event: T) => void;\n\nexport class FastboardEmitter<T> {\n listeners = new Set<FastboardListener<T>>();\n\n get length(): number {\n return this.listeners.size;\n }\n\n dispatch(message: T) {\n this.listeners.forEach(callback => callback(message));\n }\n\n addListener(listener: FastboardListener<T>) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: FastboardListener<T>) {\n this.listeners.delete(listener);\n }\n}\n","import { FastboardEmitter } from \"./emitter\";\nimport { noop } from \"./utils\";\n\nexport type FastboardDisposer = () => void;\n\nexport interface FastboardReadable<T> {\n readonly value: T;\n subscribe(callback: (value: T) => void): FastboardDisposer;\n reaction(callback: (value: T) => void): FastboardDisposer;\n}\n\nexport interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {\n setValue: SetFn;\n}\n\nexport interface FastboardInternalValue<T> extends FastboardWritable<T> {\n dispose: FastboardDisposer;\n}\n\n/**\n * Create a readonly, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * })\n */\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void\n): FastboardReadable<T>;\n\n/**\n * Create a writable, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * }, (newValue) => {\n * manager.setMainViewSceneIndex(newValue)\n * })\n */\nexport function createValue<T, SetFn = (value: T) => void>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n set: (value: T) => void\n): FastboardWritable<T, SetFn>;\n\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n setValue: (value: T) => void = noop\n): FastboardInternalValue<T> {\n const emitter = new FastboardEmitter<T>();\n\n function set(newValue: T) {\n emitter.dispatch((value = newValue));\n }\n\n const dispose = effect(set) || noop;\n\n function subscribe(callback: (value: T) => void) {\n emitter.addListener(callback);\n callback(value);\n return () => emitter.removeListener(callback);\n }\n\n function reaction(callback: (value: T) => void) {\n emitter.addListener(callback);\n return () => emitter.removeListener(callback);\n }\n\n return { value, subscribe, reaction, setValue, dispose };\n}\n","import type { Player, PlayerCallbacks, PlayerState, ViewCallbacks, WhiteWebSdk } from \"white-web-sdk\";\nimport type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardPlayerBase {\n public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardPlayer] Can not call any method on destroyed FastboardPlayer.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks, T = PlayerCallbacks[K]>(\n name: K,\n listener: T\n ) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n this.player.callbacks.off();\n }\n}\n\nexport class FastboardPlayer extends FastboardPlayerBase {\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 readonly currentTime = this.createValue(\n this.player.progressTime,\n set => this._addPlayerListener(\"onProgressTimeChanged\", set),\n this.player.seekToProgressTime.bind(this.player)\n );\n\n readonly phase = this.createValue(this.player.phase, set => this._addPlayerListener(\"onPhaseChanged\", set));\n\n readonly canplay = this.createValue(this.player.isPlayable, set =>\n this._addPlayerListener(\"onIsPlayableChanged\", set)\n );\n\n private _setSpeed!: (value: number) => void;\n readonly speed = this.createValue(\n this.player.playbackSpeed,\n set => {\n this._setSpeed = set;\n },\n value => {\n this.player.playbackSpeed = value;\n this._setSpeed(value);\n }\n );\n\n readonly state = this.createValue<PlayerState | null>(null, set => {\n const update = () => set(this.player.state);\n const dispose1 = this._addPlayerListener(\"onLoadFirstFrame\", update);\n const dispose2 = this._addPlayerListener(\"onPlayerStateChanged\", update);\n return () => (dispose1(), dispose2());\n });\n\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n}\n"],"mappings":"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","names":[]}
package/dist/minimal.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createFastboard,
3
3
  replayFastboard
4
- } from "./chunk-QSMPKHJQ.mjs";
4
+ } from "./chunk-EFXKTCHG.mjs";
5
5
  export {
6
6
  createFastboard,
7
7
  replayFastboard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/fastboard-core",
3
- "version": "0.2.1",
3
+ "version": "0.2.5",
4
4
  "description": "A tiny wrapper of white-web-sdk and @netless/window-manager.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -17,9 +17,9 @@
17
17
  "white-web-sdk": ">=2.16.0"
18
18
  },
19
19
  "devDependencies": {
20
- "@netless/window-manager": "^0.4.0-canary.24",
20
+ "@netless/window-manager": "^0.4.0",
21
21
  "tsup": "^5.11.11",
22
- "white-web-sdk": "^2.16.3"
22
+ "white-web-sdk": "^2.16.6"
23
23
  },
24
24
  "publishConfig": {
25
25
  "main": "dist/index.js",
package/src/impl/app.ts CHANGED
@@ -139,37 +139,29 @@ export class FastboardApp extends FastboardAppBase {
139
139
  /**
140
140
  * How many times can I call `app.redo()`?
141
141
  */
142
- readonly canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, set =>
143
- this._addMainViewListener("onCanRedoStepsUpdate", set)
142
+ readonly canRedoSteps = this.createValue(this.manager.canRedoSteps, set =>
143
+ this._addManagerListener("canRedoStepsChange", set)
144
144
  );
145
145
 
146
146
  /**
147
147
  * How many times can I call `app.undo()`?
148
148
  */
149
- readonly canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, set =>
150
- this._addMainViewListener("onCanUndoStepsUpdate", set)
149
+ readonly canUndoSteps = this.createValue(this.manager.canUndoSteps, set =>
150
+ this._addManagerListener("canUndoStepsChange", set)
151
151
  );
152
152
 
153
153
  /**
154
154
  * Current camera information of main view.
155
155
  */
156
- readonly camera = this.createValue(
157
- this.manager.mainView.camera,
158
- set => this._addMainViewListener("onCameraUpdated", set),
159
- this.manager.moveCamera.bind(this.manager)
156
+ readonly camera = this.createValue(this.manager.mainView.camera, set =>
157
+ this._addMainViewListener("onCameraUpdated", set)
160
158
  );
161
159
 
162
160
  /**
163
161
  * Current tool's info, like "is using pencil?", "what color?".
164
162
  */
165
- readonly memberState = this.createValue<MemberState, SetMemberStateFn>(
166
- this.room.state.memberState,
167
- set =>
168
- this._addRoomListener<"onRoomStateChanged", RoomStateChanged>(
169
- "onRoomStateChanged",
170
- ({ memberState: m }) => m && set(m)
171
- ),
172
- this.manager.mainView.setMemberState.bind(this.manager.mainView)
163
+ readonly memberState = this.createValue(this.room.state.memberState, set =>
164
+ this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m))
173
165
  );
174
166
 
175
167
  /**
@@ -225,7 +217,7 @@ export class FastboardApp extends FastboardAppBase {
225
217
  */
226
218
  cleanCurrentScene() {
227
219
  this._assertNotDestroyed();
228
- this.manager.mainView.cleanCurrentScene();
220
+ this.manager.cleanCurrentScene();
229
221
  }
230
222
 
231
223
  /**
package/src/minimal.ts CHANGED
@@ -100,11 +100,11 @@ export interface FastboardReplayOptions {
100
100
  /**
101
101
  * Create a FastboardPlayer instance.
102
102
  * @example
103
- * let app = await createFastboard({
103
+ * let app = await replayFastboard({
104
104
  * sdkConfig: {
105
105
  * appIdentifier: import.meta.env.VITE_APPID,
106
106
  * },
107
- * joinRoom: {
107
+ * replayRoom: {
108
108
  * uid: unique_id,
109
109
  * uuid: import.meta.env.VITE_ROOM_UUID,
110
110
  * roomToken: import.meta.env.VITE_ROOM_TOKEN,
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/minimal.ts","../src/behaviors/register-apps.ts","../src/helpers/utils.ts","../src/impl/app.ts","../src/helpers/emitter.ts","../src/helpers/value.ts","../src/impl/player.ts"],"sourcesContent":["import type {\n Displayer,\n HotKeys,\n JoinRoomParams,\n PlayerCallbacks,\n ReplayRoomParams,\n Room,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { MountParams } from \"@netless/window-manager\";\n\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport { ensureWindowManager } from \"./helpers/utils\";\nimport { FastboardApp } from \"./impl/app\";\nimport { FastboardPlayer } from \"./impl/player\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./helpers/value\";\n\nexport type { FastboardApp };\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\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 * },\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({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys: Partial<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 const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensureWindowManager(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n return new FastboardApp(sdk, room, manager, hotKeys);\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\">;\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\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 replayFastboard({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const player = await sdk.replayRoom(\n {\n ...ensureWindowManager(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player as Displayer as Room,\n });\n\n return new FastboardPlayer(sdk, player, manager);\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Monaco\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"Countdown\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js\",\n});\n\nWindowManager.register({\n kind: \"GeoGebra\",\n src: \"https://cdn.jsdelivr.net/npm/@netless/app-geogebra@latest/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","import type { ConvertedFile, JoinRoomParams, ReplayRoomParams, SceneDefinition, Size } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\n\nexport function noop() {\n /* noop */\n}\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\")) {\n continue;\n }\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) {\n continue;\n }\n taskId = match.groups.taskId;\n url = \"https\" + match.groups.prefix;\n break;\n }\n\n return { emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number) {\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\nexport function ensureWindowManager<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager)) {\n joinRoom.invisiblePlugins = [...(joinRoom.invisiblePlugins || []), WindowManager];\n }\n return joinRoom;\n}\n\n// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"!#%()*+,-./:;=?@[]^_`{|}~\" + \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 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","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKeys,\n MemberState,\n Rectangle,\n Room,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdk,\n} from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"../helpers/utils\";\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardAppBase {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>\n ) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardApp] Can not call any method on destroyed FastboardApp.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addRoomListener<K extends keyof RoomCallbacks, T = RoomCallbacks[K]>(name: K, listener: T) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\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\nexport class FastboardApp extends FastboardAppBase {\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 = this.createValue(\n this.room.isWritable,\n set => this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable)),\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = this.createValue(this.manager.boxState, set =>\n this._addManagerListener(\"boxStateChange\", set)\n );\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = this.createValue(this.manager.focused, set =>\n this._addManagerListener(\"focusedChange\", set)\n );\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, set =>\n this._addMainViewListener(\"onCanRedoStepsUpdate\", set)\n );\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, set =>\n this._addMainViewListener(\"onCanUndoStepsUpdate\", set)\n );\n\n /**\n * Current camera information of main view.\n */\n readonly camera = this.createValue(\n this.manager.mainView.camera,\n set => this._addMainViewListener(\"onCameraUpdated\", set),\n this.manager.moveCamera.bind(this.manager)\n );\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n */\n readonly memberState = this.createValue<MemberState, SetMemberStateFn>(\n this.room.state.memberState,\n set =>\n this._addRoomListener<\"onRoomStateChanged\", RoomStateChanged>(\n \"onRoomStateChanged\",\n ({ memberState: m }) => m && set(m)\n ),\n this.manager.mainView.setMemberState.bind(this.manager.mainView)\n );\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = this.createValue(\n this.manager.mainViewSceneIndex,\n set => this._addManagerListener(\"mainViewSceneIndexChange\", set),\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = this.createValue(this.manager.mainViewScenesLength, set =>\n this._addManagerListener(\"mainViewScenesLengthChange\", set)\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.mainView.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.mainView.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.mainView.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames, shape?: ShapeType) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });\n }\n\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Insert an image to the main view.\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 if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"[FastboardApp] Can not insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const scenes: SceneDefinition[] = arg2.progress.convertedFileList.map(convertedFileToScene);\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const { emptyScenes, taskId, url } = makeSlideParams(scenes);\n if (taskId && url) {\n const title = arg1;\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url, scenes: emptyScenes });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title: arg1 });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Monaco Code Editor app.\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 */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\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 GeoGebra app.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n","export type FastboardListener<T> = (event: T) => void;\n\nexport class FastboardEmitter<T> {\n listeners = new Set<FastboardListener<T>>();\n\n get length(): number {\n return this.listeners.size;\n }\n\n dispatch(message: T) {\n this.listeners.forEach(callback => callback(message));\n }\n\n addListener(listener: FastboardListener<T>) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: FastboardListener<T>) {\n this.listeners.delete(listener);\n }\n}\n","import { FastboardEmitter } from \"./emitter\";\nimport { noop } from \"./utils\";\n\nexport type FastboardDisposer = () => void;\n\nexport interface FastboardReadable<T> {\n readonly value: T;\n subscribe(callback: (value: T) => void): FastboardDisposer;\n reaction(callback: (value: T) => void): FastboardDisposer;\n}\n\nexport interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {\n setValue: SetFn;\n}\n\nexport interface FastboardInternalValue<T> extends FastboardWritable<T> {\n dispose: FastboardDisposer;\n}\n\n/**\n * Create a readonly, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * })\n */\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void\n): FastboardReadable<T>;\n\n/**\n * Create a writable, reactive value.\n * @example\n * createValue(manager.getMainViewSceneIndex(), (set) => {\n * manager.emitter.on(\"mainViewSceneIndexChanged\", set)\n * return () => manager.emitter.off(\"mainViewSceneIndexChanged\", set)\n * }, (newValue) => {\n * manager.setMainViewSceneIndex(newValue)\n * })\n */\nexport function createValue<T, SetFn = (value: T) => void>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n set: (value: T) => void\n): FastboardWritable<T, SetFn>;\n\nexport function createValue<T>(\n value: T,\n effect: (set: (value: T) => void) => FastboardDisposer | void,\n setValue: (value: T) => void = noop\n): FastboardInternalValue<T> {\n const emitter = new FastboardEmitter<T>();\n\n function set(newValue: T) {\n emitter.dispatch((value = newValue));\n }\n\n const dispose = effect(set) || noop;\n\n function subscribe(callback: (value: T) => void) {\n emitter.addListener(callback);\n callback(value);\n return () => emitter.removeListener(callback);\n }\n\n function reaction(callback: (value: T) => void) {\n emitter.addListener(callback);\n return () => emitter.removeListener(callback);\n }\n\n return { value, subscribe, reaction, setValue, dispose };\n}\n","import type { Player, PlayerCallbacks, PlayerState, ViewCallbacks, WhiteWebSdk } from \"white-web-sdk\";\nimport type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"../helpers/value\";\n\nimport { createValue } from \"../helpers/value\";\n\nclass FastboardPlayerBase {\n public constructor(readonly sdk: WhiteWebSdk, readonly player: Player, readonly manager: WindowManager) {}\n\n protected readonly _disposers: FastboardDisposer[] = [];\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"[FastboardPlayer] Can not call any method on destroyed FastboardPlayer.\");\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected createValue: typeof createValue = (...args: [any, any]): any => {\n const value = createValue(...args);\n this._disposers.push((value as FastboardInternalValue<unknown>).dispose);\n return value;\n };\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks, T = PlayerCallbacks[K]>(\n name: K,\n listener: T\n ) {\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>(name: K, set: (value: PublicEvent[K]) => void) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, set);\n return () => this.manager.emitter.off(name, set);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks, T = ViewCallbacks[K]>(name: K, listener: T) {\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._disposers.forEach(dispose => dispose());\n this._disposers.length = 0;\n this._destroyed = true;\n this.manager.destroy();\n this.player.callbacks.off();\n }\n}\n\nexport class FastboardPlayer extends FastboardPlayerBase {\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 readonly currentTime = this.createValue(\n this.player.progressTime,\n set => this._addPlayerListener(\"onProgressTimeChanged\", set),\n this.player.seekToProgressTime.bind(this.player)\n );\n\n readonly phase = this.createValue(this.player.phase, set => this._addPlayerListener(\"onPhaseChanged\", set));\n\n readonly canplay = this.createValue(this.player.isPlayable, set =>\n this._addPlayerListener(\"onIsPlayableChanged\", set)\n );\n\n private _setSpeed!: (value: number) => void;\n readonly speed = this.createValue(\n this.player.playbackSpeed,\n set => {\n this._setSpeed = set;\n },\n value => {\n this.player.playbackSpeed = value;\n this._setSpeed(value);\n }\n );\n\n readonly state = this.createValue<PlayerState | null>(null, set => {\n const update = () => set(this.player.state);\n const dispose1 = this._addPlayerListener(\"onLoadFirstFrame\", update);\n const dispose2 = this._addPlayerListener(\"onPlayerStateChanged\", update);\n return () => (dispose1(), dispose2());\n });\n\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n}\n"],"mappings":"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","names":[]}