Skip to content

feat(ui): BibleReaderNavigation chapter jumps (YPE-5745) - #182

Merged
Dustin-Kelley merged 13 commits into
Searchfrom
ype-5745-reader-navigation
Sep 22, 2026
Merged

Dustin-Kelley merged 13 commits into
Searchfrom
ype-5745-reader-navigation

Conversation

@Dustin-Kelley

@Dustin-Kelley Dustin-Kelley commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Public BibleReaderNavigation with request and focusReference. Host can submit before BibleReader mounts. One pending request; newer replaces older; Reader consumes once.
  • Chapter load only (existing book / chapter / versionId). No Web SDK change. Scroll-to-verse and focus are not in this PR.

Stack

  1. YPE-5746 Search client — merged into Search (feat(core): wrap platform-core SearchClient (YPE-5746) #180)
  2. This PR — YPE-5745 → Search
  3. YPE-5748 native Search UI will target this branch

YPE-5747 (scroll/focus) is out of this stack.

Test plan

  • Request before mount lands on first Reader render
  • Newer request wins; consumed once
  • focusReference changes chapter the same way as request
  • BibleReaderHandle still only refreshHighlights
  • Native toolbar still jumps prev/next after this merge
  • pnpm typecheck / pnpm test / pnpm lint from worktree root

Made with Cursor

RetriggerConfidence Score: 5/5

The PR appears safe to merge.

Summary

The PR adds a public imperative navigation object that lets hosts queue one chapter jump before or after a native Bible Reader mounts.

  • Exports BibleReaderNavigation and its factory from the UI package.
  • Applies pending book, chapter, and version changes during commit while preserving controlled and persisted reader-location behavior.
  • Documents the API and adds coverage for replacement, one-time consumption, pre-mount requests, and focus-reference chapter changes.

Diagram

sequenceDiagram
  participant Host
  participant Navigation as BibleReaderNavigation
  participant Reader as BibleReader
  participant Store as Reader Location Store
  Host->>Navigation: request(reference)
  Navigation->>Navigation: Replace pending request and increment version
  Reader->>Navigation: Read pending request during render
  Reader->>Reader: Render requested book/chapter/version overlay
  Reader->>Navigation: Consume matching version after commit
  Reader->>Store: Persist uncontrolled location fields
  Reader-->>Host: Notify controlled field changes
Loading

Reviews (6) · Last reviewed commit: "docs(ui): note one Reader per navigation..."

@Dustin-Kelley
Dustin-Kelley added this pull request to stack #185 September 10, 2026 19:05
@Dustin-Kelley
Dustin-Kelley force-pushed the ype-5745-reader-navigation branch from 20ff5ba to 1e2cb42 Compare September 10, 2026 19:12
@Dustin-Kelley
Dustin-Kelley force-pushed the ype-5745-reader-navigation branch from 1e2cb42 to 8a6e214 Compare September 15, 2026 14:27
@cursor
cursor Bot force-pushed the ype-5745-reader-navigation branch from 34106a2 to 6d5ad53 Compare September 15, 2026 22:28
Dustin-Kelley and others added 6 commits September 17, 2026 10:56
YPE-5706: temporary Search HTTP in expo-core until platform-core
ships SearchClient. Public hook and types only; wrapper stays internal.

Co-authored-by: Cursor <cursoragent@cursor.com>
YPE-5706: hook must throw when used without YouVersionProvider.
Co-authored-by: Cursor <cursoragent@cursor.com>
Delete the local Search HTTP client and wrap SearchClient from
@youversion/platform-core 2.13.0. Thrown errors map to the existing
RN Result kinds. Verse hits use id. Query lists are { queries }.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>
The USFM tests already pin verse-only three-segment parsing.
The exports tests already pin the public surface.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>
Digit-only USFM chapter and verse segments can parse past
Number.MAX_SAFE_INTEGER. Require a positive safe integer.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>
Public request/focusReference object so a host can jump the Reader
before mount. Scroll-to-verse waits. YPE-5745.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Dustin-Kelley
Dustin-Kelley force-pushed the ype-5745-reader-navigation branch from 6d5ad53 to 77db50d Compare September 17, 2026 15:56
@Dustin-Kelley
Dustin-Kelley removed this pull request from stack #185 September 18, 2026 13:14
@Dustin-Kelley
Dustin-Kelley added this pull request to stack #199 September 18, 2026 13:14
Base automatically changed from ype-5706-search-core-v2 to Search September 18, 2026 21:19
Keep Search's Core USFM parser. Combine the native toolbar with
BibleReaderNavigation so a pending jump paints on the first frame.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Dustin-Kelley
Dustin-Kelley marked this pull request as ready for review September 21, 2026 14:05
Comment thread packages/ui/src/native/bible-reader-navigation.ts Outdated
Comment thread README.md Outdated
Dustin-Kelley and others added 2 commits September 21, 2026 10:00
Consume the pending BibleReaderNavigation request after commit so a
retried render cannot drop the host's chapter jump.

Co-authored-by: Cursor <cursoragent@cursor.com>
Call request when creating BibleReaderNavigation so a parent re-render
does not queue the same jump again.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/ui/src/native/bible-reader.tsx Outdated
Keep the first-paint overlay, but wait to set book/chapter/version so a
discarded render cannot notify the host of a chapter that never showed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Dustin-Kelley
Dustin-Kelley removed this pull request from stack #199 September 21, 2026 17:57
@Dustin-Kelley
Dustin-Kelley added this pull request to stack #203 September 21, 2026 17:57

@cameronapak cameronapak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review

YPE-5745

Summary

Standards: 2 must-fix. Spec: 0 must-fix. Primary concerns: the exported class exposes reader-owned queue controls, and a combined jump persists intermediate Reader Location snapshots.

Review evidence
  • Scope: revision 28af625, YPE-5745, PR history, resolved threads, public declarations, Reader Location behavior, and the Search follow-up boundary.
  • Method: independent Standards, Spec, and Correctness passes, followed by source-level verification of each finding.
Behavior or check Method / command Result Evidence source
Navigation requirements Jira issue and comments, README, CONTEXT.md, implementation and tests Chapter-only scope and YPE-5748 deferral are satisfied Coordinator
Public API surface Generated packages/ui/build/native/bible-reader-navigation.d.ts Reader-owned getters, subscription, and consume methods are public Coordinator
Reader Location commit Traced navigation setters, useControllableState, Zustand persistence, and applyReaderLocation One jump writes separate field patches instead of one combined snapshot Coordinator
Tests pnpm test -- --runInBand 731 passed, 1 skipped Coordinator
Static checks pnpm lint; pnpm typecheck Passed Coordinator
  • Limits: no native-device run; this PR changes coordination rather than visual presentation.
  • CI and bot review: all current GitHub checks passed; prior bot findings are resolved and outdated.
  • Event: REQUEST_CHANGES.

Written by Code Reviewer bot on behalf of Cam.

Comment thread packages/ui/src/native/bible-reader-navigation.ts Outdated
Comment thread packages/ui/src/native/bible-reader-navigation.ts Outdated
Comment thread packages/ui/src/native/bible-reader-navigation.ts Outdated
Comment thread packages/ui/src/native/bible-reader.tsx
cursoragent and others added 3 commits September 21, 2026 18:46
Keep request and focusReference as the host API. Move subscribe,
snapshot, and consume helpers off the exported class so a host cannot
clear a jump before the Reader sees it. Drop unused consumePending.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>
Write book, chapter, and version in a single Reader Location patch so
an uncontrolled jump cannot save a mixed book with the old chapter.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>
Hosts should pass one BibleReaderNavigation to one mounted Reader.
Broadcast across stacked readers is left for a later issue if needed.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

@cameronapak cameronapak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review

YPE-5745

Summary

Standards: 0 must-fix. Spec: 0 must-fix. Primary concern: none. The previous public-API and Reader Location findings are resolved.

Review evidence
  • Scope: revision 548bcb4, full PR behavior, changes since the prior review, resolved threads, YPE-5745, and the YPE-5748 boundary.
  • Method: traced the queue encapsulation, generated declaration surface, external-store consumption, controlled and uncontrolled Reader paths, combined persistence, and single-Reader ownership documentation.
Behavior or check Method / command Result Evidence source
Public navigation API Built package and inspected generated declaration Only request and focusReference are public Coordinator
Combined Reader Location Source trace and focused regression test One complete patch persists after commit Coordinator
Navigation and Reader tests Focused Jest suites 14 passed Coordinator
Full test suite pnpm test -- --runInBand 730 passed, 1 skipped Coordinator
Static checks and build pnpm lint, UI typecheck, UI build Passed Coordinator
  • Limits: no native-device run; the change is coordination rather than visual presentation. Existing asynchronous test-harness warnings remain pre-existing and non-blocking.
  • CI and bot review: all current GitHub checks passed; all prior review threads are resolved.
  • Event: APPROVE.

Written by Code Reviewer bot on behalf of Cam.

) {
return
}
commitReaderLocationPatch({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

praise: Persisting the complete destination before the individual setters keeps Reader Location coherent without losing the first-paint overlay.

For Agents: atomic navigation commit

This resolves the prior mixed-location failure while preserving controlled callbacks and the consume-after-commit safety. The added regression test also checks the observable patch count and final stored values, so a future return to per-field writes will fail clearly.

Written by Code Reviewer bot on behalf of Cam.

@Dustin-Kelley
Dustin-Kelley merged commit 3df12c4 into Search Sep 22, 2026
8 checks passed
@Dustin-Kelley
Dustin-Kelley deleted the ype-5745-reader-navigation branch September 22, 2026 14:05
camrun91 added a commit that referenced this pull request Sep 28, 2026
* feat(ui): hybridize BibleCard chrome with DOM BibleTextView

YPE-5830. Native Card owns header, version control, copyright, and
maxWidth. Scripture still paints through BibleTextViewDom.

* fix: clear BibleCard chrome metadata before refetch

* fix: guard BibleCard version picker until language tag loads

Disable the version control and skip onVersionPickerPress when chrome
metadata has no languageTag, so consumers never receive an empty languageId.

* fix: invalidate BibleCard chrome metadata synchronously on transition

Track which reference/versionId loaded metadata and return null during
render when inputs change, so chrome cannot flash stale values before
the refetch effect runs.

* chore: upgrade example app and packages to Expo SDK 57

Bump the example dev client to expo@57.0.22 with RN 0.86.3, pin
@expo/dom-webview@57.0.1, and move publishable package peers to
>=57.0.0 <58.0.0. Add pnpm overrides for transitive Expo deps still
inside the supply-chain cooldown window.

* chore: bump expo to 57.0.23 for iOS 27 lifecycle backport

Pick up the SDK patch without enabling ios.enableSceneSupport; workspace
override and example app pin expo@57.0.23 exactly.

* fix(example): enable iOS 27 UIScene lifecycle for Xcode 27 builds

Opt in via expo-build-properties enableSceneSupport and bump the plugin
to 57.0.20, which implements the scene delegate wiring required alongside
expo@57.0.23 on SDK 57.

* fix(ui): tighten Reanimated/Worklets peers for RN 0.86

Raise peer floors so consumers on React Native 0.86 cannot resolve
Reanimated 4.3.x or Worklets 0.8.x, which only declare support through
0.85. Add a major changeset recording the Expo 57 peer requirement.

* fix: sync lockfile with Reanimated/Worklets peer floors

5970824 raised packages/ui peer floors to >=4.4.0 / >=0.9.1 but
did not regenerate pnpm-lock.yaml, causing frozen-lockfile CI to fail.

Co-authored-by: Cameron Llewellyn <cameron.b.llewellyn@gmail.com>

* docs: align READMEs with Expo SDK 57 peer contract

Consumer-facing docs still listed SDK 56 while published peers require 57.

* fix(ui): address BibleCard hybrid chrome review feedback

Apply provider version filters to chrome metadata, restore abbreviation and
web background theming, gate the version picker only for consumer handlers,
and keep Expo web from showing a dead built-in picker trigger.

Co-authored-by: Cameron Llewellyn <cameron.b.llewellyn@gmail.com>

* fix(ui): clear BibleCard chrome when version filters change

Include provider filter lists in the chrome metadata key so a tighten
without reference/versionId change drops prohibited chrome immediately,
matching the reference-transition safety net.

Co-authored-by: Cameron Llewellyn <cameron.b.llewellyn@gmail.com>

* fix(ui): keep 600px inner column for BibleCard maxWidth 100%

Match the Web SDK full-bleed contract: the Card surface fills the parent
while header, scripture, and footer stay in a centered 600px column.

Co-authored-by: Cameron Llewellyn <cameron.b.llewellyn@gmail.com>

* fix(ui): clear BibleCard chrome when content client changes

Include fetchBibleContent in the chrome metadata key so an appKey/apiHost
swap drops stale reference/copyright/language before the new lookup resolves.

Co-authored-by: Cameron Llewellyn <cameron.b.llewellyn@gmail.com>

* feat(core): wrap platform-core SearchClient (YPE-5746) (#180)

* feat(core): add placeholder Search client

YPE-5706: temporary Search HTTP in expo-core until platform-core
ships SearchClient. Public hook and types only; wrapper stays internal.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(core): cover useSearch outside provider

YPE-5706: hook must throw when used without YouVersionProvider.
Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(core): wrap platform-core SearchClient (YPE-5746)

Delete the local Search HTTP client and wrap SearchClient from
@youversion/platform-core 2.13.0. Thrown errors map to the existing
RN Result kinds. Verse hits use id. Query lists are { queries }.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* style(core): drop restated Search comments

The USFM tests already pin verse-only three-segment parsing.
The exports tests already pin the public surface.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(core): reject unsafe integers in bibleReferenceFromUsfm

Digit-only USFM chapter and verse segments can parse past
Number.MAX_SAFE_INTEGER. Require a positive safe integer.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(core): reject malformed USFM book identifiers

Require a 3-character uppercase alphanumeric book code so punctuation, whitespace, and overlong ids return null.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* feat(ui): BibleReaderNavigation chapter jumps (YPE-5745) (#182)

* feat(core): add placeholder Search client

YPE-5706: temporary Search HTTP in expo-core until platform-core
ships SearchClient. Public hook and types only; wrapper stays internal.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(core): cover useSearch outside provider

YPE-5706: hook must throw when used without YouVersionProvider.
Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(core): wrap platform-core SearchClient (YPE-5746)

Delete the local Search HTTP client and wrap SearchClient from
@youversion/platform-core 2.13.0. Thrown errors map to the existing
RN Result kinds. Verse hits use id. Query lists are { queries }.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* style(core): drop restated Search comments

The USFM tests already pin verse-only three-segment parsing.
The exports tests already pin the public surface.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(core): reject unsafe integers in bibleReferenceFromUsfm

Digit-only USFM chapter and verse segments can parse past
Number.MAX_SAFE_INTEGER. Require a positive safe integer.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* feat(ui): add BibleReaderNavigation for chapter jumps

Public request/focusReference object so a host can jump the Reader
before mount. Scroll-to-verse waits. YPE-5745.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): keep chapter jumps across discarded renders

Consume the pending BibleReaderNavigation request after commit so a
retried render cannot drop the host's chapter jump.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(ui): request the chapter jump once in the host example

Call request when creating BibleReaderNavigation so a parent re-render
does not queue the same jump again.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): apply reader jumps after the paint commits

Keep the first-paint overlay, but wait to set book/chapter/version so a
discarded render cannot notify the host of a chapter that never showed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): hide reader navigation queue controls

Keep request and focusReference as the host API. Move subscribe,
snapshot, and consume helpers off the exported class so a host cannot
clear a jump before the Reader sees it. Drop unused consumePending.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): persist reader jumps as one location

