Skip to content

Treat verse 0 as an ordinary verse; remove liveScrRef stickiness guard#134

Merged
alex-rawlings-yyc merged 5 commits into
mainfrom
remove-verse-0-guards
Jul 6, 2026
Merged

Treat verse 0 as an ordinary verse; remove liveScrRef stickiness guard#134
alex-rawlings-yyc merged 5 commits into
mainfrom
remove-verse-0-guards

Conversation

@alex-rawlings-yyc

@alex-rawlings-yyc alex-rawlings-yyc commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

A chapter's pre-verse-1 superscription is a real, focusable verse-0 segment,
but liveScrRef held a stickiness guard that swallowed any same-chapter verseNum: 0 reference naming the verse already shown. That guard was added
(b9dec18, "fix verse-0 echo nav") before verse 0 was a parsed verse, to absorb
the host's spurious post-verse-nav chapter echo. It could not distinguish that
echo from a genuine external < (previous-verse) from verse 1 — both are
same-chapter, verse 0, and markerless on the global selector path — so it also
ate the intentional <, leaving the extension stuck on verse 1 instead of
moving to the superscription.

Verified in a live session (probe logging liveScrRef/rawScrRef) that the host
no longer emits the spurious echo: exactly one delivery per navigation, never
an unsolicited trailing verse 0. With the echo gone the guard defended against
nothing, so remove it. Verse 0 now passes through verbatim; the host's < from
verse 1 lands on the chapter's superscription (the loader resolves verse 0 to
the superscription segment, else to verse 1).

The internal-nav marker machinery is retained — it still classifies internal/external navigations for the recenter fade. Only its former role
inside the verse-0 guard is gone.

Tests: collapse the two sticky-behavior tests into one pass-through regression
test; flip the mid-reveal fade test to expect the curtain to re-engage for a
verse-0 navigation arriving during fade-in (verse 0 is now an ordinary mid-reveal move).


This change is Reviewable

Summary by CodeRabbit

  • Bug Fixes
    • Improved verse navigation so out-of-range or in-segment references now land on the nearest valid verse/segment instead of jumping unexpectedly.
    • Fixed handling for chapter superscription references and verse-0 navigation during live updates and fade transitions.
    • Kept chapter navigation more stable when selecting the same chapter again or moving through merged verse segments.

@alex-rawlings-yyc alex-rawlings-yyc self-assigned this Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@alex-rawlings-yyc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 57e871e1-e7ee-4cec-bf91-8ba04602dd85

📥 Commits

Reviewing files that changed from the base of the PR and between b98d91c and d3a8d2f.

📒 Files selected for processing (4)
  • src/__tests__/components/InterlinearNavContext.test.tsx
  • src/__tests__/components/InterlinearizerLoader.test.tsx
  • src/components/InterlinearNavContext.tsx
  • src/components/InterlinearizerLoader.tsx
📝 Walkthrough

Walkthrough

Removes verse-0 "stickiness" from InterlinearNavContext so liveScrRef always passes through rawScrRef, expands InterlinearizerLoader's activeScrRef to resolve any non-matching reference to the nearest preceding segment start (not just verse-0), updates related documentation, and adjusts/adds corresponding tests.

Changes

Verse-0 navigation semantics

Layer / File(s) Summary
liveScrRef stickiness removal
src/components/InterlinearNavContext.tsx
Removes the memoized verse-0 stickiness computation; liveScrRef is now a direct alias of rawScrRef. Documentation for liveScrRef, liveScrRefRef, and the navigate invariant is rewritten to describe passthrough behavior and marker-freshness pairing.
Interlinearizer documentation rewrite
src/components/Interlinearizer.tsx
scrRef prop, focusToken, and handleSegmentSelect comments are reworded to explain internal-origin navigation markers skipping the recenter fade, replacing the prior "stickiness exception" framing.
Loader nearest-segment resolution
src/components/InterlinearizerLoader.tsx
Adds ScriptureRef type import and toSerializedVerseRef import; activeScrRef now resolves any non-matching reference to the nearest preceding segment start in the same book/chapter, with verse-0 still mapping to verse 1 when absent.
Loader resolution tests
src/__tests__/components/InterlinearizerLoader.test.tsx
Adds tests for out-of-range verse resolving to the chapter's last segment and for verses inside merged segments resolving to the segment's start verse.
NavContext/Interlinearizer test updates
src/__tests__/components/InterlinearNavContext.test.tsx, src/__tests__/components/Interlinearizer.test.tsx
Renames/adjusts same-chapter verse-0 test expecting liveScrRef to stay on verse 1; replaces "verse-0 echo" fade test with "verse-0 navigation" test expecting fadePhase 'out'; updates an inline comment.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

  • sillsdev/interlinearizer-extension#123: Changes the same verse-0 handling code paths in InterlinearNavContext.tsx and InterlinearizerLoader.tsx regarding liveScrRef/activeScrRef stickiness and echo treatment.

Suggested reviewers: imnasnainaec

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main change: verse 0 is now treated normally and the liveScrRef stickiness guard is removed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch remove-verse-0-guards

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@alex-rawlings-yyc alex-rawlings-yyc linked an issue Jun 29, 2026 that may be closed by this pull request
@alex-rawlings-yyc

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

@alex-rawlings-yyc alex-rawlings-yyc marked this pull request as ready for review June 29, 2026 21:41
@imnasnainaec

