fix(ios): replace community time picker with a custom wheel picker #12

Merged
uwayss merged 3 commits from claude/ios-time-picker-fix into main 2026-08-27 11:05:49 +00:00

Closes #9.

Replaces @react-native-community/datetimepicker with a custom in-house time picker to fix the iOS dismiss-on-first-drag bug.

What changed:

  • src/components/WheelPicker.tsx (new): a reusable vertical wheel column built on react-native-reanimated + a plain ScrollView with snapToInterval. Items fade/scale by distance from center, and a tiny selection haptic fires each time the centered value changes while scrolling.
  • src/features/settings/TimePickerModal.tsx (new): the reminder-time modal, using the app's existing centered-card modal style, with an hours/minutes wheel pair, a shared highlight bar, and Cancel/Done actions.
  • src/screens/NotificationsScreen.tsx: swapped the community DateTimePicker for TimePickerModal.
  • src/core/utils/haptics.ts: added triggerSelectionHaptic.
  • package.json / package-lock.json / app.json: removed the @react-native-community/datetimepicker dependency and its Expo config plugin entry.
  • Added a settings.done i18n string (en/ar).

Follow-up fix: the wheels initially couldn't be scrolled at all. The card was wrapped in a nested TouchableWithoutFeedback (only there to stop backdrop-dismiss taps from bubbling), which put the wheel ScrollViews inside a Touchable's responder subtree — on iOS that Touchable claims the touch responder before the ScrollView can recognize the pan gesture. Fixed by making the backdrop a Pressable sibling of the card instead of an ancestor, so drags on the wheels never pass through a touch-consuming parent.

Verified with tsc --noEmit, expo lint, and prettier --check — all clean. No access to a real iOS device in this environment, so the drag/haptics feel is worth a manual on-device check before merging.

Closes #9. Replaces `@react-native-community/datetimepicker` with a custom in-house time picker to fix the iOS dismiss-on-first-drag bug. **What changed:** - **`src/components/WheelPicker.tsx`** (new): a reusable vertical wheel column built on `react-native-reanimated` + a plain `ScrollView` with `snapToInterval`. Items fade/scale by distance from center, and a tiny selection haptic fires each time the centered value changes while scrolling. - **`src/features/settings/TimePickerModal.tsx`** (new): the reminder-time modal, using the app's existing centered-card modal style, with an hours/minutes wheel pair, a shared highlight bar, and Cancel/Done actions. - **`src/screens/NotificationsScreen.tsx`**: swapped the community `DateTimePicker` for `TimePickerModal`. - **`src/core/utils/haptics.ts`**: added `triggerSelectionHaptic`. - **`package.json` / `package-lock.json` / `app.json`**: removed the `@react-native-community/datetimepicker` dependency and its Expo config plugin entry. - Added a `settings.done` i18n string (en/ar). **Follow-up fix:** the wheels initially couldn't be scrolled at all. The card was wrapped in a nested `TouchableWithoutFeedback` (only there to stop backdrop-dismiss taps from bubbling), which put the wheel `ScrollView`s inside a Touchable's responder subtree — on iOS that Touchable claims the touch responder before the ScrollView can recognize the pan gesture. Fixed by making the backdrop a `Pressable` sibling of the card instead of an ancestor, so drags on the wheels never pass through a touch-consuming parent. Verified with `tsc --noEmit`, `expo lint`, and `prettier --check` — all clean. No access to a real iOS device in this environment, so the drag/haptics feel is worth a manual on-device check before merging.
The community DateTimePicker's spinner dismisses itself on iOS after the
first drag, so onChange never commits a selection. Build our own simple
wheel picker (hours/minutes columns, reanimated-driven, tiny selection
haptics per tick) and drop @react-native-community/datetimepicker.
TimePickerModal wrapped its card in a nested TouchableWithoutFeedback
(used only to stop backdrop-dismiss taps from bubbling), which put the
WheelPicker ScrollViews inside a Touchable's responder subtree. On iOS
that nested Touchable claims the touch responder before the ScrollView
can recognize the pan, so the wheels never scrolled at all.

Replaced it with a Pressable backdrop that's a sibling of the card
instead of an ancestor, so drags on the wheels never pass through a
touch-consuming parent.
fix: reduce the transparency effect for the done and cancel buttons
All checks were successful
Checks / checks (pull_request) Successful in 24s
cefe3bbc43
uwayss merged commit da20202a49 into main 2026-08-27 11:05:49 +00:00
uwayss deleted branch claude/ios-time-picker-fix 2026-08-27 11:05:49 +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!12
No description provided.