@netless/fastboard-core 0.3.6 → 0.3.8-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/store.ts","../src/utils/misc.ts","../src/utils/uid.ts","../src/utils/warn.ts","../src/impl/FastboardApp.ts","../src/internal.ts","../src/behaviors/index.ts","../src/impl/FastboardPlayer.ts"],"names":[],"mappings":"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","sourcesContent":["// This is a simple mimic of svelte/store.\nexport type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\nexport type Updater<T> = (value: T) => T;\nexport type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;\n\nexport interface Readable<T> {\n readonly value: T;\n subscribe(this: void, run: Subscriber<T>): Unsubscriber;\n reaction(this: void, run: Subscriber<T>): Unsubscriber;\n}\n\nexport interface Writable<T> extends Readable<T> {\n set(this: void, value: T): void;\n update(this: void, updater: Updater<T>): void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noop() {}\n\nfunction safe_not_equal(a: unknown, b: unknown) {\n return a != a ? b == b : a !== b || (a && typeof a === \"object\") || typeof a === \"function\";\n}\n\nexport function readable<T>(value: T, start: StartStopNotifier<T> = noop): Readable<T> {\n let stop: Unsubscriber | undefined;\n const subscribers = new Set<Subscriber<T>>();\n function set(new_value: T) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) {\n for (const run of subscribers) {\n run(value);\n }\n }\n }\n }\n function subscribe(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n function reaction(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n return {\n get value() {\n return value;\n },\n subscribe,\n reaction,\n };\n}\n\nexport function writable<T>(value: T, start: StartStopNotifier<T> = noop, set: Subscriber<T>): Writable<T> {\n const internal = readable(value, start);\n return {\n get value() {\n return internal.value;\n },\n subscribe: internal.subscribe,\n reaction: internal.reaction,\n set,\n update(fn: Updater<T>) {\n set(fn(value));\n },\n };\n}\n","import type { ConvertedFile, SceneDefinition, Size } from \"white-web-sdk\";\n\nexport function getImageSize(url: string, fallback: Size) {\n return new Promise<Size>(resolve => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => resolve(fallback);\n img.src = url;\n });\n}\n\nexport function makeSlideParams(scenes: SceneDefinition[]) {\n const emptyScenes: SceneDefinition[] = [];\n let taskId = \"\";\n let url = \"\";\n\n // e.g. \"ppt(x)://cdn/prefix/dynamicConvert/{taskId}/1.slide\"\n const pptSrcRE = /^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\//;\n\n for (const { name, ppt } of scenes) {\n // make sure scenesWithoutPPT.length === scenes.length\n emptyScenes.push({ name });\n\n if (!ppt || !ppt.src.startsWith(\"ppt\")) {\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 { scenes: emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number): SceneDefinition {\n return {\n name: String(i + 1),\n ppt: {\n src: f.conversionFileUrl,\n width: f.width,\n height: f.height,\n previewURL: f.preview,\n },\n };\n}\n","// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 62; // SOUP.length\nconst ID_LEN = 20;\nconst reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);\n\nexport function genUID() {\n for (let i = 0; i < ID_LEN; i++) {\n reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);\n }\n return reusedIdCarrier.join(\"\");\n}\n","const warnings = {\n \"no-ppt-in-scenes\":\n \"You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`.\",\n} as const;\nconst warned = new Set<string>();\n\nexport function warn(id: keyof typeof warnings) {\n if (warned.has(id)) return;\n warned.add(id);\n console.warn(warnings[id]);\n}\n","import type { AddPageParams, PublicEvent, MountParams, NetlessApp } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n Rectangle,\n Room,\n RoomPhase as RoomPhaseEnum,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore, Storage, Diff, DiffOne } from \"@netless/synced-store\";\n\nimport { DefaultHotKeys, WhiteWebSdk, contentModeScale } from \"white-web-sdk\";\nimport { BuiltinApps, WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport {\n getImageSize,\n genUID,\n convertedFileToScene,\n makeSlideParams,\n readable,\n writable,\n warn,\n} from \"../utils\";\nimport { ensure_official_plugins, transform_app_status } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardAppBase<TEventData = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {\n this._assertNotDestroyed();\n this.room.callbacks.on(name, listener);\n return () => this.room.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n /**\n * Destroy fastboard (disconnect from the whiteboard room).\n */\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\ntype RoomPhase = `${RoomPhaseEnum}`;\n\nexport type {\n AddPageParams,\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n MountParams,\n NetlessApp,\n PublicEvent,\n Rectangle,\n Room,\n RoomPhase,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n SyncedStore,\n Storage,\n Diff,\n DiffOne,\n ViewCallbacks,\n WhiteWebSdk,\n WhiteWebSdkConfiguration,\n WindowManager,\n};\n\n/** pencil, eraser, rectangle... */\nexport type Appliance = `${ApplianceNames}`;\n/** triangle, star... */\nexport type Shape = `${ShapeType}`;\n\n/** Params for static docs, they are rendered as many images. */\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** @example [{ name: '1', ppt: { src: 'url/to/ppt/1.png' } }] */\n readonly scenes: SceneDefinition[];\n /** Window title. */\n readonly title?: string;\n}\n\n/** Params for slides, they are rendered in @netless/app-slide with animations. */\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** Conversion task id, see https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress. */\n readonly taskId: string;\n /** Window title. */\n readonly title?: string;\n /** Where the slide resource placed. @default `https://convertcdn.netless.link/dynamicConvert` */\n readonly url?: string;\n /** @example [{ name: '1' }, { name: '2' }, { name: '3' }] */\n readonly scenes?: SceneDefinition[];\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;\n\nexport type RoomStateChanged = (diff: Partial<RoomState>) => void;\n\n/** App download progress. */\nexport interface AppsStatus {\n [kind: string]: {\n status: \"idle\" | \"loading\" | \"failed\";\n /** Exist if status is `failed`. */\n reason?: string;\n };\n}\n\nexport class FastboardApp<TEventData = any> extends FastboardAppBase<TEventData> {\n /**\n * Render this app to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Is current room writable?\n */\n readonly writable = writable(\n this.room.isWritable,\n set => {\n set(this.room.isWritable);\n return this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable));\n },\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Is current room online?\n */\n readonly phase = readable<RoomPhase>(this.room.phase, set => {\n set(this.room.phase);\n return this._addRoomListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = readable(this.manager.boxState, set => {\n set(this.manager.boxState);\n return this._addManagerListener(\"boxStateChange\", set);\n });\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = readable(this.manager.focused, set => {\n set(this.manager.focused);\n return this._addManagerListener(\"focusedChange\", set);\n });\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = readable(this.manager.canRedoSteps, set => {\n set(this.manager.canRedoSteps);\n return this._addManagerListener(\"canRedoStepsChange\", set);\n });\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = readable(this.manager.canUndoSteps, set => {\n set(this.manager.canUndoSteps);\n return this._addManagerListener(\"canUndoStepsChange\", set);\n });\n\n /**\n * Current camera information of main view.\n *\n * Change the camera position by `app.moveCamera()`.\n */\n readonly camera = readable(this.manager.camera, set => {\n set(this.manager.camera);\n return this._addMainViewListener(\"onCameraUpdated\", set);\n });\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n *\n * Change the tool by `app.setAppliance()`.\n */\n readonly memberState = readable(this.room.state.memberState, set => {\n set(this.room.state.memberState);\n return this._addRoomListener(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m));\n });\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = writable(\n this.manager.mainViewSceneIndex,\n set => {\n set(this.manager.mainViewSceneIndex);\n return this._addManagerListener(\"mainViewSceneIndexChange\", set);\n },\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = readable(this.manager.mainViewScenesLength, set => {\n set(this.manager.mainViewScenesLength);\n return this._addManagerListener(\"mainViewScenesLengthChange\", set);\n });\n\n private _appsStatus: AppsStatus = {};\n /**\n * Apps status.\n */\n readonly appsStatus = readable<AppsStatus>({}, set =>\n this._addManagerListener(\"loadApp\", ({ kind, status, reason }) => {\n this._appsStatus[kind] = { status: transform_app_status(status), reason };\n set(this._appsStatus);\n })\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.redo();\n }\n\n /**\n * Move current main view's camera position.\n */\n moveCamera(camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }) {\n this._assertNotDestroyed();\n this.manager.moveCamera(camera);\n }\n\n /**\n * Move current main view's camera to include a rectangle.\n */\n moveCameraToContain(rectangle: Rectangle & { animationMode?: AnimationMode }) {\n this._assertNotDestroyed();\n this.manager.moveCameraToContain(rectangle);\n }\n\n /**\n * Delete all things on the main view.\n */\n cleanCurrentScene() {\n this._assertNotDestroyed();\n this.manager.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({\n currentApplianceName: appliance as ApplianceNames,\n shapeType: shape as ShapeType,\n });\n }\n\n /**\n * Set pencil and shape's thickness.\n */\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n /**\n * Set pencil and shape's color.\n */\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Set text size. Default is 16.\n */\n setTextSize(textSize: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textSize });\n }\n\n /**\n * Set text color.\n *\n * @example\n * setTextColor([0x66, 0xcc, 0xff])\n */\n setTextColor(textColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textColor });\n }\n\n /**\n * Goto previous page (the main whiteboard view).\n */\n prevPage() {\n this._assertNotDestroyed();\n return this.manager.prevPage();\n }\n\n /**\n * Goto next page (the main whiteboard view).\n */\n nextPage() {\n this._assertNotDestroyed();\n return this.manager.nextPage();\n }\n\n /**\n * Add one page to the main whiteboard view.\n *\n * @example\n * addPage({ after: true }) // add one page right after current one.\n * nextPage() // then, goto that page.\n */\n addPage(params?: AddPageParams) {\n this._assertNotDestroyed();\n return this.manager.addPage(params);\n }\n\n /**\n * Remove one page at given index or current page (by default).\n *\n * Requires `@netless/window-manager` >= 0.4.30.\n *\n * @example\n * removePage() // remove current page\n */\n removePage(index?: number) {\n this._assertNotDestroyed();\n return this.manager.removePage(index);\n }\n\n /**\n * Insert an image to the main view.\n *\n * @example\n * insertImage(\"https://i.imgur.com/CzXTtJV.jpg\")\n */\n async insertImage(url: string) {\n this._assertNotDestroyed();\n await this.manager.switchMainViewToWriter();\n\n const { divElement } = this.manager.mainView;\n const containerSize = {\n width: divElement?.scrollWidth || window.innerWidth,\n height: divElement?.scrollHeight || window.innerHeight,\n };\n\n // 1. shrink the image a little to fit container **width**\n const maxWidth = containerSize.width * 0.8;\n let { width, height } = await getImageSize(url, containerSize);\n const scale = Math.min(maxWidth / width, 1);\n const uuid = genUID();\n const { centerX, centerY } = this.manager.camera;\n width *= scale;\n height *= scale;\n this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });\n this.manager.mainView.completeImageUpload(uuid, url);\n\n // 2. move camera to fit image **height**\n width /= 0.8;\n height /= 0.8;\n const originX = centerX - width / 2;\n const originY = centerY - height / 2;\n this.manager.moveCameraToContain({ originX, originY, width, height });\n }\n\n /**\n * Insert PDF/PPTX from conversion result.\n * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress\n */\n insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;\n\n /**\n * Manual way.\n * @example\n * app.insertDocs({\n * fileType: 'pptx',\n * scenePath: `/pptx/${conversion.taskId}`,\n * taskId: conversion.taskId,\n * title: 'Title',\n * })\n */\n insertDocs(params: InsertDocsParams): Promise<string | undefined>;\n\n insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse) {\n this._assertNotDestroyed();\n if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"FastboardApp cannot insert a converting doc.\");\n } else if (arg2 && arg2.progress) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);\n const { scenes, taskId, url } = makeSlideParams(scenes1);\n if (taskId && url) {\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, scenes, title, taskId, url });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes: scenes1, title });\n }\n }\n }\n\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n if (scenes && scenes[0].ppt) {\n warn(\"no-ppt-in-scenes\");\n }\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Media Player app.\n */\n insertMedia(title: string, src: string) {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: BuiltinApps.MediaPlayer,\n options: { title },\n attributes: { src },\n });\n }\n\n /**\n * Insert the Monaco Code Editor app.\n * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.\n */\n insertCodeEditor() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n /**\n * Insert the Countdown app.\n * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.\n */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n /**\n * Insert the GeoGebra app.\n * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<RoomCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardApp instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * joinRoom: {\n * uid: unique_id,\n * uuid: import.meta.env.VITE_ROOM_UUID,\n * roomToken: import.meta.env.VITE_ROOM_TOKEN,\n * },\n * })\n */\nexport async function createFastboard<TEventData = any>({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys = joinRoomParams.hotKeys || {\n ...DefaultHotKeys,\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n };\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensure_official_plugins(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(room);\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n manager.mainView.setCameraBound({\n minContentMode: contentModeScale(0.3),\n maxContentMode: contentModeScale(3),\n });\n\n return new FastboardApp<TEventData>(sdk, room, manager, hotKeys, syncedStore);\n}\n","import type { JoinRoomParams, ReplayRoomParams } from \"white-web-sdk\";\nimport type { PublicEvent } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\n\nexport function ensure_official_plugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n const plugins = new Set(joinRoom.invisiblePlugins || []);\n plugins.add(WindowManager);\n plugins.add(SyncedStorePlugin);\n joinRoom.invisiblePlugins = [...plugins];\n return joinRoom;\n}\n\nexport function transform_app_status(status: PublicEvent[\"loadApp\"][\"status\"]) {\n return status === \"start\" ? \"loading\" : status === \"failed\" ? \"failed\" : \"idle\";\n}\n","import type { RegisterParams } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport SlideApp, { apps, addHooks, previewSlide } from \"@netless/app-slide\";\n\nexport type {\n AppOptions as SlideOptions,\n Controller as SlideController,\n PreviewParams,\n SlidePreviewer,\n} from \"@netless/app-slide\";\nexport { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };\n\nexport interface AppsConfig {\n [kind: string]: Omit<RegisterParams, \"kind\">;\n}\n\nconst DefaultApps: AppsConfig = {\n Monaco: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.12/dist/main.iife.js\",\n },\n Countdown: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js\",\n },\n GeoGebra: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n },\n EmbeddedPage: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js\",\n },\n Plyr: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js\",\n },\n};\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: { debug: false },\n src: SlideApp,\n addHooks,\n});\n\nfor (const kind in DefaultApps) {\n if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {\n const options = DefaultApps[kind];\n WindowManager.register({ kind, ...options });\n }\n}\n\nexport const register = WindowManager.register.bind(WindowManager);\n\ndeclare let __NAME__: string, __VERSION__: string;\n\nexport const version = __VERSION__;\n\nif (typeof window !== \"undefined\") {\n let str = (window as { __netlessUA?: string }).__netlessUA || \"\";\n str += ` ${__NAME__}@${version} `;\n (window as { __netlessUA?: string }).__netlessUA = str;\n}\n","import type { MountParams, NetlessApp, PublicEvent } from \"@netless/window-manager\";\nimport type {\n Player,\n PlayerPhase as PlayerPhaseEnum,\n PlayerCallbacks,\n PlayerState,\n PlayerSeekingResult,\n ReplayRoomParams,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore } from \"@netless/synced-store\";\n\nimport { WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport { readable, writable } from \"../utils\";\nimport { ensure_official_plugins } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardPlayerBase<TEventData = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly player: Player,\n readonly manager: WindowManager,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {\n this._assertNotDestroyed();\n this.player.callbacks.on(name, listener);\n return () => this.player.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.player.callbacks.off();\n }\n}\n\ntype PlayerPhase = `${PlayerPhaseEnum}`;\n\nexport type { PlayerPhase, PlayerSeekingResult };\n\nexport class FastboardPlayer<TEventData = any> extends FastboardPlayerBase<TEventData> {\n /**\n * Render this player to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Player current time in milliseconds.\n */\n readonly currentTime = writable(\n this.player.progressTime,\n set => {\n set(this.player.progressTime);\n return this._addPlayerListener(\"onProgressTimeChanged\", set);\n },\n this.player.seekToProgressTime.bind(this.player)\n );\n\n /**\n * Player state, like \"is it playing?\".\n */\n readonly phase = readable<PlayerPhase>(this.player.phase, set => {\n set(this.player.phase);\n return this._addPlayerListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Will become true after buffering.\n */\n readonly canplay = readable(this.player.isPlayable, set => {\n set(this.player.isPlayable);\n return this._addPlayerListener(\"onIsPlayableChanged\", set);\n });\n\n private _setPlaybackRate!: (value: number) => void;\n /**\n * Playback speed, default `1`.\n */\n readonly playbackRate = writable(\n this.player.playbackSpeed,\n set => {\n this._setPlaybackRate = set;\n set(this.player.playbackSpeed);\n },\n value => {\n this.player.playbackSpeed = value;\n this._setPlaybackRate(value);\n }\n );\n\n /**\n * Playback duration in milliseconds.\n */\n readonly duration = readable(this.player.timeDuration, set => {\n set(this.player.timeDuration);\n });\n\n /**\n * Get state of room at that time, like \"who was in the room?\".\n */\n readonly state = readable<PlayerState>(this.player.state, set => {\n set(this.player.state);\n return this._addPlayerListener(\"onPlayerStateChanged\", () => set(this.player.state));\n });\n\n /**\n * Seek to some time in milliseconds.\n */\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n /**\n * Change player state to playing.\n */\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n /**\n * Change player state to paused.\n */\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n /**\n * Change player state to stopped.\n */\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n\n /**\n * Set playback speed, a shortcut for `speed.set(x)`.\n */\n setPlaybackRate(value: number) {\n this._assertNotDestroyed();\n this.playbackRate.set(value);\n }\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let player = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * replayRoom: {\n * room: \"room uuid\",\n * roomToken: \"NETLESSROOM_...\",\n * beginTimestamp: 1646619090394,\n * duration: 70448,\n * },\n * })\n */\nexport async function replayFastboard<TEventData = any>({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const player = await sdk.replayRoom(\n {\n ...ensure_official_plugins(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(player);\n\n const managerPromise = WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player,\n });\n\n player.play();\n const manager = await managerPromise;\n player.pause();\n await player.seekToProgressTime(0);\n\n return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/store.ts","../src/utils/misc.ts","../src/utils/uid.ts","../src/utils/warn.ts","../src/impl/FastboardApp.ts","../src/internal.ts","../src/behaviors/index.ts","../src/impl/FastboardPlayer.ts","../src/helpers/listen.ts","../src/helpers/docs.ts"],"names":["WindowManager","SyncedStorePlugin","WhiteWebSdk"],"mappings":"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","sourcesContent":["// This is a simple mimic of svelte/store.\nexport type Subscriber<T> = (value: T) => void;\nexport type Unsubscriber = () => void;\nexport type Updater<T> = (value: T) => T;\nexport type StartStopNotifier<T> = (set: Subscriber<T>) => Unsubscriber | void;\n\nexport interface Readable<T> {\n readonly value: T;\n subscribe(this: void, run: Subscriber<T>): Unsubscriber;\n reaction(this: void, run: Subscriber<T>): Unsubscriber;\n}\n\nexport interface Writable<T> extends Readable<T> {\n set(this: void, value: T): void;\n update(this: void, updater: Updater<T>): void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nfunction noop() {}\n\nfunction safe_not_equal(a: unknown, b: unknown) {\n return a != a ? b == b : a !== b || (a && typeof a === \"object\") || typeof a === \"function\";\n}\n\nexport function readable<T>(value: T, start: StartStopNotifier<T> = noop): Readable<T> {\n let stop: Unsubscriber | undefined;\n const subscribers = new Set<Subscriber<T>>();\n function set(new_value: T) {\n if (safe_not_equal(value, new_value)) {\n value = new_value;\n if (stop) {\n for (const run of subscribers) {\n run(value);\n }\n }\n }\n }\n function subscribe(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n run(value);\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n function reaction(run: Subscriber<T>) {\n subscribers.add(run);\n if (subscribers.size === 1) {\n stop = start(set) || noop;\n }\n return () => {\n subscribers.delete(run);\n if (subscribers.size === 0) {\n stop && stop();\n stop = undefined;\n }\n };\n }\n return {\n get value() {\n return value;\n },\n subscribe,\n reaction,\n };\n}\n\nexport function writable<T>(value: T, start: StartStopNotifier<T> = noop, set: Subscriber<T>): Writable<T> {\n const internal = readable(value, start);\n return {\n get value() {\n return internal.value;\n },\n subscribe: internal.subscribe,\n reaction: internal.reaction,\n set,\n update(fn: Updater<T>) {\n set(fn(value));\n },\n };\n}\n","import type { ConvertedFile, SceneDefinition, Size } from \"white-web-sdk\";\n\nexport function getImageSize(url: string, fallback: Size) {\n return new Promise<Size>(resolve => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = () => resolve(fallback);\n img.src = url;\n });\n}\n\nexport function makeSlideParams(scenes: SceneDefinition[]) {\n const emptyScenes: SceneDefinition[] = [];\n let taskId = \"\";\n let url = \"\";\n\n // e.g. \"ppt(x)://cdn/prefix/dynamicConvert/{taskId}/1.slide\"\n const pptSrcRE = /^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\//;\n\n for (const { name, ppt } of scenes) {\n // make sure scenesWithoutPPT.length === scenes.length\n emptyScenes.push({ name });\n\n if (!ppt || !ppt.src.startsWith(\"ppt\")) continue;\n\n const match = pptSrcRE.exec(ppt.src);\n if (!match || !match.groups) continue;\n\n taskId = match.groups.taskId;\n url = `https${match.groups.prefix}`;\n break;\n }\n\n return { scenes: emptyScenes, taskId, url };\n}\n\nexport function convertedFileToScene(f: ConvertedFile, i: number): SceneDefinition {\n return {\n name: String(i + 1),\n ppt: {\n src: f.conversionFileUrl,\n width: f.width,\n height: f.height,\n previewURL: f.preview,\n },\n };\n}\n","// Copy from https://github.com/crimx/side-effect-manager/blob/main/src/gen-uid.ts\nconst SOUP = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst SOUP_LEN = 62; // SOUP.length\nconst ID_LEN = 20;\nconst reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);\n\nexport function genUID() {\n for (let i = 0; i < ID_LEN; i++) {\n reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);\n }\n return reusedIdCarrier.join(\"\");\n}\n","const warnings = {\n \"no-ppt-in-scenes\":\n \"You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`.\",\n} as const;\nconst warned = new Set<string>();\n\nexport function warn(id: keyof typeof warnings) {\n if (warned.has(id)) return;\n warned.add(id);\n console.warn(warnings[id]);\n}\n","import type { AddPageParams, PublicEvent, MountParams, NetlessApp } from \"@netless/window-manager\";\nimport type {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n Rectangle,\n Room,\n RoomPhase as RoomPhaseEnum,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore, Storage, Diff, DiffOne } from \"@netless/synced-store\";\n\nimport { DefaultHotKeys, WhiteWebSdk, contentModeScale } from \"white-web-sdk\";\nimport { BuiltinApps, WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport {\n getImageSize,\n genUID,\n convertedFileToScene,\n makeSlideParams,\n readable,\n writable,\n warn,\n} from \"../utils\";\nimport { ensure_official_plugins, transform_app_status } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardAppBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly room: Room,\n readonly manager: WindowManager,\n readonly hotKeys: Partial<HotKeys>,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addRoomListener<K extends keyof RoomCallbacks>(name: K, listener: RoomCallbacks[K]) {\n this._assertNotDestroyed();\n this.room.callbacks.on(name, listener);\n return () => this.room.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n /**\n * Destroy fastboard (disconnect from the whiteboard room).\n */\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.room.disconnect();\n }\n}\n\ntype RoomPhase = `${RoomPhaseEnum}`;\n\nexport type {\n AddPageParams,\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n HotKey,\n HotKeys,\n JoinRoomParams,\n MemberState,\n MountParams,\n NetlessApp,\n PublicEvent,\n Rectangle,\n Room,\n RoomPhase,\n RoomCallbacks,\n RoomState,\n SceneDefinition,\n ShapeType,\n SyncedStore,\n Storage,\n Diff,\n DiffOne,\n ViewCallbacks,\n WhiteWebSdk,\n WhiteWebSdkConfiguration,\n WindowManager,\n};\n\n/** pencil, eraser, rectangle... */\nexport type Appliance = `${ApplianceNames}`;\n/** triangle, star... */\nexport type Shape = `${ShapeType}`;\n\n/** Params for static docs, they are rendered as many images. */\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** @example [{ name: '1', ppt: { src: 'url/to/ppt/1.png' } }] */\n readonly scenes: SceneDefinition[];\n /** Window title. */\n readonly title?: string;\n}\n\n/** Params for slides, they are rendered in @netless/app-slide with animations. */\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n /** Unique string for binding whiteboard view to the doc. Must start with `/`. */\n readonly scenePath: string;\n /** Conversion task id, see https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress. */\n readonly taskId: string;\n /** Window title. */\n readonly title?: string;\n /** Where the slide resource placed. @default `https://convertcdn.netless.link/dynamicConvert` */\n readonly url?: string;\n /** @example [{ name: '1' }, { name: '2' }, { name: '3' }] */\n readonly scenes?: SceneDefinition[];\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport interface ProjectorResponse {\n uuid: string;\n status: \"Waiting\" | \"Converting\" | \"Finished\" | \"Fail\";\n type: \"dynamic\" | \"static\";\n /** 0..100 */\n convertedPercentage: number;\n /** https://example.org/path/to/dynamicConvert, only when type=dynamic */\n prefix?: string;\n pageCount?: number;\n /** {1:\"{prefix}/{taskId}/preview/1.png\"}, only when type=dynamic and preview=true */\n previews?: Record<number, string>;\n /** {prefix}/{taskId}/jsonOutput/note.json */\n note?: string;\n /** {1:{width,height,url}}, only when type=static */\n images?: Record<number, { width: number; height: number; url: string }>;\n /** 20xxxxx */\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;\n\nexport type RoomStateChanged = (diff: Partial<RoomState>) => void;\n\n/** App download progress. */\nexport interface AppsStatus {\n [kind: string]: {\n status: \"idle\" | \"loading\" | \"failed\";\n /** Exist if status is `failed`. */\n reason?: string;\n };\n}\n\nexport class FastboardApp<TEventData extends Record<string, any> = any> extends FastboardAppBase<TEventData> {\n /**\n * Render this app to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Is current room writable?\n */\n readonly writable = writable(\n this.room.isWritable,\n set => {\n set(this.room.isWritable);\n return this._addRoomListener(\"onEnableWriteNowChanged\", () => set(this.room.isWritable));\n },\n this.room.setWritable.bind(this.room)\n );\n\n /**\n * Is current room online?\n */\n readonly phase = readable<RoomPhase>(this.room.phase, set => {\n set(this.room.phase);\n return this._addRoomListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Current window-manager's windows' state (is it maximized?).\n */\n readonly boxState = readable(this.manager.boxState, set => {\n set(this.manager.boxState);\n return this._addManagerListener(\"boxStateChange\", set);\n });\n\n /**\n * Current window-manager's focused app's id.\n * @example \"HelloWorld-1A2b3C4d\"\n */\n readonly focusedApp = readable(this.manager.focused, set => {\n set(this.manager.focused);\n return this._addManagerListener(\"focusedChange\", set);\n });\n\n /**\n * How many times can I call `app.redo()`?\n */\n readonly canRedoSteps = readable(this.manager.canRedoSteps, set => {\n set(this.manager.canRedoSteps);\n return this._addManagerListener(\"canRedoStepsChange\", set);\n });\n\n /**\n * How many times can I call `app.undo()`?\n */\n readonly canUndoSteps = readable(this.manager.canUndoSteps, set => {\n set(this.manager.canUndoSteps);\n return this._addManagerListener(\"canUndoStepsChange\", set);\n });\n\n /**\n * Current camera information of main view.\n *\n * Change the camera position by `app.moveCamera()`.\n */\n readonly camera = readable(this.manager.camera, set => {\n set(this.manager.camera);\n return this._addMainViewListener(\"onCameraUpdated\", set);\n });\n\n /**\n * Current tool's info, like \"is using pencil?\", \"what color?\".\n *\n * Change the tool by `app.setAppliance()`.\n */\n readonly memberState = readable(this.room.state.memberState, set => {\n set(this.room.state.memberState);\n return this._addRoomListener(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m));\n });\n\n /**\n * 0..n-1, current index of main view scenes.\n */\n readonly sceneIndex = writable(\n this.manager.mainViewSceneIndex,\n set => {\n set(this.manager.mainViewSceneIndex);\n return this._addManagerListener(\"mainViewSceneIndexChange\", set);\n },\n this.manager.setMainViewSceneIndex.bind(this.manager)\n );\n\n /**\n * How many pages are in the main view?\n */\n readonly sceneLength = readable(this.manager.mainViewScenesLength, set => {\n set(this.manager.mainViewScenesLength);\n return this._addManagerListener(\"mainViewScenesLengthChange\", set);\n });\n\n /** @internal */\n private _appsStatus: AppsStatus = {};\n /**\n * Apps status.\n */\n readonly appsStatus = readable<AppsStatus>({}, set =>\n this._addManagerListener(\"loadApp\", ({ kind, status, reason }) => {\n this._appsStatus[kind] = { status: transform_app_status(status), reason };\n set(this._appsStatus);\n })\n );\n\n /**\n * Undo a step on main view.\n */\n undo() {\n this._assertNotDestroyed();\n this.manager.undo();\n }\n\n /**\n * Redo a step on main view.\n */\n redo() {\n this._assertNotDestroyed();\n this.manager.redo();\n }\n\n /**\n * Move current main view's camera position.\n */\n moveCamera(camera: Partial<Camera> & { animationMode?: AnimationMode | undefined }) {\n this._assertNotDestroyed();\n this.manager.moveCamera(camera);\n }\n\n /**\n * Move current main view's camera to include a rectangle.\n */\n moveCameraToContain(rectangle: Rectangle & { animationMode?: AnimationMode }) {\n this._assertNotDestroyed();\n this.manager.moveCameraToContain(rectangle);\n }\n\n /**\n * Delete all things on the main view.\n */\n cleanCurrentScene() {\n this._assertNotDestroyed();\n this.manager.cleanCurrentScene();\n }\n\n /**\n * Set current tool, like \"pencil\".\n */\n setAppliance(appliance: ApplianceNames | Appliance, shape?: ShapeType | Shape) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({\n currentApplianceName: appliance as ApplianceNames,\n shapeType: shape as ShapeType,\n });\n }\n\n /**\n * Set pencil and shape's thickness.\n */\n setStrokeWidth(strokeWidth: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeWidth });\n }\n\n /**\n * Set pencil and shape's color.\n */\n setStrokeColor(strokeColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ strokeColor });\n }\n\n /**\n * Set text size. Default is 16.\n */\n setTextSize(textSize: number) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textSize });\n }\n\n /**\n * Set text color.\n *\n * @example\n * setTextColor([0x66, 0xcc, 0xff])\n */\n setTextColor(textColor: Color) {\n this._assertNotDestroyed();\n this.manager.mainView.setMemberState({ textColor });\n }\n\n /**\n * Goto previous page (the main whiteboard view).\n */\n prevPage() {\n this._assertNotDestroyed();\n return this.manager.prevPage();\n }\n\n /**\n * Goto next page (the main whiteboard view).\n */\n nextPage() {\n this._assertNotDestroyed();\n return this.manager.nextPage();\n }\n\n /**\n * Add one page to the main whiteboard view.\n *\n * @example\n * addPage({ after: true }) // add one page right after current one.\n * nextPage() // then, goto that page.\n */\n addPage(params?: AddPageParams) {\n this._assertNotDestroyed();\n return this.manager.addPage(params);\n }\n\n /**\n * Remove one page at given index or current page (by default).\n *\n * Requires `@netless/window-manager` >= 0.4.30.\n *\n * @example\n * removePage() // remove current page\n */\n removePage(index?: number) {\n this._assertNotDestroyed();\n return this.manager.removePage(index);\n }\n\n /**\n * Insert an image to the main view.\n *\n * @example\n * insertImage(\"https://i.imgur.com/CzXTtJV.jpg\")\n */\n async insertImage(url: string) {\n this._assertNotDestroyed();\n await this.manager.switchMainViewToWriter();\n\n const { divElement } = this.manager.mainView;\n const containerSize = {\n width: divElement?.scrollWidth || window.innerWidth,\n height: divElement?.scrollHeight || window.innerHeight,\n };\n\n // 1. shrink the image a little to fit container **width**\n const maxWidth = containerSize.width * 0.8;\n let { width, height } = await getImageSize(url, containerSize);\n const scale = Math.min(maxWidth / width, 1);\n const uuid = genUID();\n const { centerX, centerY } = this.manager.camera;\n width *= scale;\n height *= scale;\n this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });\n this.manager.mainView.completeImageUpload(uuid, url);\n\n // 2. move camera to fit image **height**\n width /= 0.8;\n height /= 0.8;\n const originX = centerX - width / 2;\n const originY = centerY - height / 2;\n this.manager.moveCameraToContain({ originX, originY, width, height });\n }\n\n /**\n * Insert PDF/PPTX from conversion result.\n * @param status https://developer.netless.link/server-en/home/server-conversion#get-query-task-conversion-progress\n */\n insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;\n\n /**\n * Insert PDF/PPTX from projector conversion result.\n * @param response https://developer.netless.link/server-zh/home/server-projector#get-%E6%9F%A5%E8%AF%A2%E4%BB%BB%E5%8A%A1%E8%BD%AC%E6%8D%A2%E8%BF%9B%E5%BA%A6\n */\n insertDocs(filename: string, response: ProjectorResponse): Promise<string | undefined>;\n\n /**\n * Manual way.\n * @example\n * app.insertDocs({\n * fileType: 'pptx',\n * scenePath: `/pptx/${conversion.taskId}`,\n * taskId: conversion.taskId,\n * title: 'Title',\n * })\n */\n insertDocs(params: InsertDocsParams): Promise<string | undefined>;\n\n insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse | ProjectorResponse) {\n this._assertNotDestroyed();\n if (typeof arg1 === \"object\" && \"fileType\" in arg1) {\n return this._insertDocsImpl(arg1);\n } else if (arg2 && arg2.status !== \"Finished\") {\n throw new Error(\"FastboardApp cannot insert a converting doc.\");\n } else if (arg2 && \"progress\" in arg2) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);\n const { scenes, taskId, url } = makeSlideParams(scenes1);\n if (taskId && url) {\n return this._insertDocsImpl({ fileType: \"pptx\", scenePath, scenes, title, taskId, url });\n } else {\n return this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes: scenes1, title });\n }\n } else if (arg2 && arg2.prefix) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const taskId = arg2.uuid;\n const url = arg2.prefix;\n this._insertDocsImpl({ fileType: \"pptx\", scenePath, taskId, title, url });\n } else if (arg2 && arg2.images) {\n const title = arg1;\n const scenePath = `/${arg2.uuid}/${genUID()}`;\n const scenes: SceneDefinition[] = [];\n for (const name in arg2.images) {\n const { width, height, url } = arg2.images[name];\n scenes.push({ name, ppt: { width, height, src: url } });\n }\n this._insertDocsImpl({ fileType: \"pdf\", scenePath, scenes, title });\n } else {\n throw new Error(\"Invalid input: not found 'progress', 'prefix' nor 'images'\");\n }\n }\n\n /** @internal */\n private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {\n this._assertNotDestroyed();\n switch (fileType) {\n case \"pdf\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: { scenePath, title, scenes },\n });\n case \"pptx\":\n if (scenes && scenes[0].ppt) {\n warn(\"no-ppt-in-scenes\");\n }\n return this.manager.addApp({\n kind: \"Slide\",\n options: { scenePath, title, scenes },\n attributes,\n });\n }\n }\n\n /**\n * Insert the Media Player app.\n */\n insertMedia(title: string, src: string) {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: BuiltinApps.MediaPlayer,\n options: { title },\n attributes: { src },\n });\n }\n\n /**\n * Insert the Monaco Code Editor app.\n * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.\n */\n insertCodeEditor() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n /**\n * Insert the Countdown app.\n * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.\n */\n insertCountdown() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n /**\n * Insert the GeoGebra app.\n * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.\n */\n insertGeoGebra() {\n this._assertNotDestroyed();\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n}\n\nexport interface FastboardOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n joinRoom: Omit<JoinRoomParams, \"useMultiViews\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"> & {\n callbacks?: Partial<Omit<RoomCallbacks, \"onCanRedoStepsUpdate\" | \"onCanUndoStepsUpdate\">>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardApp instance.\n * @example\n * let app = await createFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * joinRoom: {\n * uid: unique_id,\n * uuid: import.meta.env.VITE_ROOM_UUID,\n * roomToken: import.meta.env.VITE_ROOM_TOKEN,\n * },\n * })\n */\nexport async function createFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n joinRoom: { callbacks, ...joinRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n const hotKeys = joinRoomParams.hotKeys || {\n ...DefaultHotKeys,\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n };\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const room = await sdk.joinRoom(\n {\n floatBar: true,\n hotKeys,\n ...ensure_official_plugins(joinRoomParams),\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(room);\n\n const manager = await WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room,\n });\n\n manager.mainView.setCameraBound({\n minContentMode: contentModeScale(0.3),\n maxContentMode: contentModeScale(3),\n });\n\n return new FastboardApp<TEventData>(sdk, room, manager, hotKeys, syncedStore);\n}\n","import type { JoinRoomParams, ReplayRoomParams } from \"white-web-sdk\";\nimport type { PublicEvent } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\n\nexport function ensure_official_plugins<T extends JoinRoomParams | ReplayRoomParams>(joinRoom: T): T {\n const plugins = new Set(joinRoom.invisiblePlugins || []);\n plugins.add(WindowManager);\n plugins.add(SyncedStorePlugin);\n joinRoom.invisiblePlugins = [...plugins];\n return joinRoom;\n}\n\nexport function transform_app_status(status: PublicEvent[\"loadApp\"][\"status\"]) {\n return status === \"start\" ? \"loading\" : status === \"failed\" ? \"failed\" : \"idle\";\n}\n","import type { RegisterParams } from \"@netless/window-manager\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport SlideApp, { apps, addHooks, previewSlide } from \"@netless/app-slide\";\n\nexport type {\n AppOptions as SlideOptions,\n AppResult as SlideController,\n PreviewParams,\n SlidePreviewer,\n} from \"@netless/app-slide\";\nexport { previewSlide, SlideApp, addHooks as addSlideHooks, apps as slideApps };\n\nexport interface AppsConfig {\n [kind: string]: Omit<RegisterParams, \"kind\">;\n}\n\nconst DefaultApps: AppsConfig = {\n Monaco: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js\",\n },\n Countdown: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js\",\n },\n GeoGebra: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js\",\n appOptions: {\n HTML5Codebase: \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n },\n EmbeddedPage: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js\",\n },\n Plyr: {\n src: \"https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js\",\n },\n};\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: { debug: false },\n src: SlideApp,\n addHooks,\n});\n\nfor (const kind in DefaultApps) {\n if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {\n const options = DefaultApps[kind];\n WindowManager.register({ kind, ...options });\n }\n}\n\nexport const register = WindowManager.register.bind(WindowManager);\n\ndeclare let __NAME__: string, __VERSION__: string;\n\nexport const version = __VERSION__;\n\nif (typeof window !== \"undefined\") {\n let str = (window as { __netlessUA?: string }).__netlessUA || \"\";\n str += ` ${__NAME__}@${version} `;\n (window as { __netlessUA?: string }).__netlessUA = str;\n}\n","import type { MountParams, NetlessApp, PublicEvent } from \"@netless/window-manager\";\nimport type {\n Player,\n PlayerPhase as PlayerPhaseEnum,\n PlayerCallbacks,\n PlayerState,\n PlayerSeekingResult,\n ReplayRoomParams,\n ViewCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { SyncedStore } from \"@netless/synced-store\";\n\nimport { WhiteWebSdk } from \"white-web-sdk\";\nimport { WindowManager } from \"@netless/window-manager\";\nimport { SyncedStorePlugin } from \"@netless/synced-store\";\nimport { readable, writable } from \"../utils\";\nimport { ensure_official_plugins } from \"../internal\";\nimport { register } from \"../behaviors\";\n\nclass FastboardPlayerBase<TEventData extends Record<string, any> = any> {\n public constructor(\n readonly sdk: WhiteWebSdk,\n readonly player: Player,\n readonly manager: WindowManager,\n readonly syncedStore: SyncedStore<TEventData>\n ) {}\n\n protected _destroyed = false;\n protected _assertNotDestroyed() {\n if (this._destroyed) {\n throw new Error(\"FastboardApp has been destroyed\");\n }\n }\n\n protected _addPlayerListener<K extends keyof PlayerCallbacks>(name: K, listener: PlayerCallbacks[K]) {\n this._assertNotDestroyed();\n this.player.callbacks.on(name, listener);\n return () => this.player.callbacks.off(name, listener);\n }\n\n protected _addManagerListener<K extends keyof PublicEvent>(\n name: K,\n listener: (value: PublicEvent[K]) => void\n ) {\n this._assertNotDestroyed();\n this.manager.emitter.on(name, listener);\n return () => this.manager.emitter.off(name, listener);\n }\n\n protected _addMainViewListener<K extends keyof ViewCallbacks>(name: K, listener: ViewCallbacks[K]) {\n this._assertNotDestroyed();\n this.manager.mainView.callbacks.on(name, listener);\n return () => this.manager.mainView.callbacks.off(name, listener);\n }\n\n public destroy() {\n this._destroyed = true;\n this.manager.destroy();\n return this.player.callbacks.off();\n }\n}\n\ntype PlayerPhase = `${PlayerPhaseEnum}`;\n\nexport type { PlayerPhase, PlayerSeekingResult };\n\nexport class FastboardPlayer<\n TEventData extends Record<string, any> = any\n> extends FastboardPlayerBase<TEventData> {\n /**\n * Render this player to some DOM.\n */\n bindContainer(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindContainer(container);\n }\n\n /**\n * Move window-manager's collector to some place.\n */\n bindCollector(container: HTMLElement) {\n this._assertNotDestroyed();\n this.manager.bindCollectorContainer(container);\n }\n\n /**\n * Player current time in milliseconds.\n */\n readonly currentTime = writable(\n this.player.progressTime,\n set => {\n set(this.player.progressTime);\n return this._addPlayerListener(\"onProgressTimeChanged\", set);\n },\n this.player.seekToProgressTime.bind(this.player)\n );\n\n /**\n * Player state, like \"is it playing?\".\n */\n readonly phase = readable<PlayerPhase>(this.player.phase, set => {\n set(this.player.phase);\n return this._addPlayerListener(\"onPhaseChanged\", set);\n });\n\n /**\n * Will become true after buffering.\n */\n readonly canplay = readable(this.player.isPlayable, set => {\n set(this.player.isPlayable);\n return this._addPlayerListener(\"onIsPlayableChanged\", set);\n });\n\n /** @internal */\n private _setPlaybackRate!: (value: number) => void;\n /**\n * Playback speed, default `1`.\n */\n readonly playbackRate = writable(\n this.player.playbackSpeed,\n set => {\n this._setPlaybackRate = set;\n set(this.player.playbackSpeed);\n },\n value => {\n this.player.playbackSpeed = value;\n this._setPlaybackRate(value);\n }\n );\n\n /**\n * Playback duration in milliseconds.\n */\n readonly duration = readable(this.player.timeDuration, set => {\n set(this.player.timeDuration);\n });\n\n /**\n * Get state of room at that time, like \"who was in the room?\".\n */\n readonly state = readable<PlayerState>(this.player.state, set => {\n set(this.player.state);\n return this._addPlayerListener(\"onPlayerStateChanged\", () => set(this.player.state));\n });\n\n /**\n * Seek to some time in milliseconds.\n */\n seek(timestamp: number) {\n this._assertNotDestroyed();\n return this.player.seekToProgressTime(timestamp);\n }\n\n /**\n * Change player state to playing.\n */\n play() {\n this._assertNotDestroyed();\n this.player.play();\n }\n\n /**\n * Change player state to paused.\n */\n pause() {\n this._assertNotDestroyed();\n this.player.pause();\n }\n\n /**\n * Change player state to stopped.\n */\n stop() {\n this._assertNotDestroyed();\n this.player.stop();\n }\n\n /**\n * Set playback speed, a shortcut for `speed.set(x)`.\n */\n setPlaybackRate(value: number) {\n this._assertNotDestroyed();\n this.playbackRate.set(value);\n }\n}\n\nexport interface FastboardReplayOptions {\n sdkConfig: Omit<WhiteWebSdkConfiguration, \"useMobXState\"> & {\n region: NonNullable<WhiteWebSdkConfiguration[\"region\"]>;\n };\n replayRoom: Omit<ReplayRoomParams, \"useMultiViews\"> & {\n callbacks?: Partial<PlayerCallbacks>;\n };\n managerConfig?: Omit<MountParams, \"room\">;\n netlessApps?: NetlessApp[];\n}\n\n/**\n * Create a FastboardPlayer instance.\n * @example\n * let player = await replayFastboard({\n * sdkConfig: {\n * appIdentifier: import.meta.env.VITE_APPID,\n * region: 'cn-hz',\n * },\n * replayRoom: {\n * room: \"room uuid\",\n * roomToken: \"NETLESSROOM_...\",\n * beginTimestamp: 1646619090394,\n * duration: 70448,\n * },\n * })\n */\nexport async function replayFastboard<TEventData extends Record<string, any> = any>({\n sdkConfig,\n replayRoom: { callbacks, ...replayRoomParams },\n managerConfig,\n netlessApps,\n}: FastboardReplayOptions) {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n if (netlessApps) {\n netlessApps.forEach(app => {\n register({ kind: app.kind, src: app });\n });\n }\n\n const player = await sdk.replayRoom(\n {\n ...ensure_official_plugins(replayRoomParams),\n useMultiViews: true,\n },\n callbacks\n );\n\n const syncedStore = await SyncedStorePlugin.init<TEventData>(player);\n\n const managerPromise = WindowManager.mount({\n cursor: true,\n ...managerConfig,\n room: player,\n });\n\n player.play();\n const manager = await managerPromise;\n player.pause();\n await player.seekToProgressTime(0);\n\n return new FastboardPlayer<TEventData>(sdk, player, manager, syncedStore);\n}\n","import type { PublicEvent, WindowManager } from \"@netless/window-manager\";\nimport type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from \"white-web-sdk\";\n\nexport function addRoomListener<K extends keyof RoomCallbacks>(\n room: Room,\n name: K,\n listener: RoomCallbacks[K]\n) {\n room.callbacks.on(name, listener);\n return () => room.callbacks.off(name, listener);\n}\n\nexport function addPlayerListener<K extends keyof PlayerCallbacks>(\n player: Player,\n name: K,\n listener: PlayerCallbacks[K]\n) {\n player.callbacks.on(name, listener);\n return () => player.callbacks.off(name, listener);\n}\n\nexport function addViewListener<K extends keyof ViewCallbacks>(\n view: View,\n name: K,\n listener: (value: ViewCallbacks[K]) => void\n) {\n view.callbacks.on(name, listener);\n return () => view.callbacks.off(name, listener);\n}\n\nexport function addManagerListener<K extends keyof PublicEvent>(\n manager: WindowManager,\n name: K,\n listener: (value: PublicEvent[K]) => void\n): () => void {\n return manager.emitter.on(name, listener);\n}\n","import type { AppResult } from \"@netless/app-slide\";\nimport type { FastboardApp, WindowManager } from \"../impl\";\n\nexport interface DocsEventOptions {\n /** If provided, will dispatch to the specific app. Default to the focused app. */\n appId?: string;\n /** Used by `jumpToPage` event, range from 1 to total pages count. */\n page?: number;\n}\n\n/**\n * Send specific command to the static docs / slide app.\n * Only works for apps that were created by `insertDocs()`.\n *\n * Returns false if failed to find the app or not writable.\n *\n * For static docs, `nextPage` equals to `nextStep`, as with `prevPage` and `prevStep`.\n *\n * @example\n * ```js\n * // send \"next page\" to the focused app\n * dispatchDocsEvent(fastboard, \"nextPage\")\n *\n * // send \"prev page\" to some app\n * dispatchDocsEvent(fastboard, \"prevPage\", {appId:\"Slide-1a2b3c4d\"})\n * ```\n */\nexport function dispatchDocsEvent(\n fastboard: FastboardApp | WindowManager,\n event: \"prevPage\" | \"nextPage\" | \"prevStep\" | \"nextStep\" | \"jumpToPage\",\n options: DocsEventOptions = {}\n): boolean {\n const manager = \"manager\" in fastboard ? fastboard.manager : fastboard;\n\n const appId = options.appId || manager.focused;\n if (!appId) {\n console.warn(\"not found \" + (options.appId || \"focused app\"));\n return false;\n }\n\n let page: number | undefined, input: HTMLInputElement | null;\n\n // Click the DOM elements for static docs\n if (appId.startsWith(\"DocsViewer-\")) {\n const dom = manager.queryOne(appId)?.box?.$footer;\n if (!dom) {\n console.warn(\"not found app with id \" + appId);\n return false;\n }\n\n const click = (el: Element | null) => {\n el && el.dispatchEvent(new MouseEvent(\"click\"));\n };\n\n switch (event) {\n case \"prevPage\":\n case \"prevStep\":\n click(dom.querySelector('button[class$=\"btn-page-back\"]'));\n break;\n case \"nextPage\":\n case \"nextStep\":\n click(dom.querySelector('button[class$=\"btn-page-next\"]'));\n break;\n case \"jumpToPage\":\n page = options.page;\n input = dom.querySelector('input[class$=\"page-number-input\"]');\n if (!input || typeof page !== \"number\") {\n console.warn(\"failed to jump\" + (page ? \" to page \" + page : \"\"));\n return false;\n }\n input.value = \"\" + page;\n input.dispatchEvent(new InputEvent(\"change\"));\n break;\n default:\n console.warn(\"unknown event \" + event);\n return false;\n }\n\n return true;\n }\n\n // Check controller for slide docs\n else if (appId.startsWith(\"Slide-\")) {\n const app = manager.queryOne(appId)?.appResult as unknown as AppResult | undefined;\n if (!app) {\n console.warn(\"not found app with id \" + appId);\n return false;\n }\n\n switch (event) {\n case \"prevPage\":\n return app.prevPage();\n case \"nextPage\":\n return app.nextPage();\n case \"prevStep\":\n return app.prevStep();\n case \"nextStep\":\n return app.nextStep();\n case \"jumpToPage\":\n page = options.page;\n if (typeof page !== \"number\") {\n console.warn(\"failed to jump\" + (page ? \" to page \" + page : \"\"));\n return false;\n }\n return app.jumpToPage(page);\n default:\n console.warn(\"unknown event \" + event);\n return false;\n }\n }\n\n // No support for any other kind\n else {\n console.warn(\"not supported app \" + appId);\n return false;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/fastboard-core",
3
- "version": "0.3.6",
3
+ "version": "0.3.8-alpha.0",
4
4
  "description": "A tiny wrapper of white-web-sdk and @netless/window-manager.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -9,15 +9,15 @@
