@volter/editor-blender 0.1.95 → 0.1.96

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.
@@ -579,11 +579,16 @@ export class BlenderSkinDirector {
579
579
  const stopSettled = transport.onSettled(() => {
580
580
  void this.writeBookmark();
581
581
  });
582
+ let released = false;
582
583
  const detach = () => {
584
+ if (released) return;
585
+ released = true;
583
586
  stopSettled();
584
587
  detachSubject();
585
- if (this.#transport === transport) this.#transport = null;
586
- this.#detach = null;
588
+ if (this.#detach === detach) {
589
+ if (this.#transport === transport) this.#transport = null;
590
+ this.#detach = null;
591
+ }
587
592
  };
588
593
  this.#detach = detach;
589
594
  // The bookmark READ, if the clip is already loaded when we attach.
@@ -556,17 +556,33 @@ function BlenderViewportArea({
556
556
  if (!documentId || !main) return;
557
557
  const { transport } = editorHost();
558
558
  let detach: (() => void) | null = null;
559
+ let cancelled = false;
560
+ let queued = false;
559
561
  const attach = (): void => {
560
- if (detach) return;
562
+ if (cancelled || detach) return;
561
563
  const handle = transport.for(documentId);
562
564
  if (!handle) return;
563
565
  detach = blenderSkin.attachTo(handle);
564
566
  };
565
- attach();
566
- const stop = transport.subscribe(attach);
567
+ // attachTo restores the loaded clip's bookmark through transport.seek.
568
+ // That publishes the skin/transport snapshots consumed by the Timeline's
569
+ // separate React root. Keep those updates outside this root's passive
570
+ // effect stack, including a registry notification during another effect.
571
+ const requestAttach = (): void => {
572
+ if (cancelled || queued) return;
573
+ queued = true;
574
+ queueMicrotask(() => { queued = false; attach(); });
575
+ };
576
+ requestAttach();
577
+ const stop = transport.subscribe(requestAttach);
567
578
  return () => {
579
+ cancelled = true;
568
580
  stop();
569
- detach?.();
581
+ // Detaching the subject also publishes the transport snapshot. A
582
+ // superseded effect releases its own handle before the next attachment.
583
+ const release = detach;
584
+ detach = null;
585
+ if (release) queueMicrotask(release);
570
586
  };
571
587
  }, [documentId, main]);
572
588
  /**
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@volter/editor-blender",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "AGPL-3.0-only AND GPL-3.0-or-later",
5
- "version": "0.1.95",
5
+ "version": "0.1.96",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -70,14 +70,14 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "@modelcontextprotocol/sdk": "1.30.0",
73
- "@volter/blender-engine": "0.1.93",
74
- "@volter/editor-threejs": "0.5.155",
73
+ "@volter/blender-engine": "0.1.94",
74
+ "@volter/editor-threejs": "0.5.156",
75
75
  "zod": "^4.3.6"
76
76
  },
77
77
  "peerDependencies": {
78
- "@volter/editor-live": "0.5.155",
79
- "@volter/editor-project": "0.5.155",
80
- "@volter/editor-sdk": "0.5.155",
78
+ "@volter/editor-live": "0.5.156",
79
+ "@volter/editor-project": "0.5.156",
80
+ "@volter/editor-sdk": "0.5.156",
81
81
  "react": "^19.0.0",
82
82
  "react-dom": "^19.0.0",
83
83
  "three": "^0.180.0",