fix(book): J3-data — sweep the last inline nextFrame readers

Two stragglers from the migration commit:

- _bookPortOnClick read layer.nextFrame?.frameId to decide whether
  the click should break a thread. Now reads from the thread
  collection via _findThreadForFrame + _frameIndexInThread.
- The out-port tooltip read layer.nextFrame.frameId for the
  '⌗xxxxxx' destination hint. Switched to the pre-computed nextRef
  variable (already derived from threads[] earlier in the function).
- addBookTextFrame no longer initializes 'nextFrame: null' on new
  layers — that field is gone. Thread membership comes from
  book.threads[]; new frames are solo until linked.

After this sweep, no runtime code path reads layer.nextFrame. Only
the one-time migrator still touches it (intentional — it converts
legacy inline data into the collection then deletes the field).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.7 committed 2026-06-05 09:01:32 -04:00
1 parent ee77820284
commit 75fc29533e
1 file changed
+8 -7
+8 -7
View File
@@ -10255,12 +10255,9 @@
stroke: { type: 'none', color: '#60a5fa', width: 0, dash: 'solid' },
// Phase J2: stable frameId for thread addressing. Independent
// of the layer's `id` so a thread definition survives a layer
// delete + re-add (if the user keeps the frameId in mind, or
// we surface it in the inspector).
// delete + re-add. Thread membership + chapter source live on
// book.threads[] (J3-data-migration), not inline on the layer.
frameId: makeBookEntryId(),
// Phase J3: when threaded, points at the next frame in the
// chain ({ pageId, frameId }) or null for end-of-thread.
nextFrame: null,
// Phase J4.d: frame typography. Authors strip markdown
// formatting on import; styling applies here in the design
// phase. Defaults to a reasonable book body style.
@@ -24193,8 +24190,12 @@
ev.preventDefault();
ev.stopPropagation();
if (portKind === 'out') {
// J3-data-migration: linked-out check reads from threads[].
const thread = _findThreadForFrame(state.book, layer.frameId);
const idx = thread ? _frameIndexInThread(thread, layer.frameId) : -1;
const isLinkedOut = thread && idx >= 0 && idx < thread.frames.length - 1;
// Already linked? Click breaks the thread at this point.
if (layer.nextFrame?.frameId) {
if (isLinkedOut) {
_breakBookFrameLink(layer);
return;
}
@@ -24260,7 +24261,7 @@
+ (linkedOut ? ' linked' : '')
+ (isLoadingSource ? ' loadingSource' : '');
outPort.title = linkedOut
? `Out port — text continues into frame ⌗${String(layer.nextFrame.frameId).slice(0,6)}. Click to break the thread.`
? `Out port — text continues into frame ⌗${String(nextRef?.frameId || '').slice(0,6)}. Click to break the thread.`
: (isLoadingSource
? 'Out port — loaded; click an in port elsewhere to link, or click this again / press Esc to cancel.'
: 'Out port — text ends here. Click to load and then click another frame\'s in port to link.');