Skip to content

Native iOS app: fixes from the first phone test - #129

Merged
Programcode merged 8 commits into
feat/native-iosfrom
native-ios/03d-m1-fixes
Oct 9, 2026
Merged

Programcode merged 8 commits into
feat/native-iosfrom
native-ios/03d-m1-fixes

Conversation

@Programcode

Copy link
Copy Markdown
Owner

These are the fixes from Adam's first test of milestone 1 on his iPhone in Expo Go.

  • Blank form sheets. The New debate sheet opened blank with the keyboard up. In that sheet the ScrollView sat inside a KeyboardAvoidingView, so react-native-screens 4.26 fell back to setting the scroll view's frame to the sheet's frame (RNSScreen.mm:203). That frame includes the sheet's slide-in offset, which probably moved the content off the visible sheet. This is inferred from the source, not observed on a device. All six sheets now use a SheetScrollView root, which is how the switcher sheet is built, and that one rendered fine. automaticallyAdjustKeyboardInsets keeps the fields clear of the keyboard.
  • One-off mode was greyed out whenever there was no Current Debate. It now works at any time, as on the website. The website's one-off copy shows on the Debate tab and in Ask, and Library shows debate.oneOffActive.
  • Plurals. Hermes in Expo Go has no Intl.PluralRules. i18next logged a red LogBox error, and keys that only have _one/_other forms rendered as raw keys. @formatjs/intl-pluralrules with en, es and hu data now loads before i18n, and only when the API is missing.
  • Header warning. The RNScreens warning about using blurEffect and scrollEdgeEffects together is gone: iOS 26 uses its scroll edge effect, and older versions keep the blur.
  • Smoothness.
    • A debate refresh that changes nothing keeps the same array, so mounted tabs don't re-render.
    • While an answer streams in, Ask jumps to the end instead of restarting an animated scroll every 30 ms.
  • 120 Hz. app.json now sets CADisableMinimumFrameDurationOnPhone. It takes effect from the first dev build; Expo Go keeps its own frame rate.
  • Runbook. Expo Go now uses the tailnet IP, because the Metro CLI crashed when it tried to resolve the VPS's own MagicDNS name. The Expo login notes are in docs/development.md.

"No current debate" on Adam's account is not a bug. His staging account has no current_debates row, and the website shows the same empty state for it.

Checks, run locally on Node 22 at 5961a02, because GitHub Actions starts no jobs on this account (billing):

  • lint, typecheck, docs:check, build and the web export pass, and npm test passes all 287 tests.
  • The iOS bundle builds through Metro (2985 modules).
  • 176 screenshots of the web export signed in to staging pass, including the one-off on and off states and the new-debate sheet. The run wrote nothing to staging.

Not proven: native sheet rendering, the LogBox error going away, the iOS 26 header, and how smooth the app feels. Adam checks those on his phone from this branch's Metro.

🤖 Generated with Claude Code

Programcode and others added 6 commits October 9, 2026 13:08
New debate opened as an empty sheet on the iPhone: the keyboard came up,
but nothing else showed. react-native-screens sizes a form sheet's scroll
view natively. A scroll view that is the sheet's direct child only has
its size set. One nested in a KeyboardAvoidingView falls back to
setFrame(screen.frame), which copies the sheet's slide-in offset and
leaves the content below the visible sheet. The switcher, whose scroll
view was the root, rendered fine.

SheetScrollView is now the root of every sheet, with no
KeyboardAvoidingView. iOS raises the sheet to its top detent for the
keyboard, and automaticallyAdjustKeyboardInsets scrolls the fields clear
of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The switcher's one-off switch was disabled without a Current Debate, so
on an account with no current debate it was greyed out and did nothing.
The website lets you turn one-off mode on at any time.

The switch now always works. OneOffNotice shows the website's one-off
copy on the Debate tab (also in its empty state), in Ask and in the
Library, with "Return to debate" only when there is a debate to return
to, as in CurrentDebateStrip. The Library says only that the mode is on,
because new sources still go to the Current Debate there, as on the
website. The debates switcher also moves to SheetScrollView.

The screenshot run toggles the switch with and without a Current
Debate, shoots both states, and checks that Return turns the mode off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hermes in Expo Go has no Intl.PluralRules. i18next logged a red LogBox
error on the phone and fell back to v3 plural handling, which looks for
`_plural` keys. Keys with only `_one` and `_other` then rendered as the
raw key ("mobile.debates.sourceCount"), and the rest always used the
plural form ("1 messages").

@formatjs/intl-pluralrules (pure JS, with en, es and hu data) now loads
before i18next initialises. It installs only where PluralRules is
missing, so the web keeps the browser's. Hermes already has
Intl.getCanonicalLocales, which the polyfill needs, and
Intl.DateTimeFormat, the only other Intl API the app calls. date-fns
formats relative dates itself.

Checked in Node with Intl.PluralRules and Intl.Locale deleted: without
the polyfill the error and raw keys reproduce; with it en, es and hu
give 1 source / 2 sources, 1 fuente / 2 fuentes, 1 forrás / 2 forrás.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On iOS 26, react-native-screens warned that the tab headers used both a
blur effect and scroll edge effects. iOS 26 draws its own scroll edge
effect under a transparent header, so the blur now applies only on
earlier iOS, which has no edge effect.

CADisableMinimumFrameDurationOnPhone lets ProMotion iPhones run at 120
Hz. Expo Go's Info.plist cannot change, so this takes effect from the
first development build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The debate list refreshes on every Debate tab focus, on returning to the
app and when the switcher opens. Each refresh stored a new array, which
re-rendered every mounted tab that reads the debates even when nothing
had changed. An unchanged list now keeps its identity.

