@netless/fastboard 0.1.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,393 +1,7 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __objRest = (source, exclude) => {
21
- var target = {};
22
- for (var prop in source)
23
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
- target[prop] = source[prop];
25
- if (source != null && __getOwnPropSymbols)
26
- for (var prop of __getOwnPropSymbols(source)) {
27
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
- target[prop] = source[prop];
29
- }
30
- return target;
31
- };
32
-
33
- // src/index.ts
34
- import { DefaultHotKeys, WhiteWebSdk } from "white-web-sdk";
35
- import { WindowManager as WindowManager3 } from "@netless/window-manager";
36
-
37
- // src/register-apps.ts
38
- import { WindowManager } from "@netless/window-manager";
39
- WindowManager.register({
40
- kind: "Slide",
41
- appOptions: {
42
- debug: false
43
- },
44
- src: async () => {
45
- var _a;
46
- const app = await import("@netless/app-slide");
47
- return (_a = app.default) != null ? _a : app;
48
- }
49
- });
50
- WindowManager.register({
51
- kind: "Monaco",
52
- src: "https://cdn.jsdelivr.net/npm/@netless/app-monaco@latest/dist/main.iife.js"
53
- });
54
- WindowManager.register({
55
- kind: "Countdown",
56
- src: "https://cdn.jsdelivr.net/npm/@netless/app-countdown@latest/dist/main.iife.js"
57
- });
58
- WindowManager.register({
59
- kind: "GeoGebra",
60
- src: "https://cdn.jsdelivr.net/npm/@netless/app-monaco@geogebra/dist/main.iife.js",
61
- appOptions: {
62
- HTML5Codebase: "https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d"
63
- }
64
- });
65
-
66
- // src/core.ts
67
- import { BuiltinApps } from "@netless/window-manager";
68
-
69
- // src/emitter.ts
70
- var FastboardEmitter = class {
71
- constructor() {
72
- this.listeners = /* @__PURE__ */ new Set();
73
- }
74
- get length() {
75
- return this.listeners.size;
76
- }
77
- dispatch(message) {
78
- this.listeners.forEach((callback) => callback(message));
79
- }
80
- addListener(listener) {
81
- this.listeners.add(listener);
82
- }
83
- removeListener(listener) {
84
- this.listeners.delete(listener);
85
- }
86
- };
87
-
88
- // src/utils.ts
89
- import { WindowManager as WindowManager2 } from "@netless/window-manager";
90
- function noop() {
91
- }
92
- function getImageSize(url, fallback) {
93
- return new Promise((resolve) => {
94
- const img = new Image();
95
- img.onload = () => resolve(img);
96
- img.onerror = () => resolve(fallback);
97
- img.src = url;
98
- });
99
- }
100
- function makeSlideParams(scenes) {
101
- const emptyScenes = [];
102
- let taskId = "";
103
- let url = "";
104
- const pptSrcRE = /^pptx?(?<prefix>:\/\/\S+?dynamicConvert)\/(?<taskId>\w+)\//;
105
- for (const { name, ppt } of scenes) {
106
- emptyScenes.push({ name });
107
- if (!ppt || !ppt.src.startsWith("ppt")) {
108
- continue;
109
- }
110
- const match = pptSrcRE.exec(ppt.src);
111
- if (!match || !match.groups) {
112
- continue;
113
- }
114
- taskId = match.groups.taskId;
115
- url = "https" + match.groups.prefix;
116
- break;
117
- }
118
- return { emptyScenes, taskId, url };
119
- }
120
- function convertedFileToScene(f, i) {
121
- return {
122
- name: String(i + 1),
123
- ppt: {
124
- src: f.conversionFileUrl,
125
- width: f.width,
126
- height: f.height,
127
- previewURL: f.preview
128
- }
129
- };
130
- }
131
- function ensureWindowManager(joinRoom) {
132
- if (!joinRoom.invisiblePlugins || !joinRoom.invisiblePlugins.includes(WindowManager2)) {
133
- joinRoom.invisiblePlugins = [...joinRoom.invisiblePlugins || [], WindowManager2];
134
- }
135
- return joinRoom;
136
- }
137
- var SOUP = "!#%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
138
- var SOUP_LEN = SOUP.length;
139
- var ID_LEN = 20;
140
- var reusedIdCarrier = Array(ID_LEN);
141
- function genUID() {
142
- for (let i = 0; i < ID_LEN; i++) {
143
- reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);
144
- }
145
- return reusedIdCarrier.join("");
146
- }
147
-
148
- // src/value.ts
149
- function createValue(value, effect, setValue = noop) {
150
- const emitter = new FastboardEmitter();
151
- function set(newValue) {
152
- emitter.dispatch(value = newValue);
153
- }
154
- const dispose = effect(set) || noop;
155
- function subscribe(callback) {
156
- emitter.addListener(callback);
157
- callback(value);
158
- return () => emitter.removeListener(callback);
159
- }
160
- function reaction(callback) {
161
- emitter.addListener(callback);
162
- return () => emitter.removeListener(callback);
163
- }
164
- return { value, subscribe, reaction, setValue, dispose };
165
- }
166
-
167
- // src/base.ts
168
- var FastboardAppBase = class {
169
- constructor(sdk, room, manager, hotKeys) {
170
- this.sdk = sdk;
171
- this.room = room;
172
- this.manager = manager;
173
- this.hotKeys = hotKeys;
174
- this._disposers = [];
175
- this._destroyed = false;
176
- this.createValue = (...args) => {
177
- const value = createValue(...args);
178
- this._disposers.push(value.dispose);
179
- return value;
180
- };
181
- }
182
- _assertNotDestroyed() {
183
- if (this._destroyed) {
184
- throw new Error("[FastboardApp] Can not call any method on destroyed FastboardApp.");
185
- }
186
- }
187
- _addRoomListener(name, listener) {
188
- this._assertNotDestroyed();
189
- this.room.callbacks.on(name, listener);
190
- return () => this.room.callbacks.off(name, listener);
191
- }
192
- _addManagerListener(name, set) {
193
- this._assertNotDestroyed();
194
- this.manager.emitter.on(name, set);
195
- return () => this.manager.emitter.off(name, set);
196
- }
197
- _addMainViewListener(name, listener) {
198
- this._assertNotDestroyed();
199
- this.manager.mainView.callbacks.on(name, listener);
200
- return () => this.manager.mainView.callbacks.off(name, listener);
201
- }
202
- destroy() {
203
- this._disposers.forEach((dispose) => dispose());
204
- this._disposers.length = 0;
205
- this._destroyed = true;
206
- this.manager.destroy();
207
- return this.room.disconnect();
208
- }
209
- };
210
-
211
- // src/core.ts
212
- var FastboardApp = class extends FastboardAppBase {
213
- constructor() {
214
- super(...arguments);
215
- this.writable = this.createValue(this.room.isWritable, (set) => this._addRoomListener("onEnableWriteNowChanged", () => set(this.room.isWritable)), this.room.setWritable.bind(this.room));
216
- this.boxState = this.createValue(this.manager.boxState, (set) => this._addManagerListener("boxStateChange", set));
217
- this.focusedApp = this.createValue(this.manager.focused, (set) => this._addManagerListener("focusedChange", set));
218
- this.canRedoSteps = this.createValue(this.manager.mainView.canRedoSteps, (set) => this._addMainViewListener("onCanRedoStepsUpdate", set));
219
- this.canUndoSteps = this.createValue(this.manager.mainView.canUndoSteps, (set) => this._addMainViewListener("onCanUndoStepsUpdate", set));
220
- this.camera = this.createValue(this.manager.mainView.camera, (set) => this._addMainViewListener("onCameraUpdated", set), this.manager.moveCamera.bind(this.manager));
221
- 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));
222
- }
223
- bindContainer(container) {
224
- this._assertNotDestroyed();
225
- this.manager.bindContainer(container);
226
- }
227
- bindCollector(container) {
228
- this._assertNotDestroyed();
229
- this.manager.bindCollectorContainer(container);
230
- }
231
- undo() {
232
- this._assertNotDestroyed();
233
- this.manager.mainView.undo();
234
- }
235
- redo() {
236
- this._assertNotDestroyed();
237
- this.manager.mainView.redo();
238
- }
239
- moveCamera(camera) {
240
- this._assertNotDestroyed();
241
- this.manager.moveCamera(camera);
242
- }
243
- moveCameraToContain(rectangle) {
244
- this._assertNotDestroyed();
245
- this.manager.moveCameraToContain(rectangle);
246
- }
247
- cleanCurrentScene() {
248
- this._assertNotDestroyed();
249
- this.manager.mainView.cleanCurrentScene();
250
- }
251
- setAppliance(appliance, shape) {
252
- this._assertNotDestroyed();
253
- this.manager.mainView.setMemberState({ currentApplianceName: appliance, shapeType: shape });
254
- }
255
- setStrokeWidth(strokeWidth) {
256
- this._assertNotDestroyed();
257
- this.manager.mainView.setMemberState({ strokeWidth });
258
- }
259
- setStrokeColor(strokeColor) {
260
- this._assertNotDestroyed();
261
- this.manager.mainView.setMemberState({ strokeColor });
262
- }
263
- async insertImage(url) {
264
- this._assertNotDestroyed();
265
- await this.manager.switchMainViewToWriter();
266
- const { divElement } = this.manager.mainView;
267
- const containerSize = {
268
- width: (divElement == null ? void 0 : divElement.scrollWidth) || window.innerWidth,
269
- height: (divElement == null ? void 0 : divElement.scrollHeight) || window.innerHeight
270
- };
271
- const maxWidth = containerSize.width * 0.8;
272
- let { width, height } = await getImageSize(url, containerSize);
273
- const scale = Math.min(maxWidth / width, 1);
274
- const uuid = genUID();
275
- const { centerX, centerY } = this.manager.camera;
276
- width *= scale;
277
- height *= scale;
278
- this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });
279
- this.manager.mainView.completeImageUpload(uuid, url);
280
- width /= 0.8;
281
- height /= 0.8;
282
- const originX = centerX - width / 2;
283
- const originY = centerY - height / 2;
284
- this.manager.moveCameraToContain({ originX, originY, width, height });
285
- }
286
- insertDocs(arg1, arg2) {
287
- if (typeof arg1 === "object" && "fileType" in arg1) {
288
- return this._insertDocsImpl(arg1);
289
- } else if (arg2 && arg2.status !== "Finished") {
290
- throw new Error("[FastboardApp] Can not insert a converting doc.");
291
- } else if (arg2 && arg2.progress) {
292
- const scenes = arg2.progress.convertedFileList.map(convertedFileToScene);
293
- const scenePath = `/${arg2.uuid}/${genUID()}`;
294
- const { emptyScenes, taskId, url } = makeSlideParams(scenes);
295
- if (taskId && url) {
296
- const title = arg1;
297
- return this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url, scenes: emptyScenes });
298
- } else {
299
- return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title: arg1 });
300
- }
301
- }
302
- }
303
- _insertDocsImpl(_a) {
304
- var _b = _a, { fileType, scenePath, title, scenes } = _b, attributes = __objRest(_b, ["fileType", "scenePath", "title", "scenes"]);
305
- this._assertNotDestroyed();
306
- switch (fileType) {
307
- case "pdf":
308
- case "ppt":
309
- return this.manager.addApp({
310
- kind: "DocsViewer",
311
- options: { scenePath, title, scenes }
312
- });
313
- case "pptx":
314
- return this.manager.addApp({
315
- kind: "Slide",
316
- options: { scenePath, title, scenes },
317
- attributes
318
- });
319
- }
320
- }
321
- insertCodeEditor() {
322
- this._assertNotDestroyed();
323
- return this.manager.addApp({
324
- kind: "Monaco",
325
- options: { title: "Code Editor" }
326
- });
327
- }
328
- insertCountdown() {
329
- this._assertNotDestroyed();
330
- return this.manager.addApp({
331
- kind: "Countdown",
332
- options: { title: "Countdown" }
333
- });
334
- }
335
- insertMedia({ title, src }) {
336
- this._assertNotDestroyed();
337
- return this.manager.addApp({
338
- kind: BuiltinApps.MediaPlayer,
339
- options: { title },
340
- attributes: { src }
341
- });
342
- }
343
- insertGeoGebra() {
344
- this._assertNotDestroyed();
345
- return this.manager.addApp({
346
- kind: "GeoGebra",
347
- options: { title: "GeoGebra" }
348
- });
349
- }
350
- };
351
-
352
1
  // src/index.ts