Write book, chapter, and version in a single Reader Location patch so
an uncontrolled jump cannot save a mixed book with the old chapter.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* docs(ui): note one Reader per navigation object

Hosts should pass one BibleReaderNavigation to one mounted Reader.
Broadcast across stacked readers is left for a later issue if needed.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* feat(ui): match native Reader chrome to Swift

Drop the avatar row. Half-pills, overlay chapter buttons, and a More menu keep the same host presses. Search stays off this PR.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): lift Reader overlay nav above the iOS tab bar

Prev and next sat 24pt from the reader bottom, on SampleApp tabs, so those presses hit Bible or Profile instead of changing chapter.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): retarget Reader chrome to Swift PR 268

Previous and next live in the chapter capsule. Overlay circles are gone so the toolbar matches the current Swift header.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): polish v2 Reader toolbar chrome

Match Figma capsules, a softer halo, side padding, and More-menu icons so the native row reads like the v2 file.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): finish v2 toolbar leftovers from self-review

Cap the version pill so Select version cannot squeeze the chapter row.
Drop unused GearIcon and avatar copy. Open More while auth is restoring.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ui): delete unused Avatar primitive

The v2 toolbar no longer mounts it. Drop the component, its tests, and the internal barrel export.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): even the Reader toolbar gaps around More

