Feature: Onboarding #35

Merged
uwayss merged 7 commits from feat/onboarding into develop 2026-09-04 14:41:37 +00:00
Owner

finally wuhuu

finally wuhuu
Closes #31.

A four-page swipeable flow shown once on first launch, before the tabs
mount: welcome, gender, preferences, and a closing page. Answers are
written to the store as they are tapped, so going back and forth keeps
them, and a dev-menu row replays the flow without touching any data.

- Gender is required; Next stays disabled until it is answered. The two
  options are pastel cards with the stick-figure icons, labelled Brother
  and Sister.
- Preferences is an extensible opt-in checklist, currently just the
  Hanafi Asr sunnah, each row with an info sheet explaining what it
  changes. Stored as an id list, so a future preference needs no new
  persisted field and existing users default to it being unset. The same
  list is reachable afterwards under Settings > Preferences.
- Skip finishes the flow early and is offered on the pages either side of
  the gender question. It stays mounted but invisible elsewhere so the
  footer height never changes mid-swipe.
- One mascot is drawn above the pager rather than per page, and
  interpolates its position and size between the room each page reserves
  for it, so it glides with the swipe instead of jumping between pages.

The pager is hand-rolled on a Pan gesture rather than a paging
ScrollView, whose contentOffset origin under RTL differs between iOS and
Android; layout direction reduces to a single multiplier here. Pages are
centred columns with no row layouts, so they read the same either way -
which also covers a first launch in Arabic, where forceRTL has been set
but does not apply until the next launch.

Also fixes a fresh install defaulting to English rather than the device
language, which the store needed a narrowed language type for anyway.
Gender and preferences carry about the same amount of content, so
shrinking the mascot on the second of them read as arbitrary. Both now
share one slot, leaving two sizes overall: large on the greeting pages,
smaller on the ones that ask something.
Gender had its own Settings row and option modal, which made sense while
Preferences held only the Hanafi tickbox. It no longer does: Preferences
is where a user goes to revisit what onboarding asked, so it now holds
both, in the order onboarding asks them.

GenderOption moves to features/preferences alongside the list it now
sits with, and both controls read and write the store themselves rather
than taking props - onboarding and Settings render the same components,
so the two places can't drift.
The first thing onboarding's gender question actually changes. It is a
display derivation, not a second deed: underneath it stays prayer-dhuhr,
so one id carries one unbroken run of logs and nothing needs rewriting
when Friday ends.

Deed names were resolved with the same i18n.t call spelled out at ten
sites, which left nowhere to put an exception. They now go through
getDeedName, and a deed may carry a displayNameKey that it prefers.
feat(onboarding): drop skipping entirely
All checks were successful
Checks / checks (pull_request) Successful in 1m36s
bf0dce62c9
The flow gated hard on the gender question and then offered a Skip link
on the page before it, which walked past that gate in one tap. Four
pages with one required question is short enough not to need an escape
hatch, and the last page is a send-off rather than a question - not
answering it is already an answer.
@ -20,0 +24,4 @@
"stepLabel": "الخطوة {{current}} من {{total}}",
"welcomeTitle": "أهلًا بك في مُحْسِن",
"welcomeBody": "أجب عن هذين السؤالين وابدأ استخدام التطبيق",
"genderTitle": "الجنس، من فضلك؟",
Author
Owner

OH GOD I NEED TO RE-DO THE TRANSLATIONS LOL!

OH GOD I NEED TO RE-DO THE TRANSLATIONS LOL!
uwayss marked this conversation as resolved
i18n: rewrite the onboarding copy in each language
All checks were successful
Checks / checks (pull_request) Successful in 23s
583f7ff796
The onboarding strings were written in English and then rendered word for
word into the other five, which left lines nobody would actually say -
"الجنس، من فضلك؟" for "Gender, please?", and Turkish option labels reading
"younger brother" / "younger sister" instead of male and female.

Rewritten per locale to say the same thing the way that language says it,
English source included: the gender question now asks "Brother or sister?"
to match the cards under it, and the German section is "Persönliches"
rather than the unidiomatic "Präferenzen".

Also corrects the Hanafi sunnah before Asr from two rak'ahs to four in all
six files.
Author
Owner

@claude i'm done with this branch but i might've missed something. Go ahead and take a look at the changes. Then give me a very very short and concise, direct verdict. Is it ready to be merged? What may I have missed?

@claude i'm done with this branch but i might've missed something. Go ahead and take a look at the changes. Then give me a very very short and concise, direct verdict. Is it ready to be merged? What may I have missed?
Collaborator

All 8 finder agents have now reported. The headline finding: swiping past the Gender page bypasses the required-answer gate entirely (the gesture handler calls onPageChange directly without checking canAdvance), letting users skip the very question commit bf0dce6 says skipping was removed for. The code-review skill should now move into its verification phase — waiting for that to complete before I write the final reply.

All 8 finder agents have now reported. The headline finding: swiping past the Gender page bypasses the required-answer gate entirely (the gesture handler calls `onPageChange` directly without checking `canAdvance`), letting users skip the very question commit `bf0dce6` says skipping was removed for. The code-review skill should now move into its verification phase — waiting for that to complete before I write the final reply.
fix(onboarding): stop a swipe getting past the gender question
All checks were successful
Checks / checks (pull_request) Successful in 2m47s
bf1d15fba6
The Next button was disabled until a gender was picked, but the pager's
gesture snapped to whichever page it landed on and called onPageChange
without consulting that rule - so a swipe walked straight past the one
question the flow requires an answer to.

The gate is now the furthest reachable page rather than a boolean the
button alone read. The pager clamps the live drag to it, so the next page
never slides into view, and clamps again on release, since a flick can
project past a bound the drag itself stayed inside. Bounds come from the
two end columns rather than from the layout direction, so RTL needs no
second path.
Author
Owner

@claude okay i fixed that. do another check. don't use complex skills or subagents you can only send me one answer. just do one message.

@claude okay i fixed that. do another check. don't use complex skills or subagents you can only send me one answer. just do one message.
Collaborator

All locales are consistent, lint and typecheck pass clean, and the swipe-gate fix (bf1d15f) correctly caps both the live drag and the post-flick projection via maxPage, with gender un-selectable back to null so the cap can't regress mid-flow. That closes the bug flagged earlier.

Verdict: Ready to merge.

Nothing else jumped out. One minor thing worth a glance, not a blocker: BackHandler on page === 0 returns false to let the OS close the app — fine — but there's no hardware-back handling gate on the gender page itself, though that's moot since back only ever moves to a lower page number, never past the gate.

No changes made to files this run.

All locales are consistent, lint and typecheck pass clean, and the swipe-gate fix (`bf1d15f`) correctly caps both the live drag and the post-flick projection via `maxPage`, with gender un-selectable back to null so the cap can't regress mid-flow. That closes the bug flagged earlier. ## Verdict: Ready to merge. Nothing else jumped out. One minor thing worth a glance, not a blocker: `BackHandler` on `page === 0` returns `false` to let the OS close the app — fine — but there's no hardware-back handling gate on the gender page itself, though that's moot since back only ever moves to a lower page number, never past the gate. No changes made to files this run.
uwayss merged commit 88a9f0a42e into develop 2026-09-04 14:41:37 +00:00
uwayss deleted branch feat/onboarding 2026-09-04 14:41:37 +00:00
uwayss referenced this pull request from a commit 2026-09-04 14:41:38 +00:00
uwayss referenced this pull request from a commit 2026-09-06 11:57:29 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
uwayss/muhsin!35
No description provided.