@q9labsai/chalk-whiteboard 4.1.4 → 4.1.7

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.
@@ -441,6 +441,7 @@ var ExcalidrawCollabEngine = class {
441
441
  broadcastedElementVersions = /* @__PURE__ */ new Map();
442
442
  submissionInFlight = false;
443
443
  dirtyDuringSubmission = false;
444
+ disposed = false;
444
445
  changeDebounce = null;
445
446
  fullSyncTimer = null;
446
447
  filesSync;
@@ -464,16 +465,22 @@ var ExcalidrawCollabEngine = class {
464
465
  return commit;
465
466
  }
466
467
  dispose() {
468
+ if (this.disposed) return;
469
+ const hasPendingChange = this.changeDebounce !== null || this.dirtyDuringSubmission;
470
+ this.disposed = true;
467
471
  if (this.changeDebounce) clearTimeout(this.changeDebounce);
468
- if (this.fullSyncTimer) clearTimeout(this.fullSyncTimer);
469
472
  this.changeDebounce = null;
473
+ if (hasPendingChange) this.flushOnDispose();
474
+ if (this.fullSyncTimer) clearTimeout(this.fullSyncTimer);
470
475
  this.fullSyncTimer = null;
476
+ this.dirtyDuringSubmission = false;
471
477
  this.filesSync.dispose();
472
478
  this.presence.dispose();
473
479
  this.unsubscribe();
474
480
  this.unsubPointerUp?.();
475
481
  }
476
482
  handleChange(_elements, _appState, files) {
483
+ if (this.disposed) return;
477
484
  const elementsAll = this.opts.excalidrawAPI.getSceneElementsIncludingDeleted();
478
485
  this.filesSync.handleLocalScene(elementsAll, files);
479
486
  if (!this.canDraw) return;
@@ -540,6 +547,7 @@ var ExcalidrawCollabEngine = class {
540
547
  });
541
548
  }