Size More to the icon so the 8px gap matches the space between the chapter and version chips.

Co-authored-by: Cursor <cursoragent@cursor.com>

* revert(ui): keep userAvatarAlt in synced locale catalogs

Locale JSON is generated from platform-localization. Dropping the unused key here fails Greptile. Leave the string until that repo deletes it.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): match More menu icons to Swift glyphs

Use San Francisco textformat.size for Fonts & Settings and person for sign in/out.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): restack Reader Search onto Swift chrome

Search belongs in the 5953 spacer. The old row put it between version and gear, and that chrome is gone.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): keep 5745 navigation consume API on Search rebase

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): keep combined Reader Location jumps after Search rebase

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ui): delete unused components/ui PersonIcon

The More menu still uses native/icons/person-icon.tsx.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): stop the Reader example from jumping every render

The sample called navigation.request after every ReaderScreen render, so a copied example reset the reader to John 3 on unrelated updates. The request now happens once, inside the same useMemo that creates the navigation object.

Drop the hand-written Spanish search strings. Missing keys fall back to English until Crowdin returns them.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* YPE-5833 / RNV2-6: compose YouVersionAuthButton on design-system Button (#194)

* feat(ui)!: compose YouVersionAuthButton on design-system Button

YPE-5833 / RNV2-6. The branded control is now Button + Button.Text with
the Bible App logo as a child. background still forces the light or dark
token scheme.

BREAKING CHANGE: YouVersionAuthButton no longer accepts outline, radius,
or size. Short, icon, and rectangular variants are gone. The canonical
look is a filled, rounded Button with the full localized label.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): keep Trans props off Button.Text in YouVersionAuthButton

