Address review findings: navigation edge cases, dropdown stacking, verse-0 dead code#103
Conversation
An external focusedTokenRef change arriving while an internal nav was still awaiting its echo left the in-flight marker set, so the render-phase guard never resynced pendingPhraseIndexRef and the next step() advanced from the stale index. Clear the marker when the prop changes to something other than the in-flight ref. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When React batches rapid internal navigations, the host echoes only the final reference, stranding the earlier verse marker in the pending set forever; a later external navigation to that verse would then be misclassified as internal and skip its recenter fade. Store markers with a timestamp and evict entries older than 3s on consume. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
normalizeScrRef maps verse 0 to verse 1 before the reference reaches the display layer, so the chapter-heading active/snap branches in SegmentListView and snapActiveToTop could never run in production. Remove them and the tests that injected verse 0 directly as a prop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The verse-0 display handling was removed as unreachable, so the "scrRef is always normalized" assumption is now load-bearing; state it on the prop. Also spell out why focusedTokenRef/tokenSegmentMap and phraseMode must stay out of their effects' dependency arrays, so the eslint-disables are not removed without understanding the consequence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The invisible click-catcher backdrop sat at z-20 while the toolbar (sticky, z-10) caps all its descendants at level 10, so in a real browser the gear button could never receive a click while the dropdown was open -- the tested toggle-closed path only worked because jsdom ignores z-index for hit-testing. Lower the backdrop to z-5 so the gear toggle is the real mechanism; the panel itself stays at z-30. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The TTL added to consumeInternalNav was bypassed by the render-phase mid-reveal guard, which still checked the marker map with a bare has(): an expired stranded marker (batched rapid-click whose echo never arrived) would wrongly exempt a later external navigation from re-engaging the cross-book curtain during the fade-in. Extract the freshness check into a shared helper used by both readers; the guard reads purely (no eviction during render) while consumeInternalNav keeps evicting to bound the map. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@alex-rawlings-yyc This pr is Claude Fable addressing Devin's remaining comments on #98 , but I haven't actually had a chance to review any of these changes myself. So as I break for lunch, you can decide whether you want to look at this yet. |
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
I think these are worthy changes to make. Continue
@alex-rawlings-yyc reviewed 10 files and all commit messages, and made 1 comment.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on imnasnainaec).
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
@alex-rawlings-yyc reviewed 2 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on imnasnainaec).
* Change segment view to allow for infinite scroll within a book * Fix external scrRef change-related issues (UNFINISHED) * Adjust animation/fade timing * Refactor scrRef navigation with new hook * Post-refactor adjustments * Hoist SegmentListView into own component, fix lingering external nav fade/realignment timing issues, add chapter markers and associated setting * Cleanup * Fix snapping issues * Extract useLatestRef/useRecenterSnap hooks, fix verse-0 echo nav * Add shared hooks to reduce odds of drift * Minor improvements * Minor adjustments * Stabilize duplicate results from PAPI scripture picker * Update doc * Fix alignment issues when toggling Continuous Scroll Mode * Prevent scroll from going past final segment * Clear timeout for stale fade-in * Add same verse ref guard to handleSegmentSelect * Improve test coverage * Minor adjustments * Refactor useSegmentWindow hook * Fix flicker after external nav double-sends new ref * Address review findings: navigation edge cases, dropdown stacking, verse-0 dead code (#103) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Cleanup --------- Co-authored-by: D. Ror. <imnasnainaec@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Devin: https://app.devin.ai/review/sillsdev/interlinearizer-extension/pull/103
Follow-ups to the segment-view rework, addressing code-review findings. Two navigation edge-case bugs, one real-browser click-handling fix, removal of an unreachable code path, and documentation hardening around fragile patterns the review called out.
Navigation fixes
Continuous strip: external navigation interrupting an in-flight internal step. The strip tracks its pending phrase index in a ref so two rapid arrow clicks advance two groups before React re-renders. But when the parent imposed a new external
focusedTokenRefwhile an internal step was still awaiting its echo, the in-flight marker suppressed the render-phase resync and the next step advanced from the stale index. The trigger is narrow but real: the focus-change effect early-returns when the new prop equals the currently displayed ref, so an external navigation landing on the displayed verse left the marker stuck indefinitely. The render-phase sync now detects an external override (the prop changed to something other than the in-flight internal ref), clears the marker, and resyncs the pending index. Covered by a regression test alongside the existing rapid-double-click test.Internal-navigation markers now expire. When React batches rapid internal clicks into one update, the host echoes only the final reference, stranding the earlier verse's marker forever; a later external navigation to that verse would then be misclassified as internal and skip its recenter fade. Markers are now stamped (
Map<verseKey, timestamp>) and expire afterINTERNAL_NAV_TTL_MS(3 s — legitimate echoes round-trip in milliseconds, so nothing real can expire early). Both readers honor the TTL through a single shared freshness helper so they cannot drift:consumeInternalNav(which also evicts expired entries to bound the map) and the render-phase mid-reveal curtain guard (a pure read — no map mutation during render). Tests cover both the stranded-marker expiry and the mid-reveal re-engage with an expired marker naming the target verse.View-options dropdown: gear toggle works in real browsers
The portaled click-catcher backdrop sat at
z-20, while the toolbar (sticky+z-10) caps all its descendants at level 10 — so in a real browser the gear button could never receive a click while the dropdown was open, and the tested toggle-closed path only passed because jsdom ignores z-index for hit-testing. Raising the button cannot work (the toolbar's stacking context caps it), so the backdrop drops toz-5instead: panel above toolbar above backdrop above page content. The backdrop is invisible, so this changes hit-testing only. One deliberate behavior change: while the dropdown is open, clicks on other toolbar controls now reach those controls directly instead of merely dismissing the dropdown.Unreachable verse-0 handling removed
normalizeScrRefmaps a verse-0 (chapter heading) selection to verse 1 before the reference ever reaches the display layer, so the chapter-heading active/snap branches inSegmentListViewanduseSegmentWindow.snapActiveToTopcould never run in production — their tests only passed by injectingverseNum: 0directly as a prop, bypassing the nav context. Those branches, the now-unconsumeddata-chapter-startattribute, and their prop-injection tests are removed. Since the "scrRef is always normalized" assumption is now load-bearing, it is stated explicitly onInterlinearizer'sscrRefprop.Documentation hardening
The review flagged two effect dependency arrays as easy to break without understanding the design. Their comments now spell out the consequence: adding
focusedTokenRef/tokenSegmentMapto the external-reseed effect would clobber the deliberately focused token on every focus move (they are guard-reads, not triggers), and the revert effect's correctness depends onisRevertstaying derived directly fromphraseMode.Testing
Full Jest suite green (893 tests, 34 suites), ESLint/stylelint/typecheck clean.
This change is