542
549
  flushNow() {
550
+ if (this.disposed) return;
543
551
  const context = this.submissionContext();
544
552
  if (!context) return;
545
553
  const elementsHash = hashElementsVersion(context.elements);
@@ -553,26 +561,43 @@ var ExcalidrawCollabEngine = class {
553
561
  if (delta.length === 0) return;
554
562
  this.submit(context.sceneId, context.sceneGeneration ?? null, false, delta, elementsHash);
555
563
  }
564
+ flushOnDispose() {
565
+ const context = this.submissionContext({ allowDisposed: true, allowInFlight: true });
566
+ if (!context) return;
567
+ const elementsHash = hashElementsVersion(context.elements);
568
+ if (elementsHash === this.lastBroadcastedOrReceivedElementsHash) return;
569
+ const syncableAll = filterSyncableElements(context.elements);
570
+ const delta = [];
571
+ for (const element of syncableAll) {
572
+ const previousVersion = this.broadcastedElementVersions.get(element.id) ?? 0;
573
+ if (!previousVersion || element.version > previousVersion) delta.push(element);
574
+ }
575
+ if (delta.length === 0) return;
576
+ this.submitFinalUpdate(context.sceneId, context.sceneGeneration ?? null, delta);
577
+ }
556
578
  scheduleFullSync() {
557
- if (this.fullSyncTimer) return;
579
+ if (this.disposed || this.fullSyncTimer) return;
558
580
  this.fullSyncTimer = setTimeout(() => {
559
581
  this.fullSyncTimer = null;
582
+ if (this.disposed) return;
560
583
  this.sendFullSync();
561
584
  }, FULL_SYNC_INTERVAL_MS);
562
585
  }
563
586
  sendFullSync() {
587
+ if (this.disposed) return;
564
588
  const context = this.submissionContext();
565
589
  if (!context) return;
566
590
  const syncableAll = filterSyncableElements(context.elements);
567
591
  this.submit(context.sceneId, context.sceneGeneration ?? null, true, syncableAll, hashElementsVersion(context.elements));
568
592
  }
569
- submissionContext() {
593
+ submissionContext(options = {}) {
594
+ if (this.disposed && !options.allowDisposed) return null;
570
595
  if (!this.canDraw) return null;
571
596
  if (!this.sceneId) {
572
597
  this.requestSnapshot();
573
598
  return null;
574
599
  }
575
- if (this.submissionInFlight) {
600
+ if (this.submissionInFlight && !options.allowInFlight) {
576
601
  this.dirtyDuringSubmission = true;
577
602
  return null;
578
603
  }
@@ -591,6 +616,7 @@ var ExcalidrawCollabEngine = class {
591
616
  syncAll,
592
617
  elements: elements.map(toWireElement)
593
618
  }).then((commit) => {
619
+ if (this.disposed) return;
594
620
  if (commit.sceneId !== sceneId || this.sceneId !== sceneId || this.sceneGeneration !== sceneGeneration) {
595
621
  this.requestSnapshot();
596
622
  return;
@@ -601,10 +627,28 @@ var ExcalidrawCollabEngine = class {
601
627
  this.lastBroadcastedOrReceivedElementsHash = elementsHash;
602
628
  this.scheduleFullSync();
603
629
  }).catch(this.opts.onSubmissionError).finally(() => {
630
+ if (this.disposed) return;
604
631
  this.submissionInFlight = false;
605
- if (this.dirtyDuringSubmission) this.flushNow();
632
+ const shouldFlush = this.dirtyDuringSubmission;
633
+ this.dirtyDuringSubmission = false;
634
+ if (!this.disposed && shouldFlush) this.flushNow();
606
635
  });
607
636
  }
637
+ submitFinalUpdate(sceneId, sceneGeneration, elements) {
638
+ let submission;
639
+ try {
640
+ submission = this.opts.submitUpdate({
641
+ sceneId,
642
+ ...sceneGeneration ? { sceneGeneration } : {},
643
+ syncAll: false,
644
+ elements: elements.map(toWireElement)
645
+ });
646
+ } catch (cause) {
647
+ this.opts.onSubmissionError?.(cause);
648
+ return;
649
+ }
650
+ void submission.catch((cause) => this.opts.onSubmissionError?.(cause));
651
+ }
608
652
  applyRemoteElements(args) {
609
653
  const remoteSceneId = args.sceneId;
610
654
  if (!this.sceneId) {
@@ -645,7 +689,11 @@ var ExcalidrawCollabEngine = class {
645
689
  this.filesSync.handleRemoteScene(reconciled);
646
690
  }
647
691
  requestSnapshot() {
648
- void Promise.resolve().then(() => this.opts.requestSnapshot()).catch((cause) => this.opts.onSubmissionError?.(cause));
692
+ if (this.disposed) return;
693
+ void Promise.resolve().then(() => {
694
+ if (this.disposed) return;
695
+ return this.opts.requestSnapshot();
696
+ }).catch((cause) => this.opts.onSubmissionError?.(cause));
649
697
  }
650
698
  };
651
699
 
@@ -56,6 +56,7 @@ export declare class ExcalidrawCollabEngine {
56
56
  private broadcastedElementVersions;
57
57
  private submissionInFlight;
58
58
  private dirtyDuringSubmission;
59
+ private disposed;
59
60
  private changeDebounce;
60
61
  private fullSyncTimer;
61
62
  private readonly filesSync;
@@ -94,10 +95,12 @@ export declare class ExcalidrawCollabEngine {
94
95
  appState?: AppState;
95
96
  }): void;
96
97
  private flushNow;
98
+ private flushOnDispose;
97
99
  private scheduleFullSync;
98
100
  private sendFullSync;
99
101
  private submissionContext;
100
102
  private submit;
103
+ private submitFinalUpdate;
101
104
  private applyRemoteElements;
102
105
  private requestSnapshot;
103
106
  }
@@ -6,7 +6,7 @@ import {
6
6
  fromWireElement,
7
7
  isWireElement,
8
8
  toWireElement
9
- } from "../chunk-SQH5KXIR.js";
9
+ } from "../chunk-GCF4VS3K.js";
10
10
  export {
11
11
  ExcalidrawCollabEngine,
12
12
  fromWireElement,
@@ -1216,8 +1216,8 @@
1216
1216
  },
1217
1217
  {
1218
1218
  "path": "renderer.js",
1219
- "bytes": 8498299,
1220
- "sha256": "9ebd3f7ccb4f2b999f40081636e51aa941dae8332ad861397daa5df43e595ee7"
1219
+ "bytes": 8499347,
1220
+ "sha256": "8fb16da140966885912fd55616156b73e24dafc94e7dd0996e169d202714281a"
1221
1221
  },
1222
1222
  {
1223
1223
  "path": "THIRD_PARTY_NOTICES.json",