@netless/fastboard-core 0.3.12 → 0.3.13-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lite.js ADDED
@@ -0,0 +1,1018 @@
1
+ 'use strict';
2
+
3
+ var whiteWebSdk = require('white-web-sdk');
4
+ var windowManager = require('@netless/window-manager');
5
+ var syncedStore = require('@netless/synced-store');
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __defProps = Object.defineProperties;
9
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
10
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ if (__getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(b)) {
20
+ if (__propIsEnum.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ }
23
+ return a;
24
+ };
25
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
26
+ var __objRest = (source, exclude) => {
27
+ var target = {};
28
+ for (var prop in source)
29
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
30
+ target[prop] = source[prop];
31
+ if (source != null && __getOwnPropSymbols)
32
+ for (var prop of __getOwnPropSymbols(source)) {
33
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
34
+ target[prop] = source[prop];
35
+ }
36
+ return target;
37
+ };
38
+ var __publicField = (obj, key, value) => {
39
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
40
+ return value;
41
+ };
42
+
43
+ // src/utils/store.ts
44
+ function noop() {
45
+ }
46
+ function safe_not_equal(a, b) {
47
+ return a != a ? b == b : a !== b || a && typeof a === "object" || typeof a === "function";
48
+ }
49
+ function readable(value, start = noop) {
50
+ let stop;
51
+ const subscribers = /* @__PURE__ */ new Set();
52
+ function set(new_value) {
53
+ if (safe_not_equal(value, new_value)) {
54
+ value = new_value;
55
+ if (stop) {
56
+ for (const run of subscribers) {
57
+ run(value);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ function subscribe(run) {
63
+ subscribers.add(run);
64
+ if (subscribers.size === 1) {
65
+ stop = start(set) || noop;
66
+ }
67
+ run(value);
68
+ return () => {
69
+ subscribers.delete(run);
70
+ if (subscribers.size === 0) {
71
+ stop && stop();
72
+ stop = void 0;
73
+ }
74
+ };
75
+ }
76
+ function reaction(run) {
77
+ subscribers.add(run);
78
+ if (subscribers.size === 1) {
79
+ stop = start(set) || noop;
80
+ }
81
+ return () => {
82
+ subscribers.delete(run);
83
+ if (subscribers.size === 0) {
84
+ stop && stop();
85
+ stop = void 0;
86
+ }
87
+ };
88
+ }
89
+ return {
90
+ get value() {
91
+ if (subscribers.size === 0) {
92
+ stop = start(set) || noop;
93
+ stop();
94
+ stop = void 0;
95
+ }
96
+ return value;
97
+ },
98
+ subscribe,
99
+ reaction
100
+ };
101
+ }
102
+ function writable(value, start = noop, set) {
103
+ const internal = readable(value, start);
104
+ return {
105
+ get value() {
106
+ return internal.value;
107
+ },
108
+ subscribe: internal.subscribe,
109
+ reaction: internal.reaction,
110
+ set,
111
+ update(fn) {
112
+ set(fn(internal.value));
113
+ }
114
+ };
115
+ }
116
+
117
+ // src/utils/misc.ts
118
+ function getImageSize(url, fallback, crossOrigin) {
119
+ return new Promise((resolve) => {
120
+ const img = new Image();
121
+ applyCrossOrigin(img, url, crossOrigin);
122
+ img.onload = () => resolve(img);
123
+ img.onerror = () => resolve(fallback);
124
+ img.src = url;
125
+ });
126
+ }
127
+ function applyCrossOrigin(image, src, crossOrigin) {
128
+ if (crossOrigin === void 0 && !src.startsWith("data:")) {
129
+ image.crossOrigin = determineCrossOrigin(src);
130
+ } else if (crossOrigin !== false) {
131
+ image.crossOrigin = typeof crossOrigin === "string" ? crossOrigin : "anonymous";
132
+ }
133
+ }
134
+ function determineCrossOrigin(src) {
135
+ if (src.startsWith("data:") || typeof window === "undefined" || !window.location) {
136
+ return "";
137
+ }
138
+ const loc = window.location;
139
+ try {
140
+ const parsedUrl = new URL(src, document.baseURI);
141
+ if (parsedUrl.hostname !== loc.hostname || parsedUrl.port !== loc.port || parsedUrl.protocol !== loc.protocol) {
142
+ return "anonymous";
143
+ }
144
+ return "";
145
+ } catch (e) {
146
+ return "";
147
+ }
148
+ }
149
+ function makeSlideParams(scenes) {
150
+ const emptyScenes = [];
151
+ let taskId = "";
152
+ let url = "";
153
+ const pptSrcRE = new RegExp("^pptx?(?<prefix>:\\/\\/\\S+?dynamicConvert)\\/(?<taskId>\\w+)\\/");
154
+ for (const { name, ppt } of scenes) {
155
+ emptyScenes.push({ name });
156
+ if (!ppt || !ppt.src.startsWith("ppt"))
157
+ continue;
158
+ const match = pptSrcRE.exec(ppt.src);
159
+ if (!match || !match.groups)
160
+ continue;
161
+ taskId = match.groups.taskId;
162
+ url = `https${match.groups.prefix}`;
163
+ break;
164
+ }
165
+ return { scenes: emptyScenes, taskId, url };
166
+ }
167
+ function convertedFileToScene(f, i) {
168
+ return {
169
+ name: String(i + 1),
170
+ ppt: {
171
+ src: f.conversionFileUrl,
172
+ width: f.width,
173
+ height: f.height,
174
+ previewURL: f.preview
175
+ }
176
+ };
177
+ }
178
+
179
+ // src/utils/uid.ts
180
+ var SOUP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
181
+ var SOUP_LEN = 62;
182
+ var ID_LEN = 20;
183
+ var reusedIdCarrier = /* @__PURE__ */ Array(ID_LEN);
184
+ function genUID() {
185
+ for (let i = 0; i < ID_LEN; i++) {
186
+ reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);
187
+ }
188
+ return reusedIdCarrier.join("");
189
+ }
190
+
191
+ // src/utils/warn.ts
192
+ var warnings = {
193
+ "no-ppt-in-scenes": "You're probably inserting the slide app in a wrong way, there shouldn't exist `scenes[0].ppt`."
194
+ };
195
+ var warned = /* @__PURE__ */ new Set();
196
+ function warn(id) {
197
+ if (warned.has(id))
198
+ return;
199
+ warned.add(id);
200
+ console.warn(warnings[id]);
201
+ }
202
+ function ensure_official_plugins(joinRoom) {
203
+ const plugins = new Set(joinRoom.invisiblePlugins || []);
204
+ plugins.add(windowManager.WindowManager);
205
+ plugins.add(syncedStore.SyncedStorePlugin);
206
+ joinRoom.invisiblePlugins = [...plugins];
207
+ return joinRoom;
208
+ }
209
+ function transform_app_status(status) {
210
+ return status === "start" ? "loading" : status === "failed" ? "failed" : "idle";
211
+ }
212
+ var register = windowManager.WindowManager.register.bind(windowManager.WindowManager);
213
+ var DefaultApps = {
214
+ Monaco: {
215
+ src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-monaco/0.1.14-beta.1/dist/main.iife.js"
216
+ },
217
+ Countdown: {
218
+ src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-countdown/0.0.2/dist/main.iife.js"
219
+ },
220
+ GeoGebra: {
221
+ src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-geogebra/0.0.4/dist/main.iife.js",
222
+ appOptions: {
223
+ HTML5Codebase: "https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d"
224
+ }
225
+ },
226
+ EmbeddedPage: {
227
+ src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-embedded-page/0.1.1/dist/main.iife.js"
228
+ },
229
+ Plyr: {
230
+ src: "https://netless-app.oss-cn-hangzhou.aliyuncs.com/@netless/app-plyr/0.1.3/dist/main.iife.js"
231
+ }
232
+ };
233
+ for (const kind in DefaultApps) {
234
+ if (Object.prototype.hasOwnProperty.call(DefaultApps, kind)) {
235
+ const options = DefaultApps[kind];
236
+ windowManager.WindowManager.register(__spreadValues({ kind }, options));
237
+ }
238
+ }
239
+ var version = "0.3.13-canary.1";
240
+ if (typeof window !== "undefined") {
241
+ let str = window.__netlessUA || "";
242
+ str += ` ${"@netless/fastboard"}@${version} `;
243
+ window.__netlessUA = str;
244
+ }
245
+
246
+ // src/impl/FastboardApp.ts
247
+ var FastboardAppBase = class {
248
+ constructor(sdk, room, manager, hotKeys, syncedStore) {
249
+ this.sdk = sdk;
250
+ this.room = room;
251
+ this.manager = manager;
252
+ this.hotKeys = hotKeys;
253
+ this.syncedStore = syncedStore;
254
+ __publicField(this, "_destroyed", false);
255
+ }
256
+ /** @internal */
257
+ _assertNotDestroyed() {
258
+ if (this._destroyed) {
259
+ throw new Error("FastboardApp has been destroyed");
260
+ }
261
+ }
262
+ /** @internal */
263
+ _addRoomListener(name, listener) {
264
+ this._assertNotDestroyed();
265
+ this.room.callbacks.on(name, listener);
266
+ return () => this.room.callbacks.off(name, listener);
267
+ }
268
+ /** @internal */
269
+ _addManagerListener(name, listener) {
270
+ this._assertNotDestroyed();
271
+ this.manager.emitter.on(name, listener);
272
+ return () => this.manager.emitter.off(name, listener);
273
+ }
274
+ /** @internal */
275
+ _addMainViewListener(name, listener) {
276
+ this._assertNotDestroyed();
277
+ this.manager.mainView.callbacks.on(name, listener);
278
+ return () => this.manager.mainView.callbacks.off(name, listener);
279
+ }
280
+ /**
281
+ * Destroy fastboard (disconnect from the whiteboard room).
282
+ */
283
+ destroy() {
284
+ this._destroyed = true;
285
+ this.manager.destroy();
286
+ return this.room.disconnect();
287
+ }
288
+ };
289
+ var FastboardApp = class extends FastboardAppBase {
290
+ constructor() {
291
+ super(...arguments);
292
+ /**
293
+ * Is current room writable?
294
+ */
295
+ __publicField(this, "writable", writable(
296
+ this.room.isWritable,
297
+ (set) => {
298
+ set(this.room.isWritable);
299
+ return this._addRoomListener("onEnableWriteNowChanged", () => set(this.room.isWritable));
300
+ },
301
+ this.room.setWritable.bind(this.room)
302
+ ));
303
+ /**
304
+ * Is current room online?
305
+ */
306
+ __publicField(this, "phase", readable(this.room.phase, (set) => {
307
+ set(this.room.phase);
308
+ return this._addRoomListener("onPhaseChanged", set);
309
+ }));
310
+ /**
311
+ * Current window-manager's windows' state (is it maximized?).
312
+ */
313
+ __publicField(this, "boxState", readable(this.manager.boxState, (set) => {
314
+ set(this.manager.boxState);
315
+ return this._addManagerListener("boxStateChange", set);
316
+ }));
317
+ /**
318
+ * Current window-manager's focused app's id.
319
+ * @example "HelloWorld-1A2b3C4d"
320
+ */
321
+ __publicField(this, "focusedApp", readable(this.manager.focused, (set) => {
322
+ set(this.manager.focused);
323
+ return this._addManagerListener("focusedChange", set);
324
+ }));
325
+ /**
326
+ * How many times can I call `app.redo()`?
327
+ */
328
+ __publicField(this, "canRedoSteps", readable(this.manager.canRedoSteps, (set) => {
329
+ set(this.manager.canRedoSteps);
330
+ return this._addManagerListener("canRedoStepsChange", set);
331
+ }));
332
+ /**
333
+ * How many times can I call `app.undo()`?
334
+ */
335
+ __publicField(this, "canUndoSteps", readable(this.manager.canUndoSteps, (set) => {
336
+ set(this.manager.canUndoSteps);
337
+ return this._addManagerListener("canUndoStepsChange", set);
338
+ }));
339
+ /**
340
+ * Current camera information of main view.
341
+ *
342
+ * Change the camera position by `app.moveCamera()`.
343
+ */
344
+ __publicField(this, "camera", readable(this.manager.cameraState, (set) => {
345
+ set(this.manager.cameraState);
346
+ return this._addManagerListener("cameraStateChange", set);
347
+ }));
348
+ /**
349
+ * Current tool's info, like "is using pencil?", "what color?".
350
+ *
351
+ * Change the tool by `app.setAppliance()`.
352
+ */
353
+ __publicField(this, "memberState", readable(this.room.state.memberState, (set) => {
354
+ set(this.room.state.memberState);
355
+ return this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m));
356
+ }));
357
+ /**
358
+ * 0..n-1, current index of main view scenes.
359
+ */
360
+ __publicField(this, "sceneIndex", writable(
361
+ this.manager.mainViewSceneIndex,
362
+ (set) => {
363
+ set(this.manager.mainViewSceneIndex);
364
+ return this._addManagerListener("mainViewSceneIndexChange", set);
365
+ },
366
+ this.manager.setMainViewSceneIndex.bind(this.manager)
367
+ ));
368
+ /**
369
+ * How many pages are in the main view?
370
+ */
371
+ __publicField(this, "sceneLength", readable(this.manager.mainViewScenesLength, (set) => {
372
+ set(this.manager.mainViewScenesLength);
373
+ return this._addManagerListener("mainViewScenesLengthChange", set);
374
+ }));
375
+ /** @internal */
376
+ __publicField(this, "_appsStatus", {});
377
+ /**
378
+ * Apps status.
379
+ */
380
+ __publicField(this, "appsStatus", readable(
381
+ {},
382
+ (set) => this._addManagerListener("loadApp", ({ kind, status, reason }) => {
383
+ this._appsStatus[kind] = { status: transform_app_status(status), reason };
384
+ set(this._appsStatus);
385
+ })
386
+ ));
387
+ }
388
+ /**
389
+ * Render this app to some DOM.
390
+ */
391
+ bindContainer(container) {
392
+ this._assertNotDestroyed();
393
+ this.manager.bindContainer(container);
394
+ }
395
+ /**
396
+ * Move window-manager's collector to some place.
397
+ */
398
+ bindCollector(container) {
399
+ this._assertNotDestroyed();
400
+ this.manager.bindCollectorContainer(container);
401
+ }
402
+ /**
403
+ * Undo a step on main view.
404
+ */
405
+ undo() {
406
+ this._assertNotDestroyed();
407
+ this.manager.undo();
408
+ }
409
+ /**
410
+ * Redo a step on main view.
411
+ */
412
+ redo() {
413
+ this._assertNotDestroyed();
414
+ this.manager.redo();
415
+ }
416
+ /**
417
+ * Move current main view's camera position.
418
+ */
419
+ moveCamera(camera) {
420
+ this._assertNotDestroyed();
421
+ this.manager.moveCamera(camera);
422
+ }
423
+ /**
424
+ * Move current main view's camera to include a rectangle.
425
+ */
426
+ moveCameraToContain(rectangle) {
427
+ this._assertNotDestroyed();
428
+ this.manager.moveCameraToContain(rectangle);
429
+ }
430
+ /**
431
+ * Delete all things on the main view.
432
+ */
433
+ cleanCurrentScene() {
434
+ this._assertNotDestroyed();
435
+ this.manager.cleanCurrentScene();
436
+ }
437
+ /**
438
+ * Set current tool, like "pencil".
439
+ */
440
+ setAppliance(appliance, shape) {
441
+ this._assertNotDestroyed();
442
+ this.manager.mainView.setMemberState({
443
+ currentApplianceName: appliance,
444
+ shapeType: shape
445
+ });
446
+ }
447
+ /**
448
+ * Set pencil and shape's thickness.
449
+ */
450
+ setStrokeWidth(strokeWidth) {
451
+ this._assertNotDestroyed();
452
+ this.manager.mainView.setMemberState({ strokeWidth });
453
+ }
454
+ /**
455
+ * Set pencil and shape's color.
456
+ */
457
+ setStrokeColor(strokeColor) {
458
+ this._assertNotDestroyed();
459
+ this.manager.mainView.setMemberState({ strokeColor });
460
+ }
461
+ /**
462
+ * Set text size. Default is 16.
463
+ */
464
+ setTextSize(textSize) {
465
+ this._assertNotDestroyed();
466
+ this.manager.mainView.setMemberState({ textSize });
467
+ }
468
+ /**
469
+ * Set text color.
470
+ *
471
+ * @example
472
+ * setTextColor([0x66, 0xcc, 0xff])
473
+ */
474
+ setTextColor(textColor) {
475
+ this._assertNotDestroyed();
476
+ this.manager.mainView.setMemberState({ textColor });
477
+ }
478
+ /**
479
+ * Toggle dotted line effect on pencil.
480
+ */
481
+ toggleDottedLine(force) {
482
+ this._assertNotDestroyed();
483
+ this.manager.mainView.setMemberState({ dottedLine: force != null ? force : !this.memberState.value.dottedLine });
484
+ }
485
+ /**
486
+ * Set pencil eraser size.
487
+ */
488
+ setPencilEraserSize(size) {
489
+ this._assertNotDestroyed();
490
+ this.manager.mainView.setMemberState({ pencilEraserSize: size });
491
+ }
492
+ /**
493
+ * Goto previous page (the main whiteboard view).
494
+ */
495
+ prevPage() {
496
+ this._assertNotDestroyed();
497
+ return this.manager.prevPage();
498
+ }
499
+ /**
500
+ * Goto next page (the main whiteboard view).
501
+ */
502
+ nextPage() {
503
+ this._assertNotDestroyed();
504
+ return this.manager.nextPage();
505
+ }
506
+ /**
507
+ * Goto any page (index range: 0..n-1)
508
+ */
509
+ jumpPage(index) {
510
+ this._assertNotDestroyed();
511
+ return this.manager.jumpPage(index);
512
+ }
513
+ /**
514
+ * Add one page to the main whiteboard view.
515
+ *
516
+ * @example
517
+ * addPage({ after: true }) // add one page right after current one.
518
+ * nextPage() // then, goto that page.
519
+ */
520
+ addPage(params) {
521
+ this._assertNotDestroyed();
522
+ return this.manager.addPage(params);
523
+ }
524
+ /**
525
+ * Remove one page at given index or current page (by default).
526
+ *
527
+ * Requires `@netless/window-manager` >= 0.4.30.
528
+ *
529
+ * @example
530
+ * removePage() // remove current page
531
+ */
532
+ removePage(index) {
533
+ this._assertNotDestroyed();
534
+ return this.manager.removePage(index);
535
+ }
536
+ /**
537
+ * Insert an image to the main view.
538
+ *
539
+ * @param crossOrigin Whether to load the image with CORS enabled, default is `true`.
540
+ *
541
+ * @example
542
+ * insertImage("https://i.imgur.com/CzXTtJV.jpg")
543
+ */
544
+ async insertImage(url, crossOrigin) {
545
+ this._assertNotDestroyed();
546
+ await this.manager.switchMainViewToWriter();
547
+ const { divElement } = this.manager.mainView;
548
+ const containerSize = {
549
+ width: (divElement == null ? void 0 : divElement.scrollWidth) || window.innerWidth,
550
+ height: (divElement == null ? void 0 : divElement.scrollHeight) || window.innerHeight
551
+ };
552
+ const maxWidth = containerSize.width * 0.8;
553
+ let { width, height } = await getImageSize(url, containerSize, crossOrigin);
554
+ const scale = Math.min(maxWidth / width, 1);
555
+ const uuid = genUID();
556
+ const { centerX, centerY } = this.manager.camera;
557
+ width *= scale;
558
+ height *= scale;
559
+ this.manager.mainView.insertImage({
560
+ uuid,
561
+ centerX,
562
+ centerY,
563
+ width,
564
+ height,
565
+ locked: false,
566
+ crossOrigin
567
+ });
568
+ this.manager.mainView.completeImageUpload(uuid, url);
569
+ width /= 0.8;
570
+ height /= 0.8;
571
+ const originX = centerX - width / 2;
572
+ const originY = centerY - height / 2;
573
+ this.manager.moveCameraToContain({ originX, originY, width, height });
574
+ }
575
+ insertDocs(arg1, arg2) {
576
+ this._assertNotDestroyed();
577
+ if (typeof arg1 === "object" && "fileType" in arg1) {
578
+ return this._insertDocsImpl(arg1);
579
+ } else if (arg2 && arg2.status !== "Finished") {
580
+ throw new Error("FastboardApp cannot insert a converting doc.");
581
+ } else if (arg2 && "progress" in arg2) {
582
+ const title = arg1;
583
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
584
+ const scenes1 = arg2.progress.convertedFileList.map(convertedFileToScene);
585
+ const { scenes, taskId, url } = makeSlideParams(scenes1);
586
+ if (taskId && url) {
587
+ return this._insertDocsImpl({ fileType: "pptx", scenePath, scenes, title, taskId, url });
588
+ } else {
589
+ return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes: scenes1, title });
590
+ }
591
+ } else if (arg2 && arg2.prefix) {
592
+ const title = arg1;
593
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
594
+ const taskId = arg2.uuid;
595
+ const url = arg2.prefix;
596
+ this._insertDocsImpl({ fileType: "pptx", scenePath, taskId, title, url });
597
+ } else if (arg2 && arg2.images) {
598
+ const title = arg1;
599
+ const scenePath = `/${arg2.uuid}/${genUID()}`;
600
+ const scenes = [];
601
+ for (const name in arg2.images) {
602
+ const { width, height, url } = arg2.images[name];
603
+ scenes.push({ name, ppt: { width, height, src: url } });
604
+ }
605
+ return this._insertDocsImpl({ fileType: "pdf", scenePath, scenes, title });
606
+ } else {
607
+ throw new Error("Invalid input: not found 'progress', 'prefix' nor 'images'");
608
+ }
609
+ }
610
+ /** @internal */
611
+ _insertDocsImpl(_a) {
612
+ var _b = _a, { fileType, scenePath, title, scenes } = _b, attributes = __objRest(_b, ["fileType", "scenePath", "title", "scenes"]);
613
+ this._assertNotDestroyed();
614
+ switch (fileType) {
615
+ case "pdf":
616
+ return this.manager.addApp({
617
+ kind: "DocsViewer",
618
+ options: { scenePath, title, scenes }
619
+ });
620
+ case "pptx":
621
+ if (scenes && scenes[0].ppt) {
622
+ warn("no-ppt-in-scenes");
623
+ }
624
+ return this.manager.addApp({
625
+ kind: "Slide",
626
+ options: { scenePath, title, scenes },
627
+ attributes
628
+ });
629
+ }
630
+ }
631
+ /**
632
+ * Insert the Media Player app.
633
+ */
634
+ insertMedia(title, src) {
635
+ this._assertNotDestroyed();
636
+ return this.manager.addApp({
637
+ kind: windowManager.BuiltinApps.MediaPlayer,
638
+ options: { title },
639
+ attributes: { src }
640
+ });
641
+ }
642
+ /**
643
+ * Insert the Monaco Code Editor app.
644
+ * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.
645
+ */
646
+ insertCodeEditor() {
647
+ this._assertNotDestroyed();
648
+ return this.manager.addApp({
649
+ kind: "Monaco",
650
+ options: { title: "Code Editor" }
651
+ });
652
+ }
653
+ /**
654
+ * Insert the Countdown app.
655
+ * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.
656
+ */
657
+ insertCountdown() {
658
+ this._assertNotDestroyed();
659
+ return this.manager.addApp({
660
+ kind: "Countdown",
661
+ options: { title: "Countdown" }
662
+ });
663
+ }
664
+ /**
665
+ * Insert the GeoGebra app.
666
+ * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.
667
+ */
668
+ insertGeoGebra() {
669
+ this._assertNotDestroyed();
670
+ return this.manager.addApp({
671
+ kind: "GeoGebra",
672
+ options: { title: "GeoGebra" }
673
+ });
674
+ }
675
+ };
676
+ async function createFastboard(_a) {
677
+ var _b = _a, {
678
+ sdkConfig,
679
+ joinRoom: _c
680
+ } = _b, _d = _c, { callbacks } = _d, joinRoomParams = __objRest(_d, ["callbacks"]), {
681
+ managerConfig,
682
+ netlessApps
683
+ } = _b;
684
+ const sdk = new whiteWebSdk.WhiteWebSdk(__spreadProps(__spreadValues({}, sdkConfig), {
685
+ useMobXState: true
686
+ }));
687
+ const hotKeys = joinRoomParams.hotKeys || __spreadProps(__spreadValues({}, whiteWebSdk.DefaultHotKeys), {
688
+ changeToSelector: "s",
689
+ changeToLaserPointer: "z",
690
+ changeToPencil: "p",
691
+ changeToRectangle: "r",
692
+ changeToEllipse: "c",
693
+ changeToEraser: "e",
694
+ changeToText: "t",
695
+ changeToStraight: "l",
696
+ changeToArrow: "a",
697
+ changeToHand: "h"
698
+ });
699
+ if (netlessApps) {
700
+ netlessApps.forEach((app) => {
701
+ register({ kind: app.kind, src: app });
702
+ });
703
+ }
704
+ const room = await sdk.joinRoom(
705
+ __spreadProps(__spreadValues({
706
+ floatBar: true,
707
+ hotKeys
708
+ }, ensure_official_plugins(joinRoomParams)), {
709
+ useMultiViews: true,
710
+ disableNewPencil: false,
711
+ disableMagixEventDispatchLimit: true
712
+ }),
713
+ callbacks
714
+ );
715
+ const syncedStore$1 = await syncedStore.SyncedStorePlugin.init(room);
716
+ const manager = await windowManager.WindowManager.mount(__spreadProps(__spreadValues({
717
+ cursor: true
718
+ }, managerConfig), {
719
+ room
720
+ }));
721
+ manager.mainView.setCameraBound({
722
+ minContentMode: whiteWebSdk.contentModeScale(0.3),
723
+ maxContentMode: whiteWebSdk.contentModeScale(3)
724
+ });
725
+ return new FastboardApp(sdk, room, manager, hotKeys, syncedStore$1);
726
+ }
727
+ var FastboardPlayerBase = class {
728
+ constructor(sdk, player, manager, syncedStore) {
729
+ this.sdk = sdk;
730
+ this.player = player;
731
+ this.manager = manager;
732
+ this.syncedStore = syncedStore;
733
+ __publicField(this, "_destroyed", false);
734
+ }
735
+ /** @internal */
736
+ _assertNotDestroyed() {
737
+ if (this._destroyed) {
738
+ throw new Error("FastboardApp has been destroyed");
739
+ }
740
+ }
741
+ /** @internal */
742
+ _addPlayerListener(name, listener) {
743
+ this._assertNotDestroyed();
744
+ this.player.callbacks.on(name, listener);
745
+ return () => this.player.callbacks.off(name, listener);
746
+ }
747
+ /** @internal */
748
+ _addManagerListener(name, listener) {
749
+ this._assertNotDestroyed();
750
+ this.manager.emitter.on(name, listener);
751
+ return () => this.manager.emitter.off(name, listener);
752
+ }
753
+ /** @internal */
754
+ _addMainViewListener(name, listener) {
755
+ this._assertNotDestroyed();
756
+ this.manager.mainView.callbacks.on(name, listener);
757
+ return () => this.manager.mainView.callbacks.off(name, listener);
758
+ }
759
+ destroy() {
760
+ this._destroyed = true;
761
+ this.manager.destroy();
762
+ return this.player.callbacks.off();
763
+ }
764
+ };
765
+ var FastboardPlayer = class extends FastboardPlayerBase {
766
+ constructor() {
767
+ super(...arguments);
768
+ /**
769
+ * Player current time in milliseconds.
770
+ */
771
+ __publicField(this, "currentTime", writable(
772
+ this.player.progressTime,
773
+ (set) => {
774
+ set(this.player.progressTime);
775
+ return this._addPlayerListener("onProgressTimeChanged", set);
776
+ },
777
+ this.player.seekToProgressTime.bind(this.player)
778
+ ));
779
+ /**
780
+ * Player state, like "is it playing?".
781
+ */
782
+ __publicField(this, "phase", readable(this.player.phase, (set) => {
783
+ set(this.player.phase);
784
+ return this._addPlayerListener("onPhaseChanged", set);
785
+ }));
786
+ /**
787
+ * Will become true after buffering.
788
+ */
789
+ __publicField(this, "canplay", readable(this.player.isPlayable, (set) => {
790
+ set(this.player.isPlayable);
791
+ return this._addPlayerListener("onIsPlayableChanged", set);
792
+ }));
793
+ /** @internal */
794
+ __publicField(this, "_setPlaybackRate");
795
+ /**
796
+ * Playback speed, default `1`.
797
+ */
798
+ __publicField(this, "playbackRate", writable(
799
+ this.player.playbackSpeed,
800
+ (set) => {
801
+ this._setPlaybackRate = set;
802
+ set(this.player.playbackSpeed);
803
+ },
804
+ (value) => {
805
+ this.player.playbackSpeed = value;
806
+ this._setPlaybackRate(value);
807
+ }
808
+ ));
809
+ /**
810
+ * Playback duration in milliseconds.
811
+ */
812
+ __publicField(this, "duration", readable(this.player.timeDuration, (set) => {
813
+ set(this.player.timeDuration);
814
+ }));
815
+ /**
816
+ * Get state of room at that time, like "who was in the room?".
817
+ */
818
+ __publicField(this, "state", readable(this.player.state, (set) => {
819
+ set(this.player.state);
820
+ return this._addPlayerListener("onPlayerStateChanged", () => set(this.player.state));
821
+ }));
822
+ }
823
+ /**
824
+ * Render this player to some DOM.
825
+ */
826
+ bindContainer(container) {
827
+ this._assertNotDestroyed();
828
+ this.manager.bindContainer(container);
829
+ }
830
+ /**
831
+ * Move window-manager's collector to some place.
832
+ */
833
+ bindCollector(container) {
834
+ this._assertNotDestroyed();
835
+ this.manager.bindCollectorContainer(container);
836
+ }
837
+ /**
838
+ * Seek to some time in milliseconds.
839
+ */
840
+ seek(timestamp) {
841
+ this._assertNotDestroyed();
842
+ return this.player.seekToProgressTime(timestamp);
843
+ }
844
+ /**
845
+ * Change player state to playing.
846
+ */
847
+ play() {
848
+ this._assertNotDestroyed();
849
+ this.player.play();
850
+ }
851
+ /**
852
+ * Change player state to paused.
853
+ */
854
+ pause() {
855
+ this._assertNotDestroyed();
856
+ this.player.pause();
857
+ }
858
+ /**
859
+ * Change player state to stopped.
860
+ */
861
+ stop() {
862
+ this._assertNotDestroyed();
863
+ this.player.stop();
864
+ }
865
+ /**
866
+ * Set playback speed, a shortcut for `speed.set(x)`.
867
+ */
868
+ setPlaybackRate(value) {
869
+ this._assertNotDestroyed();
870
+ this.playbackRate.set(value);
871
+ }
872
+ };
873
+ async function replayFastboard(_a) {
874
+ var _b = _a, {
875
+ sdkConfig,
876
+ replayRoom: _c
877
+ } = _b, _d = _c, { callbacks } = _d, replayRoomParams = __objRest(_d, ["callbacks"]), {
878
+ managerConfig,
879
+ netlessApps
880
+ } = _b;
881
+ const sdk = new whiteWebSdk.WhiteWebSdk(__spreadProps(__spreadValues({}, sdkConfig), {
882
+ useMobXState: true
883
+ }));
884
+ if (netlessApps) {
885
+ netlessApps.forEach((app) => {
886
+ register({ kind: app.kind, src: app });
887
+ });
888
+ }
889
+ const player = await sdk.replayRoom(
890
+ __spreadProps(__spreadValues({}, ensure_official_plugins(replayRoomParams)), {
891
+ useMultiViews: true
892
+ }),
893
+ callbacks
894
+ );
895
+ const syncedStore$1 = await syncedStore.SyncedStorePlugin.init(player);
896
+ const managerPromise = windowManager.WindowManager.mount(__spreadProps(__spreadValues({
897
+ cursor: true
898
+ }, managerConfig), {
899
+ room: player
900
+ }));
901
+ player.play();
902
+ const manager = await managerPromise;
903
+ player.pause();
904
+ await player.seekToProgressTime(0);
905
+ return new FastboardPlayer(sdk, player, manager, syncedStore$1);
906
+ }
907
+
908
+ // src/helpers/listen.ts
909
+ function addRoomListener(room, name, listener) {
910
+ room.callbacks.on(name, listener);
911
+ return () => room.callbacks.off(name, listener);
912
+ }
913
+ function addPlayerListener(player, name, listener) {
914
+ player.callbacks.on(name, listener);
915
+ return () => player.callbacks.off(name, listener);
916
+ }
917
+ function addViewListener(view, name, listener) {
918
+ view.callbacks.on(name, listener);
919
+ return () => view.callbacks.off(name, listener);
920
+ }
921
+ function addManagerListener(manager, name, listener) {
922
+ return manager.emitter.on(name, listener);
923
+ }
924
+
925
+ // src/helpers/docs.ts
926
+ function dispatchDocsEvent(fastboard, event, options = {}) {
927
+ var _a, _b, _c;
928
+ const manager = "manager" in fastboard ? fastboard.manager : fastboard;
929
+ const appId = options.appId || manager.focused;
930
+ if (!appId) {
931
+ console.warn("not found " + (options.appId || "focused app"));
932
+ return false;
933
+ }
934
+ let page, input;
935
+ if (appId.startsWith("DocsViewer-")) {
936
+ const dom = (_b = (_a = manager.queryOne(appId)) == null ? void 0 : _a.box) == null ? void 0 : _b.$footer;
937
+ if (!dom) {
938
+ console.warn("not found app with id " + appId);
939
+ return false;
940
+ }
941
+ const click = (el) => {
942
+ el && el.dispatchEvent(new MouseEvent("click"));
943
+ };
944
+ switch (event) {
945
+ case "prevPage":
946
+ case "prevStep":
947
+ click(dom.querySelector('button[class$="btn-page-back"]'));
948
+ break;
949
+ case "nextPage":
950
+ case "nextStep":
951
+ click(dom.querySelector('button[class$="btn-page-next"]'));
952
+ break;
953
+ case "jumpToPage":
954
+ page = options.page;
955
+ input = dom.querySelector('input[class$="page-number-input"]');
956
+ if (!input || typeof page !== "number") {
957
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
958
+ return false;
959
+ }
960
+ input.value = "" + page;
961
+ input.dispatchEvent(new InputEvent("change"));
962
+ break;
963
+ default:
964
+ console.warn("unknown event " + event);
965
+ return false;
966
+ }
967
+ return true;
968
+ } else if (appId.startsWith("Slide-")) {
969
+ const app = (_c = manager.queryOne(appId)) == null ? void 0 : _c.appResult;
970
+ if (!app) {
971
+ console.warn("not found app with id " + appId);
972
+ return false;
973
+ }
974
+ switch (event) {
975
+ case "prevPage":
976
+ return app.prevPage();
977
+ case "nextPage":
978
+ return app.nextPage();
979
+ case "prevStep":
980
+ return app.prevStep();
981
+ case "nextStep":
982
+ return app.nextStep();
983
+ case "jumpToPage":
984
+ page = options.page;
985
+ if (typeof page !== "number") {
986
+ console.warn("failed to jump" + (page ? " to page " + page : ""));
987
+ return false;
988
+ }
989
+ return app.jumpToPage(page);
990
+ default:
991
+ console.warn("unknown event " + event);
992
+ return false;
993
+ }
994
+ } else {
995
+ console.warn("not supported app " + appId);
996
+ return false;
997
+ }
998
+ }
999
+
1000
+ exports.FastboardApp = FastboardApp;
1001
+ exports.FastboardPlayer = FastboardPlayer;
1002
+ exports.addManagerListener = addManagerListener;
1003
+ exports.addPlayerListener = addPlayerListener;
1004
+ exports.addRoomListener = addRoomListener;
1005
+ exports.addViewListener = addViewListener;
1006
+ exports.convertedFileToScene = convertedFileToScene;
1007
+ exports.createFastboard = createFastboard;
1008
+ exports.dispatchDocsEvent = dispatchDocsEvent;
1009
+ exports.genUID = genUID;
1010
+ exports.getImageSize = getImageSize;
1011
+ exports.makeSlideParams = makeSlideParams;
1012
+ exports.readable = readable;
1013
+ exports.register = register;
1014
+ exports.replayFastboard = replayFastboard;
1015
+ exports.version = version;
1016
+ exports.warn = warn;
1017
+ exports.writable = writable;
1018
+ //# sourceMappingURL=lite.js.map