mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-10-27 08:40:39 +00:00
fix(book): chain walk dropped frames past 2 — separate seen sets per direction
_bookCollectThreadChain shared a single 'seen' set between the
backward and forward walks. For a chain A → B → C started from C,
the backward walk visited B then A, leaving seen = {B.id, A.id}.
The forward walk from head A then tried to push B, but found B in
seen and broke immediately — returning chain [A] instead of
[A, B, C].
Symptom: cross-page flow worked for any 2-frame chain (forward
walk only had one node to visit), but broke as soon as the chain
hit 3 frames. The user repro 'A on page 1 → B on page 1 → C on
page 2 doesn't flow' matched exactly.
Fix: use separate seen sets per walk direction. Each starts with
the relevant endpoint (layer for backward, head for forward) and
detects same-direction cycles without bleeding into the other.
Affects every consumer of _bookCollectThreadChain: editor canvas
text rendering (_attachBookFramePorts), tile thumbnails
(renderBookDesignedPageToCanvas via the J4.c.2 hook), PDF export
(same path), and the text-frame inspector's chain / line-count
diagnostic.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
cbfed8702b
commit
ce1e1a783b
1 file changed
+14
-8
+14
-8
@@ -23932,25 +23932,31 @@
|
||||
function _bookCollectThreadChain(layer) {
|
||||
// Walk backwards to the head, then forward to the tail.
|
||||
// Returns layers in flow order (head → ... → tail).
|
||||
const seen = new Set();
|
||||
// Backwards: find the layer whose nextFrame.frameId equals
|
||||
// current.frameId; loop until none exists.
|
||||
//
|
||||
// Bug fix: each walk needs its OWN seen-set. Sharing seen
|
||||
// between backward and forward walks meant the forward walk
|
||||
// tripped its cycle guard on the middle frames the backward
|
||||
// walk had already visited. A → B → C starting from C would
|
||||
// walk back through B + A (seen={B,A}), then the forward walk
|
||||
// from A would find B in `seen` and break — returning chain
|
||||
// [A] instead of [A, B, C].
|
||||
let head = layer;
|
||||
const seenBack = new Set([layer.id]);
|
||||
let guard = 0;
|
||||
while (guard++ < 1000) {
|
||||
const prev = _findBookFrameLayer(o => o !== head && o.nextFrame?.frameId === head.frameId);
|
||||
if (!prev || seen.has(prev.id)) break;
|
||||
seen.add(prev.id);
|
||||
if (!prev || seenBack.has(prev.id)) break;
|
||||
seenBack.add(prev.id);
|
||||
head = prev;
|
||||
}
|
||||
const chain = [head];
|
||||
seen.add(head.id);
|
||||
const seenFwd = new Set([head.id]);
|
||||
let cursor = head;
|
||||
guard = 0;
|
||||
while (cursor.nextFrame?.frameId && guard++ < 1000) {
|
||||
const nxt = _findBookFrameLayer(o => o.frameId === cursor.nextFrame.frameId);
|
||||
if (!nxt || seen.has(nxt.id)) break;
|
||||
seen.add(nxt.id);
|
||||
if (!nxt || seenFwd.has(nxt.id)) break;
|
||||
seenFwd.add(nxt.id);
|
||||
chain.push(nxt);
|
||||
cursor = nxt;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user