Wrap the i18n Trans node inside Button.Text instead of using it as
Trans parent, so extra Trans props are not forwarded onto the label.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): address YouVersionAuthButton review findings

Drop the unlinked example preview route. Collapse sign-in versus
sign-out to one decision. Document that core majors only because the
packages version together. Cover theme isolation and the bold Trans face.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): pin YouVersionAuthButton fill to scheme background

Button default primary is red in dark and hides the Bible App logo.
Read tokens via useTokens inside the forced ThemeContext. Cover sign-in
error logging and keep outline/radius/size off the public props type.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* docs: match native i18n Trans example to auth button

The contributing snippet still taught parent={Text} and a hand-written
fontWeight. The auth button nests Trans in Button.Text and bolds with
sansFace.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* refactor(ui): read i18n inside YouVersionAuthButton surface

AuthButtonSurface already sits under the forced scheme. It can call
useSdkTranslation itself instead of taking i18n as a pass-through prop.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): treat empty auth button text as omitted

An empty text prop used to fall back to the localized Trans label. Nullish
coalescing made it a blank control. Scope the i18n sansFace note to
primitives so sheets can keep fontWeight.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): outline YouVersionAuthButton and let the label wrap

Bake a scheme border into the locked look (light 1px, dark 2px) without
bringing back the outline prop. Override Button.Text to two lines and
drop the fixed height so a long locale can wrap.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* refactor(ui): extract AuthButtonLabel from YouVersionAuthButton