353
- async function createFastboard(_a) {
354
- var _b = _a, {
355
- sdkConfig,
356
- joinRoom: _c
357
- } = _b, _d = _c, { callbacks } = _d, joinRoomParams = __objRest(_d, ["callbacks"]), {
358
- managerConfig
359
- } = _b;
360
- const sdk = new WhiteWebSdk(__spreadProps(__spreadValues({}, sdkConfig), {
361
- useMobXState: true
362
- }));
363
- const hotKeys = __spreadProps(__spreadValues({}, DefaultHotKeys), {
364
- changeToSelector: "s",
365
- changeToLaserPointer: "z",
366
- changeToPencil: "p",
367
- changeToRectangle: "r",
368
- changeToEllipse: "c",
369
- changeToEraser: "e",
370
- changeToText: "t",
371
- changeToStraight: "l",
372
- changeToArrow: "a",
373
- changeToHand: "h"
374
- });
375
- const room = await sdk.joinRoom(__spreadProps(__spreadValues({
376
- floatBar: true,
377
- hotKeys
378
- }, ensureWindowManager(joinRoomParams)), {
379
- useMultiViews: true,
380
- disableNewPencil: false,
381
- disableMagixEventDispatchLimit: true
382
- }), callbacks);
383
- const manager = await WindowManager3.mount(__spreadProps(__spreadValues({
384
- cursor: true
385
- }, managerConfig), {
386
- room
387
- }));
388
- return new FastboardApp(sdk, room, manager, hotKeys);
389
- }
2
+ export * from "@netless/fastboard-core";
3
+ import { mount } from "@netless/fastboard-react";
390
4
  export {
391
- createFastboard
5
+ mount
392
6
  };
