@netless/fastboard-core 0.3.8 → 0.3.9

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
@@ -104,20 +104,43 @@ function writable(value, start = noop, set) {
104
104
  reaction: internal.reaction,
105
105
  set,
106
106
  update(fn) {
107
- set(fn(value));
107
+ set(fn(internal.value));
108
108
  }
109
109
  };
110
110
  }
111
111
 
112
112
  // src/utils/misc.ts
113
- function getImageSize(url, fallback) {
113
+ function getImageSize(url, fallback, crossOrigin) {
114
114
  return new Promise((resolve) => {
115
115
  const img = new Image();
116
+ applyCrossOrigin(img, url, crossOrigin);
116
117
  img.onload = () => resolve(img);
117
118
  img.onerror = () => resolve(fallback);
118
119
  img.src = url;
119
120
  });
120
121
  }
122
+ function applyCrossOrigin(image, src, crossOrigin) {
123
+ if (crossOrigin === void 0 && !src.startsWith("data:")) {
124
+ image.crossOrigin = determineCrossOrigin(src);
125
+ } else if (crossOrigin !== false) {
126
+ image.crossOrigin = typeof crossOrigin === "string" ? crossOrigin : "anonymous";
127
+ }
128
+ }
129
+ function determineCrossOrigin(src) {
130
+ if (src.startsWith("data:") || typeof window === "undefined" || !window.location) {
131
+ return "";
132
+ }
133
+ const loc = window.location;
134
+ try {
135
+ const parsedUrl = new URL(src, document.baseURI);
136
+ if (parsedUrl.hostname !== loc.hostname || parsedUrl.port !== loc.port || parsedUrl.protocol !== loc.protocol) {
137
+ return "anonymous";
138
+ }
139
+ return "";
140
+ } catch (e) {
141
+ return "";
142
+ }
143
+ }
121
144
  function makeSlideParams(scenes) {
122
145
  const emptyScenes = [];
123
146
  let taskId = "";
@@ -214,7 +237,7 @@ for (const kind in DefaultApps) {
214
237
  }
215
238
  }
216
239
  var register = WindowManager.register.bind(WindowManager);
217
- var version = "0.3.8";
240
+ var version = "0.3.9";
218
241
  if (typeof window !== "undefined") {
219
242
  let str = window.__netlessUA || "";
220
243
  str += ` ${"@netless/fastboard"}@${version} `;
@@ -231,26 +254,33 @@ var FastboardAppBase = class {
231
254
  this.syncedStore = syncedStore;
232
255
  __publicField(this, "_destroyed", false);
233
256
  }
257
+ /** @internal */
234
258
  _assertNotDestroyed() {
235
259
  if (this._destroyed) {
236
260
  throw new Error("FastboardApp has been destroyed");
237
261
  }
238
262
  }
263
+ /** @internal */
239
264
  _addRoomListener(name, listener) {
240
265
  this._assertNotDestroyed();
241
266
  this.room.callbacks.on(name, listener);
242
267
  return () => this.room.callbacks.off(name, listener);
243
268
  }
269
+ /** @internal */
244
270
  _addManagerListener(name, listener) {
245
271
  this._assertNotDestroyed();
246
272
  this.manager.emitter.on(name, listener);
247
273
  return () => this.manager.emitter.off(name, listener);
248
274
  }
275
+ /** @internal */
249
276
  _addMainViewListener(name, listener) {
250
277
  this._assertNotDestroyed();
251
278
  this.manager.mainView.callbacks.on(name, listener);
252
279
  return () => this.manager.mainView.callbacks.off(name, listener);
253
280
  }
281
+ /**
282
+ * Destroy fastboard (disconnect from the whiteboard room).
283
+ */
254
284
  destroy() {
255
285
  this._destroyed = true;
256
286
  this.manager.destroy();
@@ -260,6 +290,9 @@ var FastboardAppBase = class {
260
290
  var FastboardApp = class extends FastboardAppBase {
261
291
  constructor() {
262
292
  super(...arguments);
293
+ /**
294
+ * Is current room writable?
295
+ */
263
296
  __publicField(this, "writable", writable(
264
297
  this.room.isWritable,
265
298
  (set) => {
@@ -268,34 +301,63 @@ var FastboardApp = class extends FastboardAppBase {
268
301
  },
269
302
  this.room.setWritable.bind(this.room)
270
303
  ));
304
+ /**
305
+ * Is current room online?
306
+ */
271
307
  __publicField(this, "phase", readable(this.room.phase, (set) => {
272
308
  set(this.room.phase);
273
309
  return this._addRoomListener("onPhaseChanged", set);
274
310
  }));
311
+ /**
312
+ * Current window-manager's windows' state (is it maximized?).
313
+ */
275
314
  __publicField(this, "boxState", readable(this.manager.boxState, (set) => {
276
315
  set(this.manager.boxState);
277
316
  return this._addManagerListener("boxStateChange", set);
278
317
  }));
318
+ /**
319
+ * Current window-manager's focused app's id.
320
+ * @example "HelloWorld-1A2b3C4d"
321
+ */
279
322
  __publicField(this, "focusedApp", readable(this.manager.focused, (set) => {
280
323
  set(this.manager.focused);
281
324
  return this._addManagerListener("focusedChange", set);
282
325
  }));
326
+ /**
327
+ * How many times can I call `app.redo()`?
328
+ */
283
329
  __publicField(this, "canRedoSteps", readable(this.manager.canRedoSteps, (set) => {
284
330
  set(this.manager.canRedoSteps);
285
331
  return this._addManagerListener("canRedoStepsChange", set);
286
332
  }));
333
+ /**
334
+ * How many times can I call `app.undo()`?
335
+ */
287
336
  __publicField(this, "canUndoSteps", readable(this.manager.canUndoSteps, (set) => {
288
337
  set(this.manager.canUndoSteps);
289
338
  return this._addManagerListener("canUndoStepsChange", set);
290
339
  }));
340
+ /**
341
+ * Current camera information of main view.
342
+ *
343
+ * Change the camera position by `app.moveCamera()`.
344
+ */
291
345
  __publicField(this, "camera", readable(this.manager.camera, (set) => {
292
346
  set(this.manager.camera);
293
347
  return this._addMainViewListener("onCameraUpdated", set);
294
348
  }));
349
+ /**
350
+ * Current tool's info, like "is using pencil?", "what color?".
351
+ *
352
+ * Change the tool by `app.setAppliance()`.
353
+ */
295
354
  __publicField(this, "memberState", readable(this.room.state.memberState, (set) => {
296
355
  set(this.room.state.memberState);
297
356
  return this._addRoomListener("onRoomStateChanged", ({ memberState: m }) => m && set(m));
298
357
  }));
358
+ /**
359
+ * 0..n-1, current index of main view scenes.
360
+ */
299
361
  __publicField(this, "sceneIndex", writable(
300
362
  this.manager.mainViewSceneIndex,
301
363
  (set) => {
@@ -304,11 +366,18 @@ var FastboardApp = class extends FastboardAppBase {
304
366
  },
305
367
  this.manager.setMainViewSceneIndex.bind(this.manager)
306
368
  ));
369
+ /**
370
+ * How many pages are in the main view?
371
+ */
307
372
  __publicField(this, "sceneLength", readable(this.manager.mainViewScenesLength, (set) => {
308
373
  set(this.manager.mainViewScenesLength);
309
374
  return this._addManagerListener("mainViewScenesLengthChange", set);
310
375
  }));
376
+ /** @internal */
311
377
  __publicField(this, "_appsStatus", {});
378
+ /**
379
+ * Apps status.
380
+ */
312
381
  __publicField(this, "appsStatus", readable(
313
382
  {},
314
383
  (set) => this._addManagerListener("loadApp", ({ kind, status, reason }) => {
@@ -317,34 +386,58 @@ var FastboardApp = class extends FastboardAppBase {
317
386
  })
318
387
  ));
319
388
  }
389
+ /**
390
+ * Render this app to some DOM.
391
+ */
320
392
  bindContainer(container) {
321
393
  this._assertNotDestroyed();
322
394
  this.manager.bindContainer(container);
323
395
  }
396
+ /**
397
+ * Move window-manager's collector to some place.
398
+ */
324
399
  bindCollector(container) {
325
400
  this._assertNotDestroyed();
326
401
  this.manager.bindCollectorContainer(container);
327
402
  }
403
+ /**
404
+ * Undo a step on main view.
405
+ */
328
406
  undo() {
329
407
  this._assertNotDestroyed();
330
408
  this.manager.undo();
331
409
  }
410
+ /**
411
+ * Redo a step on main view.
412
+ */
332
413
  redo() {
333
414
  this._assertNotDestroyed();
334
415
  this.manager.redo();
335
416
  }
417
+ /**
418
+ * Move current main view's camera position.
419
+ */
336
420
  moveCamera(camera) {
337
421
  this._assertNotDestroyed();
338
422
  this.manager.moveCamera(camera);
339
423
  }
424
+ /**
425
+ * Move current main view's camera to include a rectangle.
426
+ */
340
427
  moveCameraToContain(rectangle) {
341
428
  this._assertNotDestroyed();
342
429
  this.manager.moveCameraToContain(rectangle);
343
430
  }
431
+ /**
432
+ * Delete all things on the main view.
433
+ */
344
434
  cleanCurrentScene() {
345
435
  this._assertNotDestroyed();
346
436
  this.manager.cleanCurrentScene();
347
437
  }
438
+ /**
439
+ * Set current tool, like "pencil".
440
+ */
348
441
  setAppliance(appliance, shape) {
349
442
  this._assertNotDestroyed();
350
443
  this.manager.mainView.setMemberState({
@@ -352,39 +445,97 @@ var FastboardApp = class extends FastboardAppBase {
352
445
  shapeType: shape
353
446
  });
354
447
  }
448
+ /**
449
+ * Set pencil and shape's thickness.
450
+ */
355
451
  setStrokeWidth(strokeWidth) {
356
452
  this._assertNotDestroyed();
357
453
  this.manager.mainView.setMemberState({ strokeWidth });
358
454
  }
455
+ /**
456
+ * Set pencil and shape's color.
457
+ */
359
458
  setStrokeColor(strokeColor) {
360
459
  this._assertNotDestroyed();
361
460
  this.manager.mainView.setMemberState({ strokeColor });
362
461
  }
462
+ /**
463
+ * Set text size. Default is 16.
464
+ */
363
465
  setTextSize(textSize) {
364
466
  this._assertNotDestroyed();
365
467
  this.manager.mainView.setMemberState({ textSize });
366
468
  }
469
+ /**
470
+ * Set text color.
471
+ *
472
+ * @example
473
+ * setTextColor([0x66, 0xcc, 0xff])
474
+ */
367
475
  setTextColor(textColor) {
368
476
  this._assertNotDestroyed();
369
477
  this.manager.mainView.setMemberState({ textColor });
370
478
  }
479
+ /**
480
+ * Toggle dotted line effect on pencil.
481
+ */
482
+ toggleDottedLine(force) {
483
+ this._assertNotDestroyed();
484
+ this.manager.mainView.setMemberState({ dottedLine: force != null ? force : !this.memberState.value.dottedLine });
485
+ }
486
+ /**
487
+ * Set pencil eraser size.
488
+ */
489
+ setPencilEraserSize(size) {
490
+ this._assertNotDestroyed();
491
+ this.manager.mainView.setMemberState({ pencilEraserSize: size });
492
+ }
493
+ /**
494
+ * Goto previous page (the main whiteboard view).
495
+ */
371
496
  prevPage() {
372
497
  this._assertNotDestroyed();
373
498
  return this.manager.prevPage();
374
499
  }
500
+ /**
501
+ * Goto next page (the main whiteboard view).
502
+ */
375
503
  nextPage() {
376
504
  this._assertNotDestroyed();
377
505
  return this.manager.nextPage();
378
506
  }
507
+ /**
508
+ * Add one page to the main whiteboard view.
509
+ *
510
+ * @example
511
+ * addPage({ after: true }) // add one page right after current one.
512
+ * nextPage() // then, goto that page.
513
+ */
379
514
  addPage(params) {
380
515
  this._assertNotDestroyed();
381
516
  return this.manager.addPage(params);
382
517
  }
518
+ /**
519
+ * Remove one page at given index or current page (by default).
520
+ *
521
+ * Requires `@netless/window-manager` >= 0.4.30.
522
+ *
523
+ * @example
524
+ * removePage() // remove current page
525
+ */
383
526
  removePage(index) {
384
527
  this._assertNotDestroyed();
385
528
  return this.manager.removePage(index);
386
529
  }
387
- async insertImage(url) {
530
+ /**
531
+ * Insert an image to the main view.
532
+ *
533
+ * @param crossOrigin Whether to load the image with CORS enabled, default is `true`.
534
+ *
535
+ * @example
536
+ * insertImage("https://i.imgur.com/CzXTtJV.jpg")
537
+ */
538
+ async insertImage(url, crossOrigin) {
388
539
  this._assertNotDestroyed();
389
540
  await this.manager.switchMainViewToWriter();
390
541
  const { divElement } = this.manager.mainView;
@@ -393,13 +544,21 @@ var FastboardApp = class extends FastboardAppBase {
393
544
  height: (divElement == null ? void 0 : divElement.scrollHeight) || window.innerHeight
394
545
  };
395
546
  const maxWidth = containerSize.width * 0.8;
396
- let { width, height } = await getImageSize(url, containerSize);
547
+ let { width, height } = await getImageSize(url, containerSize, crossOrigin);
397
548
  const scale = Math.min(maxWidth / width, 1);
398
549
  const uuid = genUID();
399
550
  const { centerX, centerY } = this.manager.camera;
400
551
  width *= scale;
401
552
  height *= scale;
402
- this.manager.mainView.insertImage({ uuid, centerX, centerY, width, height, locked: false });
553
+ this.manager.mainView.insertImage({
554
+ uuid,
555
+ centerX,
556
+ centerY,
557
+ width,
558
+ height,
559
+ locked: false,
560
+ crossOrigin
561
+ });
403
562
  this.manager.mainView.completeImageUpload(uuid, url);
404
563
  width /= 0.8;
405
564
  height /= 0.8;
@@ -442,6 +601,7 @@ var FastboardApp = class extends FastboardAppBase {
442
601
  throw new Error("Invalid input: not found 'progress', 'prefix' nor 'images'");
443
602
  }
444
603
  }
604
+ /** @internal */
445
605
  _insertDocsImpl(_a) {
446
606
  var _b = _a, { fileType, scenePath, title, scenes } = _b, attributes = __objRest(_b, ["fileType", "scenePath", "title", "scenes"]);
447
607
  this._assertNotDestroyed();
@@ -462,6 +622,9 @@ var FastboardApp = class extends FastboardAppBase {
462
622
  });
463
623
  }
464
624
  }
625
+ /**
626
+ * Insert the Media Player app.
627
+ */
465
628
  insertMedia(title, src) {
466
629
  this._assertNotDestroyed();
467
630
  return this.manager.addApp({
@@ -470,6 +633,10 @@ var FastboardApp = class extends FastboardAppBase {
470
633
  attributes: { src }
471
634
  });
472
635
  }
636
+ /**
637
+ * Insert the Monaco Code Editor app.
638
+ * @deprecated Use `app.manager.addApp({ kind: 'Monaco' })` instead.
639
+ */
473
640
  insertCodeEditor() {
474
641
  this._assertNotDestroyed();
475
642
  return this.manager.addApp({
@@ -477,6 +644,10 @@ var FastboardApp = class extends FastboardAppBase {
477
644
  options: { title: "Code Editor" }
478
645
  });
479
646
  }
647
+ /**
648
+ * Insert the Countdown app.
649
+ * @deprecated Use `app.manager.addApp({ kind: 'Countdown' })` instead.
650
+ */
480
651
  insertCountdown() {
481
652
  this._assertNotDestroyed();
482
653
  return this.manager.addApp({
@@ -484,6 +655,10 @@ var FastboardApp = class extends FastboardAppBase {
484
655
  options: { title: "Countdown" }
485
656
  });
486
657
  }
658
+ /**
659
+ * Insert the GeoGebra app.
660
+ * @deprecated Use `app.manager.addApp({ kind: 'GeoGebra' })` instead.
661
+ */
487
662
  insertGeoGebra() {
488
663
  this._assertNotDestroyed();
489
664
  return this.manager.addApp({
@@ -551,21 +726,25 @@ var FastboardPlayerBase = class {
551
726
  this.syncedStore = syncedStore;
552
727
  __publicField(this, "_destroyed", false);
553
728
  }
729
+ /** @internal */
554
730
  _assertNotDestroyed() {
555
731
  if (this._destroyed) {
556
732
  throw new Error("FastboardApp has been destroyed");
557
733
  }
558
734
  }
735
+ /** @internal */
559
736
  _addPlayerListener(name, listener) {
560
737
  this._assertNotDestroyed();
561
738
  this.player.callbacks.on(name, listener);
562
739
  return () => this.player.callbacks.off(name, listener);
563
740
  }
741
+ /** @internal */
564
742
  _addManagerListener(name, listener) {
565
743
  this._assertNotDestroyed();
566
744
  this.manager.emitter.on(name, listener);
567
745
  return () => this.manager.emitter.off(name, listener);
568
746
  }
747
+ /** @internal */
569
748
  _addMainViewListener(name, listener) {
570
749
  this._assertNotDestroyed();
571
750
  this.manager.mainView.callbacks.on(name, listener);
@@ -580,6 +759,9 @@ var FastboardPlayerBase = class {
580
759
  var FastboardPlayer = class extends FastboardPlayerBase {
581
760
  constructor() {
582
761
  super(...arguments);
762
+ /**
763
+ * Player current time in milliseconds.
764
+ */
583
765
  __publicField(this, "currentTime", writable(
584
766
  this.player.progressTime,
585
767
  (set) => {
@@ -588,15 +770,25 @@ var FastboardPlayer = class extends FastboardPlayerBase {
588
770
  },
589
771
  this.player.seekToProgressTime.bind(this.player)
590
772
  ));
773
+ /**
774
+ * Player state, like "is it playing?".
775
+ */
591
776
  __publicField(this, "phase", readable(this.player.phase, (set) => {
592
777
  set(this.player.phase);
593
778
  return this._addPlayerListener("onPhaseChanged", set);
594
779
  }));
780
+ /**
781
+ * Will become true after buffering.
782
+ */
595
783
  __publicField(this, "canplay", readable(this.player.isPlayable, (set) => {
596
784
  set(this.player.isPlayable);
597
785
  return this._addPlayerListener("onIsPlayableChanged", set);
598
786
  }));
787
+ /** @internal */
599
788
  __publicField(this, "_setPlaybackRate");
789
+ /**
790
+ * Playback speed, default `1`.
791
+ */
600
792
  __publicField(this, "playbackRate", writable(
601
793
  this.player.playbackSpeed,
602
794
  (set) => {
@@ -608,38 +800,65 @@ var FastboardPlayer = class extends FastboardPlayerBase {
608
800
  this._setPlaybackRate(value);
609
801
  }
610
802
  ));
803
+ /**
804
+ * Playback duration in milliseconds.
805
+ */
611
806
  __publicField(this, "duration", readable(this.player.timeDuration, (set) => {
612
807
  set(this.player.timeDuration);
613
808
  }));
809
+ /**
810
+ * Get state of room at that time, like "who was in the room?".
811
+ */
614
812
  __publicField(this, "state", readable(this.player.state, (set) => {
615
813
  set(this.player.state);
616
814
  return this._addPlayerListener("onPlayerStateChanged", () => set(this.player.state));
617
815
  }));
618
816
  }
817
+ /**
818
+ * Render this player to some DOM.
819
+ */
619
820
  bindContainer(container) {
620
821
  this._assertNotDestroyed();
621
822
  this.manager.bindContainer(container);
622
823
  }
824
+ /**
825
+ * Move window-manager's collector to some place.
826
+ */
623
827
  bindCollector(container) {
624
828
  this._assertNotDestroyed();
625
829
  this.manager.bindCollectorContainer(container);
626
830
  }
831
+ /**
832
+ * Seek to some time in milliseconds.
833
+ */
627
834
  seek(timestamp) {
628
835
  this._assertNotDestroyed();
629
836
  return this.player.seekToProgressTime(timestamp);
630
837
  }
838
+ /**
839
+ * Change player state to playing.
840
+ */
631
841
  play() {
632
842
  this._assertNotDestroyed();
633
843
  this.player.play();
634
844
  }
845
+ /**
846
+ * Change player state to paused.
847
+ */
635
848
  pause() {
636
849
  this._assertNotDestroyed();
637
850
  this.player.pause();
638
851
  }
852
+ /**
853
+ * Change player state to stopped.
854
+ */
639
855
  stop() {
640
856
  this._assertNotDestroyed();
641
857
  this.player.stop();
642
858
  }
859
+ /**
860
+ * Set playback speed, a shortcut for `speed.set(x)`.
861
+ */
643
862
  setPlaybackRate(value) {
644
863
  this._assertNotDestroyed();
645
864
  this.playbackRate.set(value);
@@ -773,5 +992,4 @@ function dispatchDocsEvent(fastboard, event, options = {}) {
773
992
  }
774
993
 
775
994
  export { FastboardApp, FastboardPlayer, addManagerListener, addPlayerListener, addRoomListener, addViewListener, convertedFileToScene, createFastboard, dispatchDocsEvent, genUID, getImageSize, makeSlideParams, readable, register, replayFastboard, version, warn, writable };
776
- //# sourceMappingURL=out.js.map
777
- //# sourceMappingURL=index.mjs.map
995
+ //# sourceMappingURL=index.mjs.map