Keep Trans named Trans. Early-return when the caller passes text.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* chore(changeset): ship YouVersionAuthButton DS work as patch

Drop core from the changeset; it has no API change. The fixed group still versions both packages together.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* refactor(ui): bold AuthButtonLabel with design-system Text

Trans bold uses DS Text plus sansFace. Pin typography.sm so the brand
name stays on the Button.Text size.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): let YouVersionAuthButton label wrap on web

Give Button.Text flex: 1 so a narrow parent wraps to two lines instead of
ellipsizing on one.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* docs: add PR 194 Expo web QA screenshots for local download

Temporary PNGs so Dustin can pull them via the GitHub API onto his Desktop.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* docs: remove temporary PR 194 screenshot drop folder

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): restore YouVersionAuthButton post-DS-9 shape on Button

Keep the old padding, logo gap, and no default border while composing
the design-system Button. Label color comes from Button context.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): match YouVersionAuthButton chrome to Swift

Compose Button outline, hug content, and use Swift padding, gap, and logo size so hosts place the pill.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* chore: sync react native localization (#200)

Co-authored-by: camrun91 <16566029+camrun91@users.noreply.github.com>

* refactor(ui): inline the Reader Search field

The design-system Input had one caller, and that caller turned its border off. The sheet now uses TextInput directly.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* feat(ui): v2 toolbar (YPE-5953) (#202)

* feat(ui): match native Reader chrome to Swift

Drop the avatar row. Half-pills, overlay chapter buttons, and a More menu keep the same host presses. Search stays off this PR.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): lift Reader overlay nav above the iOS tab bar

Prev and next sat 24pt from the reader bottom, on SampleApp tabs, so those presses hit Bible or Profile instead of changing chapter.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): retarget Reader chrome to Swift PR 268