393
7
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/register-apps.ts","../src/core.ts","../src/emitter.ts","../src/utils.ts","../src/value.ts","../src/base.ts"],"sourcesContent":["import type { HotKeys, JoinRoomParams, RoomCallbacks, WhiteWebSdkConfiguration } 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 \"./register-apps\";\nimport { FastboardApp } from \"./core\";\nimport { ensureWindowManager } from \"./utils\";\n\nexport type { FastboardReadable, FastboardWritable } from \"./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","import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: {\n // turn on to show debug controller\n debug: false,\n },\n src: async () => {\n const app = await import(\"@netless/app-slide\");\n return app.default ?? app;\n },\n});\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-monaco@geogebra/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 {\n AnimationMode,\n ApplianceNames,\n Camera,\n Color,\n ConversionResponse,\n MemberState,\n Rectangle,\n RoomState,\n SceneDefinition,\n ShapeType,\n} from \"white-web-sdk\";\n\nimport { BuiltinApps } from \"@netless/window-manager\";\nimport { FastboardAppBase } from \"./base\";\nimport { convertedFileToScene, genUID, getImageSize, makeSlideParams } from \"./utils\";\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 interface InsertMediaParams {\n title: string;\n src: string;\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 => this._addRoomListener<RoomStateChanged>(\"onRoomStateChanged\", ({ memberState: m }) => m && set(m)),\n this.manager.mainView.setMemberState.bind(this.manager.mainView)\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, src }: InsertMediaParams) {\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 type { ConvertedFile, JoinRoomParams, 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(joinRoom: JoinRoomParams) {\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 { 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 { PublicEvent, Room, WindowManager } from \"@netless/window-manager\";\nimport type { HotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport type { FastboardDisposer, FastboardInternalValue } from \"./value\";\n\nimport { createValue } from \"./value\";\n\nexport class 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<T = unknown>(name: string, 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<T = unknown>(name: string, 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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;AACA;;;ACJA;AAEA,cAAc,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,YAAY;AAAA,IAEV,OAAO;AAAA;AAAA,EAET,KAAK,YAAY;AARnB;AASI,UAAM,MAAM,MAAM,OAAO;AACzB,WAAO,UAAI,YAAJ,YAAe;AAAA;AAAA;AAI1B,cAAc,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,KAAK;AAAA;AAGP,cAAc,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,KAAK;AAAA;AAGP,cAAc,SAAS;AAAA,EACrB,MAAM;AAAA,EACN,KAAK;AAAA,EACL,YAAY;AAAA,IACV,eAAe;AAAA;AAAA;;;ACfnB;;;ACXO,6BAA0B;AAAA,EAA1B,cAFP;AAGE,qBAAY,oBAAI;AAAA;AAAA,MAEZ,SAAiB;AACnB,WAAO,KAAK,UAAU;AAAA;AAAA,EAGxB,SAAS,SAAY;AACnB,SAAK,UAAU,QAAQ,cAAY,SAAS;AAAA;AAAA,EAG9C,YAAY,UAAgC;AAC1C,SAAK,UAAU,IAAI;AAAA;AAAA,EAGrB,eAAe,UAAgC;AAC7C,SAAK,UAAU,OAAO;AAAA;AAAA;;;ACjB1B;AAEO,gBAAgB;AAAA;AAIhB,sBAAsB,KAAa,UAAgB;AACxD,SAAO,IAAI,QAAc,aAAW;AAClC,UAAM,MAAM,IAAI;AAChB,QAAI,SAAS,MAAM,QAAQ;AAC3B,QAAI,UAAU,MAAM,QAAQ;AAC5B,QAAI,MAAM;AAAA;AAAA;AAIP,yBAAyB,QAA2B;AACzD,QAAM,cAAiC;AACvC,MAAI,SAAS;AACb,MAAI,MAAM;AAGV,QAAM,WAAW;AAEjB,aAAW,EAAE,MAAM,SAAS,QAAQ;AAElC,gBAAY,KAAK,EAAE;AAEnB,QAAI,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,QAAQ;AACtC;AAAA;AAEF,UAAM,QAAQ,SAAS,KAAK,IAAI;AAChC,QAAI,CAAC,SAAS,CAAC,MAAM,QAAQ;AAC3B;AAAA;AAEF,aAAS,MAAM,OAAO;AACtB,UAAM,UAAU,MAAM,OAAO;AAC7B;AAAA;AAGF,SAAO,EAAE,aAAa,QAAQ;AAAA;AAGzB,8BAA8B,GAAkB,GAAW;AAChE,SAAO;AAAA,IACL,MAAM,OAAO,IAAI;AAAA,IACjB,KAAK;AAAA,MACH,KAAK,EAAE;AAAA,MACP,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE;AAAA,MACV,YAAY,EAAE;AAAA;AAAA;AAAA;AAKb,6BAA6B,UAA0B;AAC5D,MAAI,CAAC,SAAS,oBAAoB,CAAC,SAAS,iBAAiB,SAAS,iBAAgB;AACpF,aAAS,mBAAmB,CAAC,GAAI,SAAS,oBAAoB,IAAK;AAAA;AAErE,SAAO;AAAA;AAIT,IAAM,OAAO;AACb,IAAM,WAAW,KAAK;AACtB,IAAM,SAAS;AACf,IAAM,kBAAkC,MAAM;AAEvC,kBAAkB;AACvB,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,oBAAgB,KAAK,KAAK,OAAO,KAAK,WAAW;AAAA;AAEnD,SAAO,gBAAgB,KAAK;AAAA;;;ACxBvB,qBACL,OACA,QACA,WAA+B,MACJ;AAC3B,QAAM,UAAU,IAAI;AAEpB,eAAa,UAAa;AACxB,YAAQ,SAAU,QAAQ;AAAA;AAG5B,QAAM,UAAU,OAAO,QAAQ;AAE/B,qBAAmB,UAA8B;AAC/C,YAAQ,YAAY;AACpB,aAAS;AACT,WAAO,MAAM,QAAQ,eAAe;AAAA;AAGtC,oBAAkB,UAA8B;AAC9C,YAAQ,YAAY;AACpB,WAAO,MAAM,QAAQ,eAAe;AAAA;AAGtC,SAAO,EAAE,OAAO,WAAW,UAAU,UAAU;AAAA;;;AClE1C,6BAAuB;AAAA,EACrB,YACI,KACA,MACA,SACA,SACT;AAJS;AACA;AACA;AACA;AAGQ,sBAAkC;AAC3C,sBAAa;AAQb,uBAAkC,IAAI,SAA0B;AACxE,YAAM,QAAQ,YAAY,GAAG;AAC7B,WAAK,WAAW,KAAM,MAA0C;AAChE,aAAO;AAAA;AAAA;AAAA,EAVC,sBAAsB;AAC9B,QAAI,KAAK,YAAY;AACnB,YAAM,IAAI,MAAM;AAAA;AAAA;AAAA,EAWV,iBAA8B,MAAc,UAAa;AACjE,SAAK;AACL,SAAK,KAAK,UAAU,GAAG,MAAM;AAC7B,WAAO,MAAM,KAAK,KAAK,UAAU,IAAI,MAAM;AAAA;AAAA,EAGnC,oBAAiD,MAAS,KAAsC;AACxG,SAAK;AACL,SAAK,QAAQ,QAAQ,GAAG,MAAM;AAC9B,WAAO,MAAM,KAAK,QAAQ,QAAQ,IAAI,MAAM;AAAA;AAAA,EAGpC,qBAAkC,MAAc,UAAa;AACrE,SAAK;AACL,SAAK,QAAQ,SAAS,UAAU,GAAG,MAAM;AACzC,WAAO,MAAM,KAAK,QAAQ,SAAS,UAAU,IAAI,MAAM;AAAA;AAAA,EAGlD,UAAU;AACf,SAAK,WAAW,QAAQ,aAAW;AACnC,SAAK,WAAW,SAAS;AACzB,SAAK,aAAa;AAClB,SAAK,QAAQ;AACb,WAAO,KAAK,KAAK;AAAA;AAAA;;;AJPd,iCAA2B,iBAAiB;AAAA,EAA5C,cA7CP;AA6CO;AAoBI,oBAAW,KAAK,YACvB,KAAK,KAAK,YACV,SAAO,KAAK,iBAAiB,2BAA2B,MAAM,IAAI,KAAK,KAAK,cAC5E,KAAK,KAAK,YAAY,KAAK,KAAK;AAMzB,oBAAW,KAAK,YAAY,KAAK,QAAQ,UAAU,SAC1D,KAAK,oBAAoB,kBAAkB;AAOpC,sBAAa,KAAK,YAAY,KAAK,QAAQ,SAAS,SAC3D,KAAK,oBAAoB,iBAAiB;AAMnC,wBAAe,KAAK,YAAY,KAAK,QAAQ,SAAS,cAAc,SAC3E,KAAK,qBAAqB,wBAAwB;AAM3C,wBAAe,KAAK,YAAY,KAAK,QAAQ,SAAS,cAAc,SAC3E,KAAK,qBAAqB,wBAAwB;AAM3C,kBAAS,KAAK,YACrB,KAAK,QAAQ,SAAS,QACtB,SAAO,KAAK,qBAAqB,mBAAmB,MACpD,KAAK,QAAQ,WAAW,KAAK,KAAK;AAM3B,uBAAc,KAAK,YAC1B,KAAK,KAAK,MAAM,aAChB,SAAO,KAAK,iBAAmC,sBAAsB,CAAC,EAAE,aAAa,QAAQ,KAAK,IAAI,KACtG,KAAK,QAAQ,SAAS,eAAe,KAAK,KAAK,QAAQ;AAAA;AAAA,EAlEzD,cAAc,WAAwB;AACpC,SAAK;AACL,SAAK,QAAQ,cAAc;AAAA;AAAA,EAM7B,cAAc,WAAwB;AACpC,SAAK;AACL,SAAK,QAAQ,uBAAuB;AAAA;AAAA,EA8DtC,OAAO;AACL,SAAK;AACL,SAAK,QAAQ,SAAS;AAAA;AAAA,EAMxB,OAAO;AACL,SAAK;AACL,SAAK,QAAQ,SAAS;AAAA;AAAA,EAMxB,WAAW,QAAyE;AAClF,SAAK;AACL,SAAK,QAAQ,WAAW;AAAA;AAAA,EAM1B,oBAAoB,WAA0D;AAC5E,SAAK;AACL,SAAK,QAAQ,oBAAoB;AAAA;AAAA,EAMnC,oBAAoB;AAClB,SAAK;AACL,SAAK,QAAQ,SAAS;AAAA;AAAA,EAMxB,aAAa,WAA2B,OAAmB;AACzD,SAAK;AACL,SAAK,QAAQ,SAAS,eAAe,EAAE,sBAAsB,WAAW,WAAW;AAAA;AAAA,EAGrF,eAAe,aAAqB;AAClC,SAAK;AACL,SAAK,QAAQ,SAAS,eAAe,EAAE;AAAA;AAAA,EAGzC,eAAe,aAAoB;AACjC,SAAK;AACL,SAAK,QAAQ,SAAS,eAAe,EAAE;AAAA;AAAA,QAMnC,YAAY,KAAa;AAC7B,SAAK;AACL,UAAM,KAAK,QAAQ;AAEnB,UAAM,EAAE,eAAe,KAAK,QAAQ;AACpC,UAAM,gBAAgB;AAAA,MACpB,OAAO,0CAAY,gBAAe,OAAO;AAAA,MACzC,QAAQ,0CAAY,iBAAgB,OAAO;AAAA;AAI7C,UAAM,WAAW,cAAc,QAAQ;AACvC,QAAI,EAAE,OAAO,WAAW,MAAM,aAAa,KAAK;AAChD,UAAM,QAAQ,KAAK,IAAI,WAAW,OAAO;AACzC,UAAM,OAAO;AACb,UAAM,EAAE,SAAS,YAAY,KAAK,QAAQ;AAC1C,aAAS;AACT,cAAU;AACV,SAAK,QAAQ,SAAS,YAAY,EAAE,MAAM,SAAS,SAAS,OAAO,QAAQ,QAAQ;AACnF,SAAK,QAAQ,SAAS,oBAAoB,MAAM;AAGhD,aAAS;AACT,cAAU;AACV,UAAM,UAAU,UAAU,QAAQ;AAClC,UAAM,UAAU,UAAU,SAAS;AACnC,SAAK,QAAQ,oBAAoB,EAAE,SAAS,SAAS,OAAO;AAAA;AAAA,EAqB9D,WAAW,MAAiC,MAA2B;AACrE,QAAI,OAAO,SAAS,YAAY,cAAc,MAAM;AAClD,aAAO,KAAK,gBAAgB;AAAA,eACnB,QAAQ,KAAK,WAAW,YAAY;AAC7C,YAAM,IAAI,MAAM;AAAA,eACP,QAAQ,KAAK,UAAU;AAChC,YAAM,SAA4B,KAAK,SAAS,kBAAkB,IAAI;AACtE,YAAM,YAAY,IAAI,KAAK,QAAQ;AACnC,YAAM,EAAE,aAAa,QAAQ,QAAQ,gBAAgB;AACrD,UAAI,UAAU,KAAK;AACjB,cAAM,QAAQ;AACd,eAAO,KAAK,gBAAgB,EAAE,UAAU,QAAQ,WAAW,QAAQ,OAAO,KAAK,QAAQ;AAAA,aAClF;AACL,eAAO,KAAK,gBAAgB,EAAE,UAAU,OAAO,WAAW,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA,EAKvE,gBAAgB,IAAyE;AAAzE,iBAAE,YAAU,WAAW,OAAO,WAA9B,IAAyC,uBAAzC,IAAyC,CAAvC,YAAU,aAAW,SAAO;AACpD,SAAK;AACL,YAAQ;AAAA,WACD;AAAA,WACA;AACH,eAAO,KAAK,QAAQ,OAAO;AAAA,UACzB,MAAM;AAAA,UACN,SAAS,EAAE,WAAW,OAAO;AAAA;AAAA,WAE5B;AACH,eAAO,KAAK,QAAQ,OAAO;AAAA,UACzB,MAAM;AAAA,UACN,SAAS,EAAE,WAAW,OAAO;AAAA,UAC7B;AAAA;AAAA;AAAA;AAAA,EAQR,mBAAmB;AACjB,SAAK;AACL,WAAO,KAAK,QAAQ,OAAO;AAAA,MACzB,MAAM;AAAA,MACN,SAAS,EAAE,OAAO;AAAA;AAAA;AAAA,EAOtB,kBAAkB;AAChB,SAAK;AACL,WAAO,KAAK,QAAQ,OAAO;AAAA,MACzB,MAAM;AAAA,MACN,SAAS,EAAE,OAAO;AAAA;AAAA;AAAA,EAOtB,YAAY,EAAE,OAAO,OAA0B;AAC7C,SAAK;AACL,WAAO,KAAK,QAAQ,OAAO;AAAA,MACzB,MAAM,YAAY;AAAA,MAClB,SAAS,EAAE;AAAA,MACX,YAAY,EAAE;AAAA;AAAA;AAAA,EAOlB,iBAAiB;AACf,SAAK;AACL,WAAO,KAAK,QAAQ,OAAO;AAAA,MACzB,MAAM;AAAA,MACN,SAAS,EAAE,OAAO;AAAA;AAAA;AAAA;;;AF3QxB,+BAAsC,IAIjB;AAJiB,eAE1B;AAAA,IADV;AAAA,IACA,UAAU;AAAA,MAF0B,IAE1B,SAAE,gBAAF,IAAgB,2BAAhB,IAAgB,CAAd,eAAF;AAAA,IACV;AAAA,MAHoC;AAKpC,QAAM,MAAM,IAAI,YAAY,iCACvB,YADuB;AAAA,IAE1B,cAAc;AAAA;AAGhB,QAAM,UAA4B,iCAC7B,iBAD6B;AAAA,IAEhC,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,cAAc;AAAA;AAGhB,QAAM,OAAO,MAAM,IAAI,SACrB;AAAA,IACE,UAAU;AAAA,IACV;AAAA,KACG,oBAAoB,kBAHzB;AAAA,IAIE,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,gCAAgC;AAAA,MAElC;AAGF,QAAM,UAAU,MAAM,eAAc,MAAM;AAAA,IACxC,QAAQ;AAAA,KACL,gBAFqC;AAAA,IAGxC;AAAA;AAGF,SAAO,IAAI,aAAa,KAAK,MAAM,SAAS;AAAA;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"@netless/fastboard-core\";\nexport { mount } from \"@netless/fastboard-react\";\n"],"mappings":";AAAA;AACA;","names":[]}
package/package.json CHANGED
@@ -1,32 +1,35 @@
1
1
  {
2
2
  "name": "@netless/fastboard",
3
- "version": "0.1.0",
3
+ "version": "0.2.2",
4
4
  "description": "A tiny wrapper of white-web-sdk and @netless/window-manager.",
5
5
  "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "src/index.ts",
8
- "sideEffects": false,
9
6
  "files": [
10
7
  "src",
11
8
  "dist"
12
9
  ],
10
+ "dependencies": {
11
+ "@netless/fastboard-core": "0.2.2",
12
+ "@netless/fastboard-react": "0.2.2"
13
+ },
13
14
  "peerDependencies": {
14
- "@netless/app-slide": "*",
15
15
  "@netless/window-manager": ">=0.4.0",
16
16
  "white-web-sdk": ">=2.16.0"
17
17
  },
18
- "peerDependenciesMeta": {
19
- "@netless/app-slide": {
20
- "optional": true
21
- }
22
- },
23
18
  "devDependencies": {
24
- "@netless/app-slide": "^0.0.55",
25
- "@netless/window-manager": "^0.4.0-canary.17",
19
+ "@netless/window-manager": "^0.4.0-canary.31",
26
20
  "tsup": "^5.11.11",
27
- "white-web-sdk": "^2.16.0"
21
+ "white-web-sdk": "^2.16.5"
22
+ },
23
+ "publishConfig": {
24
+ "main": "dist/index.js",
25
+ "module": "dist/index.mjs",
26
+ "types": "src/index.ts"
28
27
  },
29
28
  "scripts": {
30
- "build": "tsup"
31
- }
29
+ "build": "tsup",
30
+ "cleanup": "rimraf dist",
31
+ "check": "tsc --noEmit"
32
+ },
33
+ "module": "dist/index.mjs",
34
+ "types": "src/index.ts"
32
35
  }