9
9
  ],
10
10
  "repository": "netless-io/fastboard",
11
11
  "dependencies": {
12
- "@netless/app-slide": "^0.2.2",
13
- "@netless/synced-store": "^2.0.2"
12
+ "@netless/app-slide": "^0.2.28",
13
+ "@netless/synced-store": "^2.0.7"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "@netless/window-manager": ">=0.4.0",
17
17
  "white-web-sdk": ">=2.16.0"
18
18
  },
19
19
  "devDependencies": {
20
- "white-web-sdk": "^2.16.27"
20
+ "white-web-sdk": "^2.16.40"
21
21
  },
22
22
  "scripts": {
23
23
  "cleanup": "rimraf dist",
@@ -4,7 +4,7 @@ import SlideApp, { apps, addHooks, previewSlide } from "@netless/app-slide";
4
4
 
5
5
  export type {
6
6
  AppOptions as SlideOptions,
7
- Controller as SlideController,
7
+ AppResult as SlideController,
8
8
  PreviewParams,
9
9
  SlidePreviewer,
10
10
  } from "@netless/app-slide";
@@ -16,7 +16,7 @@ export interface AppsConfig {
16
16
 
17
17
  const DefaultApps: AppsConfig = {
18
18
  Monaco: {
19
- src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.12/dist/main.iife.js",
19
+ src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js",
20
20
  },
21
21
  Countdown: {
22
22
  src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js",
@@ -0,0 +1,117 @@
1
+ import type { AppResult } from "@netless/app-slide";
2
+ import type { FastboardApp, WindowManager } from "../impl";
3
+
4
+ export interface DocsEventOptions {
5
+ /** If provided, will dispatch to the specific app. Default to the focused app. */
6
+ appId?: string;
7
+ /** Used by `jumpToPage` event, range from 1 to total pages count. */
8
+ page?: number;
9
+ }
10
+
11
+ /**
12
+ * Send specific command to the static docs / slide app.
13
+ * Only works for apps that were created by `insertDocs()`.
14
+ *
15
+ * Returns false if failed to find the app or not writable.
16
+ *
17
+ * For static docs, `nextPage` equals to `nextStep`, as with `prevPage` and `prevStep`.
18
+ *
19
+ * @example
20
+ * ```js
21
+ * // send "next page" to the focused app
22
+ * dispatchDocsEvent(fastboard, "nextPage")
23
+ *
24
+ * // send "prev page" to some app
25
+ * dispatchDocsEvent(fastboard, "prevPage", {appId:"Slide-1a2b3c4d"})
26
+ * ```
27
+ */
28
+ export function dispatchDocsEvent(
29
+ fastboard: FastboardApp | WindowManager,
30
+ event: "prevPage" | "nextPage" | "prevStep" | "nextStep" | "jumpToPage",
31
+ options: DocsEventOptions = {}
32
+ ): boolean {
33
+ const manager = "manager" in fastboard ? fastboard.manager : fastboard;
34
+
35
+ const appId = options.appId || manager.focused;
36
+ if (!appId) {
37
+ console.warn("not found " + (options.appId || "focused app"));
38
+ return false;
39
+ }
40
+
41
+ let page: number | undefined, input: HTMLInputElement | null;
42
+
43
+ // Click the DOM elements for static docs
44
+ if (appId.startsWith("DocsViewer-")) {
45
+ const dom = manager.queryOne(appId)?.box?.$footer;
46
+ if (!dom) {
47
+ console.warn("not found app with id " + appId);
48
+ return false;
49
+ }
50
+
51
+ const click = (el: Element | null) => {
52
+ el && el.dispatchEvent(new MouseEvent("click"));
53
+ };
54
+
55
+ switch (event) {
56
+ case "prevPage":
57
+ case "prevStep":
58
+ click(dom.querySelector('button[class$="btn-page-back"]'));
59
+ break;
60
+ case "nextPage":
61
+ case "nextStep":
62
+ click(dom.querySelector('button[class$="btn-page-next"]'));
63
+ break;
64
+ case "jumpToPage":
65
+ page = options.page;
66
+ input = dom.querySelector('input[class$="page-number-input"]');
67
+ if (!input || typeof page !== "number") {
68
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
69
+ return false;
70
+ }
71
+ input.value = "" + page;
72
+ input.dispatchEvent(new InputEvent("change"));
73
+ break;
74
+ default:
75
+ console.warn("unknown event " + event);
76
+ return false;
77
+ }
78
+
79
+ return true;
80
+ }
81
+
82
+ // Check controller for slide docs
83
+ else if (appId.startsWith("Slide-")) {
84
+ const app = manager.queryOne(appId)?.appResult as unknown as AppResult | undefined;
85
+ if (!app) {
86
+ console.warn("not found app with id " + appId);
87
+ return false;
88
+ }
89
+
90
+ switch (event) {
91
+ case "prevPage":
92
+ return app.prevPage();
93
+ case "nextPage":
94
+ return app.nextPage();
95
+ case "prevStep":
96
+ return app.prevStep();
97
+ case "nextStep":
98
+ return app.nextStep();
99
+ case "jumpToPage":
100
+ page = options.page;
101
+ if (typeof page !== "number") {
102
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
103
+ return false;
104
+ }
105
+ return app.jumpToPage(page);
106
+ default:
107
+ console.warn("unknown event " + event);
108
+ return false;
109
+ }
110
+ }
111
+
112
+ // No support for any other kind
113
+ else {
114
+ console.warn("not supported app " + appId);
115
+ return false;
116
+ }
117
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./listen";
2
+ export * from "./docs";
@@ -0,0 +1,37 @@
1
+ import type { PublicEvent, WindowManager } from "@netless/window-manager";
2
+ import type { Player, PlayerCallbacks, Room, RoomCallbacks, View, ViewCallbacks } from "white-web-sdk";
3
+
4
+ export function addRoomListener<K extends keyof RoomCallbacks>(
5
+ room: Room,
6
+ name: K,
7
+ listener: RoomCallbacks[K]
8
+ ) {
9
+ room.callbacks.on(name, listener);
10
+ return () => room.callbacks.off(name, listener);
11
+ }
12
+
13
+ export function addPlayerListener<K extends keyof PlayerCallbacks>(
14
+ player: Player,
15
+ name: K,
16
+ listener: PlayerCallbacks[K]
17
+ ) {
18
+ player.callbacks.on(name, listener);
19
+ return () => player.callbacks.off(name, listener);
20
+ }
21
+
22
+ export function addViewListener<K extends keyof ViewCallbacks>(
23
+ view: View,
24
+ name: K,
25
+ listener: (value: ViewCallbacks[K]) => void
26
+ ) {
27
+ view.callbacks.on(name, listener);
28
+ return () => view.callbacks.off(name, listener);
29
+ }
30
+
31
+ export function addManagerListener<K extends keyof PublicEvent>(
32
+ manager: WindowManager,
33
+ name: K,
34
+ listener: (value: PublicEvent[K]) => void
35
+ ): () => void {
36
+ return manager.emitter.on(name, listener);
37
+ }
@@ -36,7 +36,7 @@ import {
36
36
  import { ensure_official_plugins, transform_app_status } from "../internal";
37
37
  import { register } from "../behaviors";
38
38
 
39
- class FastboardAppBase<TEventData = any> {
39
+ class FastboardAppBase<TEventData extends Record<string, any> = any> {
40
40
  public constructor(
41
41
  readonly sdk: WhiteWebSdk,
42
42
  readonly room: Room,
@@ -149,6 +149,26 @@ export interface InsertDocsDynamic {
149
149
 
150
150
  export type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;
151
151
 
152
+ export interface ProjectorResponse {
153
+ uuid: string;
154
+ status: "Waiting" | "Converting" | "Finished" | "Fail";
155
+ type: "dynamic" | "static";
156
+ /** 0..100 */
157
+ convertedPercentage: number;
158
+ /** https://example.org/path/to/dynamicConvert, only when type=dynamic */
159
+ prefix?: string;
160
+ pageCount?: number;
161
+ /** {1:"{prefix}/{taskId}/preview/1.png"}, only when type=dynamic and preview=true */
162
+ previews?: Record<number, string>;
163
+ /** {prefix}/{taskId}/jsonOutput/note.json */
164
+ note?: string;
165
+ /** {1:{width,height,url}}, only when type=static */
166
+ images?: Record<number, { width: number; height: number; url: string }>;
167
+ /** 20xxxxx */
168
+ errorCode?: string;
169
+ errorMessage?: string;
170
+ }
171
+
152
172
  export type SetMemberStateFn = (partialMemberState: Partial<MemberState>) => void;
153
173
 
154
174
  export type RoomStateChanged = (diff: Partial<RoomState>) => void;
@@ -162,7 +182,7 @@ export interface AppsStatus {
162
182
  };
163
183
  }
164
184
 
165
- export class FastboardApp<TEventData = any> extends FastboardAppBase<TEventData> {
185
+ export class FastboardApp<TEventData extends Record<string, any> = any> extends FastboardAppBase<TEventData> {
166
186
  /**
167
187
  * Render this app to some DOM.
168
188
  */
@@ -272,6 +292,7 @@ export class FastboardApp<TEventData = any> extends FastboardAppBase<TEventData>
272
292
  return this._addManagerListener("mainViewScenesLengthChange", set);
273
293
  });
274
294
 
295
+ /** @internal */
275
296
  private _appsStatus: AppsStatus = {};
276
297
  /**
277
298
  * Apps status.
@@ -451,6 +472,12 @@ export class FastboardApp<TEventData = any> extends FastboardAppBase<TEventData>
451
472
  */
452
473
  insertDocs(filename: string, status: ConversionResponse): Promise<string | undefined>;
453
474
 
475
+ /**
476
+ * Insert PDF/PPTX from projector conversion result.
477
+ * @param response https://developer.netless.link/server-zh/home/server-projector#get-%E6%9F%A5%E8%AF%A2%E4%BB%BB%E5%8A%A1%E8%BD%AC%E6%8D%A2%E8%BF%9B%E5%BA%A6
478
+ */
479
+ insertDocs(filename: string, response: ProjectorResponse): Promise<string | undefined>;
480
+
454
481
  /**
455
482
  * Manual way.
456
483
  * @example
@@ -463,13 +490,13 @@ export class FastboardApp<TEventData = any> extends FastboardAppBase<TEventData>
463
490
  */
464
491
  insertDocs(params: InsertDocsParams): Promise<string | undefined>;
465
492
 
466
- insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse) {
493
+ insertDocs(arg1: string | InsertDocsParams, arg2?: ConversionResponse | ProjectorResponse) {
467
494
  this._assertNotDestroyed();
468
495
  if (typeof arg1 === "object" && "fileType" in arg1) {
469
496
  return this._insertDocsImpl(arg1);
470
497
  } else if (arg2 && arg2.status !== "Finished") {
471
498
  throw new Error("FastboardApp cannot insert a converting doc.");
472
- } else if (arg2 && arg2.progress) {
499
+ } else if (arg2 && "progress" in arg2) {
473
500
  const title = arg1;
474
501
  const scenePath = `/${arg2.uuid}/${genUID()}`;
475
502
  const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);
@@ -479,9 +506,27 @@ export class FastboardApp<TEventData = any> extends FastboardAppBase<TEventData>
479
506
  } else {
480
507
  return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes: scenes1, title });
481
508
  }
509
+ } else if (arg2 && arg2.prefix) {
510
+ const title = arg1;
511
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
512
+ const taskId = arg2.uuid;
513
+ const url = arg2.prefix;
514
+ this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url });
515
+ } else if (arg2 && arg2.images) {
516
+ const title = arg1;
517
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
518
+ const scenes: SceneDefinition[] = [];
519
+ for (const name in arg2.images) {
520
+ const { width, height, url } = arg2.images[name];
521
+ scenes.push({ name, ppt: { width, height, src: url } });
522
+ }
523
+ this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title });
524
+ } else {
525
+ throw new Error("Invalid input: not found 'progress', 'prefix' nor 'images'");
482
526
  }
483
527
  }
484
528
 
529
+ /** @internal */
485
530
  private _insertDocsImpl({ fileType, scenePath, title, scenes, ...attributes }: InsertDocsParams) {
486
531
  this._assertNotDestroyed();
487
532
  switch (fileType) {
@@ -556,7 +601,7 @@ export interface FastboardOptions {
556
601
  region: NonNullable<WhiteWebSdkConfiguration["region"]>;
557
602
  };
558
603
  joinRoom: Omit<JoinRoomParams, "useMultiViews" | "disableNewPencil" | "disableMagixEventDispatchLimit"> & {
559
- callbacks?: Partial<RoomCallbacks>;
604
+ callbacks?: Partial<Omit<RoomCallbacks, "onCanRedoStepsUpdate" | "onCanUndoStepsUpdate">>;
560
605
  };
561
606
  managerConfig?: Omit<MountParams, "room">;
562
607
  netlessApps?: NetlessApp[];
@@ -577,7 +622,7 @@ export interface FastboardOptions {
577
622
  * },
578
623
  * })
579
624
  */
580
- export async function createFastboard<TEventData = any>({
625
+ export async function createFastboard<TEventData extends Record<string, any> = any>({
581
626
  sdkConfig,
582
627
  joinRoom: { callbacks, ...joinRoomParams },
583
628
  managerConfig,
@@ -18,7 +18,7 @@ import { readable, writable } from "../utils";
18
18
  import { ensure_official_plugins } from "../internal";
19
19
  import { register } from "../behaviors";
20
20
 
21
- class FastboardPlayerBase<TEventData = any> {
21
+ class FastboardPlayerBase<TEventData extends Record<string, any> = any> {
22
22
  public constructor(
23
23
  readonly sdk: WhiteWebSdk,
24
24
  readonly player: Player,
@@ -65,7 +65,9 @@ type PlayerPhase = `${PlayerPhaseEnum}`;
65
65
 
66
66
  export type { PlayerPhase, PlayerSeekingResult };
67
67
 
68
- export class FastboardPlayer<TEventData = any> extends FastboardPlayerBase<TEventData> {
68
+ export class FastboardPlayer<
69
+ TEventData extends Record<string, any> = any
70
+ > extends FastboardPlayerBase<TEventData> {
69
71
  /**
70
72
  * Render this player to some DOM.
71
73
  */
@@ -110,6 +112,7 @@ export class FastboardPlayer<TEventData = any> extends FastboardPlayerBase<TEven
110
112
  return this._addPlayerListener("onIsPlayableChanged", set);
111
113
  });
112
114
 
115
+ /** @internal */
113
116
  private _setPlaybackRate!: (value: number) => void;
114
117
  /**
115
118
  * Playback speed, default `1`.
@@ -209,7 +212,7 @@ export interface FastboardReplayOptions {
209
212
  * },
210
213
  * })
211
214
  */
212
- export async function replayFastboard<TEventData = any>({
215
+ export async function replayFastboard<TEventData extends Record<string, any> = any>({
213
216
  sdkConfig,
214
217
  replayRoom: { callbacks, ...replayRoomParams },
215
218
  managerConfig,
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./utils";
2
2
  export * from "./impl";
3
3
  export * from "./behaviors";
4
+ export * from "./helpers";
package/src/utils/misc.ts CHANGED
@@ -21,15 +21,13 @@ export function makeSlideParams(scenes: SceneDefinition[]) {
21
21
  // make sure scenesWithoutPPT.length === scenes.length
22
22
  emptyScenes.push({ name });
23
23
 
24
- if (!ppt || !ppt.src.startsWith("ppt")) {
25
- continue;
26
- }
24
+ if (!ppt || !ppt.src.startsWith("ppt")) continue;
25
+
27
26
  const match = pptSrcRE.exec(ppt.src);
28
- if (!match || !match.groups) {
29
- continue;
30
- }
27
+ if (!match || !match.groups) continue;
28
+
31
29
  taskId = match.groups.taskId;
32
- url = "https" + match.groups.prefix;
30
+ url = `https${match.groups.prefix}`;
33
31
  break;
34
32
  }
35
33