Previous and next live in the chapter capsule. Overlay circles are gone so the toolbar matches the current Swift header.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): polish v2 Reader toolbar chrome

Match Figma capsules, a softer halo, side padding, and More-menu icons so the native row reads like the v2 file.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): finish v2 toolbar leftovers from self-review

Cap the version pill so Select version cannot squeeze the chapter row.
Drop unused GearIcon and avatar copy. Open More while auth is restoring.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ui): delete unused Avatar primitive

The v2 toolbar no longer mounts it. Drop the component, its tests, and the internal barrel export.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): even the Reader toolbar gaps around More

Size More to the icon so the 8px gap matches the space between the chapter and version chips.

Co-authored-by: Cursor <cursoragent@cursor.com>

* revert(ui): keep userAvatarAlt in synced locale catalogs

Locale JSON is generated from platform-localization. Dropping the unused key here fails Greptile. Leave the string until that repo deletes it.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): match More menu icons to Swift glyphs

Use San Francisco textformat.size for Fonts & Settings and person for sign in/out.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ui): delete unused components/ui PersonIcon

The More menu still uses native/icons/person-icon.tsx.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): address review feedback on host toolbar presses

The release note said hosts keep the same presses. Settings and sign-in now open from More, and the retired avatar test ids are named.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): address review feedback on capsule clipping

Light mode keeps the shadow on the outer pill. Labels and press fills clip on an inner view.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): address review feedback on the More hit target

The More pressable is 44 points. The icon stays 24, and the test checks that frame.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* feat(ui): polish Reader Search open state

Focus the field when the sheet opens, match the search pill to the other toolbar capsules, and show three trending and recent queries.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ui): simplify styles in BibleReaderSearchSheet

* fix(ui): use synced Reader Search strings

The locale check blocks a hand-edited catalog. Call the synced keys, and read the focus spy from its context so typecheck accepts it.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): YPE-5836: Add native Bible chapter picker (#204)

* feat(ui): add native Bible chapter picker

Amp-Thread-ID: https://ampcode.com/threads/T-01a0c4d9-366a-702e-a0d8-e56d50e888bc
Co-authored-by: Cameron Pak <cameronandrewpak@gmail.com>

* fix(ui): refine native chapter picker

Amp-Thread-ID: https://ampcode.com/threads/T-01a0c4d9-366a-702e-a0d8-e56d50e888bc
Co-authored-by: Cameron Pak <cameronandrewpak@gmail.com>

* fix(ui): polish chapter picker interactions

Amp-Thread-ID: https://ampcode.com/threads/T-01a0c4d9-366a-702e-a0d8-e56d50e888bc
Co-authored-by: Cameron Pak <cameronandrewpak@gmail.com>

* fix(ui): preserve chapter picker sheet theme

Amp-Thread-ID: https://ampcode.com/threads/T-01a0c5d4-3d6c-712f-b216-cb65fb75357f
Co-authored-by: Cameron Pak <cameronandrewpak@gmail.com>

* fix(ui): address chapter picker review feedback

Keep the selected-book fade on one color, avoid reloading the catalog when provider filters are recreated with the same contents, and scroll the selected chapter back into view after an order change.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): ignore chapter picks for a revoked Bible version

Drop the loaded catalog as soon as provider filters change, and refuse a selection when the current filters no longer allow that version.

Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>

* fix(ui): drop the Reader Search capsule

Search is a plain 24pt icon with 8pt of padding. The toolbar row uses 16pt on the leading edge and no trailing pad.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): inset the Reader More control from the trailing edge

The row had no trailing pad, so More sat on the screen edge. Add 8pt on that side.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): keep a trailing space after a submitted search

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): retry a search page when its hits cannot be titled

A later page with hits and no titles stays retryable instead of marking those verses seen.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): label search retry buttons Retry

The failed search and the page-error control were saying Error.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(ui): press a bad search result on the real sheet

The reader mock never called the sheet, so a bad id could still navigate and the test would pass.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(ui): say Cancel in the Reader Search changeset

The header already uses the Cancel string. The release note was still saying Done.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(ui): delete the unused font settings icon

The More menu still uses AaIcon, and nothing imported this file.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): narrow the search view before retrying in the test