package/src/index.ts CHANGED
@@ -1,80 +1,2 @@
1
- import type { HotKeys, JoinRoomParams, RoomCallbacks, WhiteWebSdkConfiguration } from "white-web-sdk";
2
- import type { MountParams } from "@netless/window-manager";
3
-
4
- import { DefaultHotKeys, WhiteWebSdk } from "white-web-sdk";
5
- import { WindowManager } from "@netless/window-manager";
6
-
7
- import "./register-apps";
8
- import { FastboardApp } from "./core";
9
- import { ensureWindowManager } from "./utils";
10
-
11
- export type { FastboardReadable, FastboardWritable } from "./value";
12
-
13
- export type { FastboardApp };
14
-
15
- export interface FastboardOptions {
16
- sdkConfig: Omit<WhiteWebSdkConfiguration, "useMobXState">;
17
- joinRoom: Omit<JoinRoomParams, "useMultiViews" | "disableNewPencil" | "disableMagixEventDispatchLimit"> & {
18
- callbacks?: Partial<RoomCallbacks>;
19
- };
20
- managerConfig?: Omit<MountParams, "room">;
21
- }
22
-
23
- /**
24
- * Create a FastboardApp instance.
25
- * @example
26
- * let app = await createFastboard({
27
- * sdkConfig: {
28
- * appIdentifier: import.meta.env.VITE_APPID,
29
- * },
30
- * joinRoom: {
31
- * uid: unique_id,
32
- * uuid: import.meta.env.VITE_ROOM_UUID,
33
- * roomToken: import.meta.env.VITE_ROOM_TOKEN,
34
- * },
35
- * })
36
- */
37
- export async function createFastboard({
38
- sdkConfig,
39
- joinRoom: { callbacks, ...joinRoomParams },
40
- managerConfig,
41
- }: FastboardOptions) {
42
- const sdk = new WhiteWebSdk({
43
- ...sdkConfig,
44
- useMobXState: true,
45
- });
46
-
47
- const hotKeys: Partial<HotKeys> = {
48
- ...DefaultHotKeys,
49
- changeToSelector: "s",
50
- changeToLaserPointer: "z",
51
- changeToPencil: "p",
52
- changeToRectangle: "r",
53
- changeToEllipse: "c",
54
- changeToEraser: "e",
55
- changeToText: "t",
56
- changeToStraight: "l",
57
- changeToArrow: "a",
58
- changeToHand: "h",
59
- };
60
-
61
- const room = await sdk.joinRoom(
62
- {
63
- floatBar: true,
64
- hotKeys,
65
- ...ensureWindowManager(joinRoomParams),
66
- useMultiViews: true,
67
- disableNewPencil: false,
68
- disableMagixEventDispatchLimit: true,
69
- },
70
- callbacks
71
- );
72
-
73
- const manager = await WindowManager.mount({
74
- cursor: true,
75
- ...managerConfig,
76
- room,
77
- });
78
-
79
- return new FastboardApp(sdk, room, manager, hotKeys);
80
- }
1
+ export * from "@netless/fastboard-core";
2
+ export { mount } from "@netless/fastboard-react";
package/src/base.ts DELETED
@@ -1,55 +0,0 @@
1
- import type { PublicEvent, Room, WindowManager } from "@netless/window-manager";
2
- import type { HotKeys, WhiteWebSdk } from "white-web-sdk";
3
- import type { FastboardDisposer, FastboardInternalValue } from "./value";
4
-
5
- import { createValue } from "./value";
6
-
7
- export class FastboardAppBase {
8
- public constructor(
9
- readonly sdk: WhiteWebSdk,
10
- readonly room: Room,
11
- readonly manager: WindowManager,
12
- readonly hotKeys: Partial<HotKeys>
13
- ) {}
14
-
15
- protected readonly _disposers: FastboardDisposer[] = [];
16
- protected _destroyed = false;
17
- protected _assertNotDestroyed() {
18
- if (this._destroyed) {
19
- throw new Error("[FastboardApp] Can not call any method on destroyed FastboardApp.");
20
- }
21
- }
22
-
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
- protected createValue: typeof createValue = (...args: [any, any]): any => {
25
- const value = createValue(...args);
26
- this._disposers.push((value as FastboardInternalValue<unknown>).dispose);
27
- return value;
28
- };
29
-
30
- protected _addRoomListener<T = unknown>(name: string, listener: T) {
31
- this._assertNotDestroyed();
32
- this.room.callbacks.on(name, listener);
33
- return () => this.room.callbacks.off(name, listener);
34
- }
35
-
36
- protected _addManagerListener<K extends keyof PublicEvent>(name: K, set: (value: PublicEvent[K]) => void) {
37
- this._assertNotDestroyed();
38
- this.manager.emitter.on(name, set);
39
- return () => this.manager.emitter.off(name, set);
40
- }
41
-
42
- protected _addMainViewListener<T = unknown>(name: string, listener: T) {
43
- this._assertNotDestroyed();
44
- this.manager.mainView.callbacks.on(name, listener);
45
- return () => this.manager.mainView.callbacks.off(name, listener);
46
- }
47
-
48
- public destroy() {
49
- this._disposers.forEach(dispose => dispose());
50
- this._disposers.length = 0;
51
- this._destroyed = true;
52
- this.manager.destroy();
53
- return this.room.disconnect();
54
- }
55
- }