Ask scrolled to the end with an animation on every 30 ms paint of a
streamed answer, restarting the animation each time. It now jumps while
streaming and animates only for whole messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Metro's CLI crashed with getaddrinfo ENOTFOUND during Adam's session: the
VPS cannot resolve its own MagicDNS name. The Expo Go runbook now puts
the tailnet IP in REACT_NATIVE_PACKAGER_HOSTNAME and keeps the name only
as a note. It also says that `npx expo login` runs from apps/mobile and
that its browser login calls back to localhost on the VPS.

apps/mobile/AGENTS.md records that a form sheet's root view must be
SheetScrollView, and where one-off mode shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 9, 2026 13:16
@vercel

vercel Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
debate-navigator Ready Ready Preview Oct 9, 2026 2:47pm UTC
debatelab-staging Ready Ready Preview Oct 9, 2026 2:47pm UTC

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Free
  • Run ID: 0f46af26-928f-4237-882d-061d2e7cb389

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.


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

@Programcode

Copy link
Copy Markdown
Owner Author

Codex review r1 (gpt-6.1-sol, head 5961a02): no findings. Codex checked whether one-off mode matches the website for Ask saves, Library additions and recent work, plus the sheet roots and keyboard insets, the header config, translations and the runbook. Node 22 probes passed for keepIfSame and for en/es/hu plurals with and without native Intl.PluralRules. I'm holding the merge until Adam checks the native sheets, the one-off switch, LogBox and smoothness on his iPhone, running this branch's Metro at exp://100.115.45.111:9231.

🤖 Generated with Claude Code

Programcode and others added 2 commits October 9, 2026 14:28
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… list on refresh

The phone-test fixes put OneOffNotice on the Debate tab, Ask and the
Library. The merged Prepare tab and the Generate and Attack forms had their
own one-off text with no way back. They now show the same notice, with
"Return to debate" when there is a Current Debate, as the website's
CurrentDebateStrip does. Prepare keeps listing the Current Debate's saved
results in one-off mode, like the Debate tab and the website's home.

Prepare rereads its saved results on every focus. An unchanged list now
keeps its identity, the way the debate list does, through a shared
keepIfSame.

The screenshot run turns one-off mode on, shoots Prepare and Generate, and
checks that Return turns it off again.

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

Copy link
Copy Markdown
Owner Author

Codex review r2 (gpt-6.1-sol, head 3ac60bb): no findings. Codex checked the full diff, the merge with #130 and the follow-up commit. It confirmed #130's session memory, Undo debate check, cancellation, truncation notices and index keys are intact, along with Prepare's sequence guard with keepIfSame, one-off context and saving, the sheet roots, screenshots, localization and docs. Node 22 probes passed.

Local checks at 3ac60bb (GitHub Actions starts no jobs because of billing): npm run verify exit 0 (289 Vitest, 333 Deno, 30 Chromium smoke); 264 screenshots; the iOS bundle builds through Metro.

Not yet confirmed on Adam's iPhone: the native sheets and how smooth it feels. Adam asked me to keep going, so I'm merging into feat/native-ios and moving his Expo Go server to the merged branch for the next phone check.

🤖 Generated with Claude Code

@Programcode
Programcode merged commit 73ee099 into feat/native-ios Oct 9, 2026
8 of 16 checks passed
@Programcode
Programcode deleted the native-ios/03d-m1-fixes branch October 9, 2026 16:26
Programcode added a commit that referenced this pull request Oct 9, 2026
Brings in #129. Conflicts kept both sides: the Debate tab and Prepare import
the shared OneOffNotice next to prepareToolHref, the screenshot script shoots
Brainstorm and Factoids and then the one-off tools, and the app guide keeps the
Brainstorm and Factoids paragraph beside #129's one-off text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Programcode added a commit that referenced this pull request Oct 9, 2026
Both forms show it through WorkingIn since #129. The screenshot script now
opens each from Prepare in one-off mode and waits for the notice, and the app
guide names them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Programcode added a commit that referenced this pull request Oct 9, 2026
Brings in #129. Conflicts kept both sides: the screenshot script shoots the
Timer, Crossfire and then the one-off tools, and the app guide keeps the Timer
and Crossfire paragraphs beside #129's one-off text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Programcode added a commit that referenced this pull request Oct 9, 2026
The website shows crossfire.charactersRemaining under the turn field. It was
left out because plural strings did not render on Hermes; #129's
Intl.PluralRules polyfill fixes that, so the composer now shows it beside its
label, and the screenshot script checks it reads as a number. The app guide
notes that the Crossfire setup shows one-off mode through WorkingIn, as the
website's CurrentDebateStrip does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Programcode added a commit that referenced this pull request Oct 14, 2026
Brings in feat/native-ios after #129 and #131's fixes. sheet.tsx,
keep-if-same.ts and one-off-notice.tsx were the same on both sides, so
the Flowchart now uses the shared files. Conflicts: apps/mobile/AGENTS.md
keeps the Flowchart entry and the base's one-off wording, with the
Flowchart added to where OneOffNotice shows; the screenshot script runs
both the Flowchart and the one-off tool shots.

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

This branch was successfully deployed

2 active deployments
Preview – debate-navigator — 3ac60bb8 Deployed Oct 9, 2026 by vercel[bot]
Preview – debatelab-staging — 3ac60bb8 Deployed Oct 9, 2026 by vercel[bot]
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.

2 participants