Typecheck rejected footer on the full search view after the await.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): focus a verse across the Expo DOM bridge

A Search tap should scroll to the verse. The WebView can only take a plain object, so the DOM wrapper builds BibleReaderNavigation and calls focusReference when seq changes.

* fix(ui): drop the example John 3:16 focus control

The example Reader is not a focus demo. Search still focuses through the Reader's own navigation.

* fix(ui): keep a repeated or rejected verse focus from moving the reader

A WebView reload was jumping back to the last focused verse, and a passage the Web SDK rejects was clearing the page.

* fix(ui): type the verse focus mocks with jest's two type arguments

tsc rejects a single type argument on jest.fn, which failed the PR typecheck.

* fix(ui): apply a verse focus queued before the Reader mounts

The WebView treated the first focus number as already handled, so a focus waiting at startup never scrolled. A later reload still skips that same number.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): show the suggestion spinner only after the request starts

The debounce wait stays blank. The spinner keeps the list height so the sheet does not collapse.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): skip a repeat search for the same query and version

Pressing Search again after results land was clearing the list and fetching it again. A failed search still retries.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): announce a failed search next to Retry

A failed search and a failed next page only showed Retry. Screen readers now hear Error when that state appears.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): load the next search page at the last five rows

The list waited until the last fifth of the viewport. It now requests the next page once a row in the last five is on screen.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): finish remaining Search review notes

Give the field a search role, grow Search and Clear to 44pt hits, and document that Search taps and focusReference scroll and dim.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): address Search review follow-ups

Prevent verse focus from replaying after a WebView reload, skip a
whitespace-only repeat search, and give Retry a 44pt hit target.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): match Search clear to the picker field

Use the same 18pt ClearIcon, trailing placement, and 10pt hit slop as the native picker search field.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): apply verse focus only after the WebView reports it

A focus requested while the WebView is loading was marked applied on the native side and then skipped when the WebView became ready.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): show completed search results again after a whitespace edit

Pressing Search on the same query restores the page already loaded and keeps the typed space.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): give Search Clear a 44pt touch target

The 18pt icon stays. The button itself is 44pt so the extra area does not cover the text field.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): drop a void call the linter rejects

The focus report already returns nothing, so the void operator is not allowed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): let Search delete whitespace after restoring results

setQuery ignored any edit equal to the submitted query. A restored page
keeps the typed text ("hope "), so backspacing to "hope" was dropped and
the field snapped back. Compare against the displayed field text instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): keep the last of two quick Search edits

Compare each edit against the reducer's current state instead of the
last render, so a type-then-delete before a re-render is not dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): keep paging Search past a page of repeated verses

A next page whose hits were all already shown added no rows, so the list
never scrolled to ask again and results stopped early. Follow the new
cursor instead; stop if the API hands back the same one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): stop Search paging when cursors cycle

Following the cursor past repeat-only pages looped forever if the API
cycled cursors (A -> B -> A). Remember every fetched cursor for the result
set and stop when a repeat-only page points back at one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): dedupe the first page of Search results

Later pages already dropped repeated hits, but page one used the raw list,
so a repeated id rendered two rows with one key and fetched the passage twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): keep Search focus and theme with the Reader

The navigation object stores the applied focus sequence, so remounting the Reader does not send an acknowledged verse to the Web SDK again. Search content uses the Reader theme, so result text matches the sheet when the provider scheme differs.

* fix(ui): scope verse focus to the navigation object

A replacement navigation object restarts its focus sequence at 1. The WebView now tracks which object that sequence belongs to, so the new object's first focus still runs once.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(ui): show a late verse-focus ack marks the replacement reader

The callback still accepts only the sequence. After a navigation swap, that sequence is stored on the reader now on screen.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): ignore a verse-focus ack from another navigation stream

Expo delivers the action to the reader on screen. The acknowledgment names its stream, so a late reply from the previous navigation object does not mark the replacement.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Dustin Kelley <141975656+Dustin-Kelley@users.noreply.github.com>
Co-authored-by: Dustin Kelley <Dustin-Kelley@users.noreply.github.com>
Co-authored-by: Dustin Kelley <Kelleydustin2018@gmail.com>
Co-authored-by: platform-localization-pr-bot[bot] <294853593+platform-localization-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: camrun91 <16566029+camrun91@users.noreply.github.com>
Co-authored-by: Cameron Pak <cameronandrewpak@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

3 participants