Copy link
Copy Markdown
Contributor

Devin has a bug and some flags on this pr: https://app.devin.ai/review/sillsdev/interlinearizer-extension/pull/134

alex-rawlings-yyc and others added 2 commits July 2, 2026 11:19
A chapter's pre-verse-1 superscription is a real, focusable verse-0
segment,
but `liveScrRef` held a stickiness guard that swallowed any same-chapter
`verseNum: 0` reference naming the verse already shown. That guard was
added
(b9dec18, "fix verse-0 echo nav") before verse 0 was a parsed verse, to
absorb
the host's spurious post-verse-nav chapter echo. It could not
distinguish that
echo from a genuine external `<` (previous-verse) from verse 1 — both
are
same-chapter, verse 0, and markerless on the global selector path — so
it also
ate the intentional `<`, leaving the extension stuck on verse 1 instead
of
moving to the superscription.

Verified in a live session (probe logging liveScrRef/rawScrRef) that the
host
no longer emits the spurious echo: exactly one delivery per navigation,
never
an unsolicited trailing verse 0. With the echo gone the guard defended
against
nothing, so remove it. Verse 0 now passes through verbatim; the host's
`<` from
verse 1 lands on the chapter's superscription (the loader resolves verse
0 to
the superscription segment, else to verse 1).

The internal-nav marker machinery is retained — it still classifies
internal/external navigations for the recenter fade. Only its former
role
inside the verse-0 guard is gone.

Tests: collapse the two sticky-behavior tests into one pass-through
regression
test; flip the mid-reveal fade test to expect the curtain to re-engage
for a
verse-0 navigation arriving during fade-in (verse 0 is now an ordinary
mid-reveal move).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@imnasnainaec

This comment was marked as resolved.

@imnasnainaec

Copy link
Copy Markdown
Contributor

The behavior is fine for me in the Psalms, so I think this is valid to act on:

src/components/InterlinearNavContext.tsx:248
liveScrRef and rawScrRef are now functionally equivalent after stickiness removal
With the verse-0 stickiness removed, both rawScrRef (line 217-220) and liveScrRef (line 248-251) perform the same deduplication logic: compare the incoming reference against their respective previous values using areScrRefsEqual, and reuse the old object on match. Since liveScrRef now always equals rawScrRef in value, the two refs will always converge to the same identity chain. The separation is still conceptually meaningful (raw host value vs. active reference) and retains its own identity-stable track for the context value's useMemo, so this is not a correctness issue — but it is now redundant logic that could be simplified if the design solidifies.

@imnasnainaec

Copy link
Copy Markdown
Contributor

I want to test this behavior out in the Psalms before approving:

src/components/InterlinearNavContext.tsx:248 Removing verse-0 stickiness relies on the host no longer sending spurious verse-0 echoes The old code explicitly guarded against the host re-broadcasting the chapter as a verseNum: 0 reference after every verse navigation (the comment at the removed lines said "After a verse navigation the host re-broadcasts the chapter as a separate verseNum: 0 reference"). With the stickiness removed (src/components/InterlinearNavContext.tsx:248-251), any verse-0 reference the host sends will pass through to liveScrRef and then to the loader's activeScrRef (src/components/InterlinearizerLoader.tsx:245-249). If the chapter has a verse-0 superscription segment, this would jump the view to the superscription after every same-chapter verse navigation. The loader's fallback (resolving verse 0 to verse 1 when no segment exists) only helps chapters without superscriptions. If the host's echo behavior described in the old comment still exists, this could cause unexpected view jumps in chapters with superscriptions (e.g., many Psalms).

And perhaps see if a new test or two could target this regression concern.

@alex-rawlings-yyc

Copy link
Copy Markdown
Contributor Author

I believe the most recent commit suffices to simplify the logic. I had done a bit of testing on my own and found that the host was no longer sending echoes. I didn't tell you because I got distracted working on the other PR and I also wanted to see if you could find any issues with the host that I didn't see

Comment thread src/components/InterlinearNavContext.tsx Outdated
The host's next-verse button emits verseNum + 1 without clamping, so
bumping forward from a chapter's last verse delivered a verse past the
chapter's end; the loader only resolved verse-0 refs, and the segment
window's anchor fallback jumped to the start of the book. Any unmatched
verse now resolves to the nearest preceding segment start in its
chapter, so the view holds at the chapter's end (and a verse inside a
merged multi-verse segment resolves to its owning segment).
With verse-0 stickiness gone the two refs held the same object at every
read, so one ref now serves both the duplicate-delivery identity guard
and the mid-reveal prev comparison. The loader's activeScrRef owns the
only raw→active mapping, which needs the loaded book anyway.

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alex-rawlings-yyc made 1 comment.
Reviewable status: 0 of 6 files reviewed, 1 unresolved discussion (waiting on alex-rawlings-yyc and imnasnainaec).

Comment thread src/components/InterlinearNavContext.tsx Outdated

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec reviewed 6 files and all commit messages, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).

@alex-rawlings-yyc alex-rawlings-yyc merged commit 9fe2e58 into main Jul 6, 2026
11 checks passed
@alex-rawlings-yyc alex-rawlings-yyc deleted the remove-verse-0-guards branch July 6, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow global ref into verse 0 (superscription)

2 participants