iOS: time picker for reminder is buggy #9

Closed
opened 2026-08-26 08:24:52 +00:00 by uwayss · 4 comments
Owner

The way we handle onChange events works on Android but causes the iOS picker to be dismissed on the first drag. We'll fix this by making our own JS picker component and removing the community package.

The way we handle onChange events works on Android but causes the iOS picker to be dismissed on the first drag. We'll fix this by making our own JS picker component and removing the community package.
Author
Owner

Hey @claude make one that looks like the native iOS time picker but.. don't over-do it. Keep it simple and make sure you give tiny haptics on the drag just like the native ones. Again, it shouldn't look like an iOS rip-off. I attached an image I hope you can see it. This is a sketch of how i'd like it to be, Go ahead image

Hey @claude make one that looks like the native iOS time picker but.. don't over-do it. Keep it simple and make sure you give tiny haptics on the drag just like the native ones. Again, it shouldn't look like an iOS rip-off. I attached an image I hope you can see it. This is a sketch of how i'd like it to be, Go ahead ![image](/attachments/bd36640f-e320-4fad-a645-6e81ccc5d4a9)
Collaborator

Pushed to claude/ios-time-picker-fix.

Summary

Replaced @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 — mirroring the native tick feel without copying iOS's chrome.
  • src/features/settings/TimePickerModal.tsx (new): the reminder-time modal, using the app's existing centered-card modal style (matches LogDeedModal/SettingsOptionModal conventions) 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 (wraps Haptics.selectionAsync(), respecting the existing haptics setting).
  • 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).

Verified with tsc --noEmit, expo lint, and prettier --check — all clean. I didn't have a way to run the actual iOS app in this CI environment, so the interaction should be manually verified on-device, but the drag-dismiss bug can no longer occur since the community picker is gone entirely.

One note: the issue included a sketch image attachment that I couldn't view from this environment, so the visual design (wheel columns with a single highlight bar, colon separator, simple fades) is my best interpretation of "looks native but simple, not a rip-off" rather than a pixel match to that sketch — worth a visual check against the original sketch before merging.

Pushed to `claude/ios-time-picker-fix`. ## Summary Replaced `@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 — mirroring the native tick feel without copying iOS's chrome. - **`src/features/settings/TimePickerModal.tsx`** (new): the reminder-time modal, using the app's existing centered-card modal style (matches `LogDeedModal`/`SettingsOptionModal` conventions) 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` (wraps `Haptics.selectionAsync()`, respecting the existing haptics setting). - **`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). Verified with `tsc --noEmit`, `expo lint`, and `prettier --check` — all clean. I didn't have a way to run the actual iOS app in this CI environment, so the interaction should be manually verified on-device, but the drag-dismiss bug can no longer occur since the community picker is gone entirely. One note: the issue included a sketch image attachment that I couldn't view from this environment, so the visual design (wheel columns with a single highlight bar, colon separator, simple fades) is my best interpretation of "looks native but simple, not a rip-off" rather than a pixel match to that sketch — worth a visual check against the original sketch before merging.
Author
Owner

Nice, @claude

  1. open a PR
  2. I can't.. scroll in it. I can't move the wheels at all for some reason.
Nice, @claude 1. open a PR 2. I can't.. scroll in it. I can't move the wheels at all for some reason.
Collaborator

PR #12 created successfully: #12

Summary

Pushed a fix to claude/ios-time-picker-fix and opened PR #12: #12

Root cause of "can't scroll at all": TimePickerModal wrapped the card in a nested TouchableWithoutFeedback whose only job was to stop backdrop-dismiss taps from bubbling up. That put the wheel-picker ScrollViews inside a Touchable's responder subtree — on iOS, that ancestor Touchable claims the touch responder on touch-down before the ScrollView's native pan gesture recognizer gets a chance to activate, so the wheels never received any drag at all (not just a first-drag dismiss).

Fix: replaced the nested TouchableWithoutFeedback wrapper with a Pressable backdrop that's a sibling of the card (absolutely positioned behind it) instead of an ancestor. The card and its WheelPickers are no longer inside any touch-consuming parent, so drags reach the ScrollView directly.

Verified tsc --noEmit, expo lint, and prettier --check all pass. I still don't have a real iOS device in this CI environment, so please give the drag feel and haptics a manual check on-device before merging.

PR #12 created successfully: https://code.uwayss.com/uwayss/muhsin/pulls/12 ## Summary Pushed a fix to `claude/ios-time-picker-fix` and opened **PR #12**: https://code.uwayss.com/uwayss/muhsin/pulls/12 **Root cause of "can't scroll at all":** `TimePickerModal` wrapped the card in a nested `TouchableWithoutFeedback` whose only job was to stop backdrop-dismiss taps from bubbling up. That put the wheel-picker `ScrollView`s inside a `Touchable`'s responder subtree — on iOS, that ancestor Touchable claims the touch responder on touch-down before the ScrollView's native pan gesture recognizer gets a chance to activate, so the wheels never received any drag at all (not just a first-drag dismiss). **Fix:** replaced the nested `TouchableWithoutFeedback` wrapper with a `Pressable` backdrop that's a *sibling* of the card (absolutely positioned behind it) instead of an *ancestor*. The card and its `WheelPicker`s are no longer inside any touch-consuming parent, so drags reach the ScrollView directly. Verified `tsc --noEmit`, `expo lint`, and `prettier --check` all pass. I still don't have a real iOS device in this CI environment, so please give the drag feel and haptics a manual check on-device before merging.
Sign in to join this conversation.
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#9
No description provided.