All MicroEvals
PLEASE IMPLEMENT THIS PLAN: # Sound + haptics redesign ## C...
Create MicroEval

PLEASE IMPLEMENT THIS PLAN: # Sound + haptics redesign ## C...

Prompt

PLEASE IMPLEMENT THIS PLAN: # Sound + haptics redesign ## Context The app's haptics and sounds grew call site by call site: ~70 raw preset calls through `utils/VibrationUtils.ts` (`expo-haptics`), four synthesized chat sounds plus two call mp3s (`expo-audio`), system defaults for pushes, nothing on web, and no sounds switch. Using the `sound-haptics-design` skill (causality, harmony, utility; default is no effect), the goal is one small feedback vocabulary that means the same thing on iOS, Android and web, with fewer and better effects. Decisions from the brainstorm: - First pass = foundation + fixes. New moments come after. - Sound scope: sounds switch, sounds on web, branded push sound, own call sounds. - Custom haptics (Core Haptics / Android compositions): decide after a Motion Lab prototype. ## Audit facts the plan rests on - iOS: `expo-haptics` = UIKit feedback generators. No Core Haptics, no `.ahap`. - Android: `impactAsync` / `notificationAsync` / `selectionAsync` are `Vibrator` waveforms (`HapticsModule.kt:51`); `performAndroidHapticsAsync` uses `view.performHapticFeedback` (line 45). - Usage: selection 23, success 16, light 13, error 11, medium 4, ripple 2, rigid 1. - `VibrationUtils.ripple` = three presets on `setTimeout`. - Voice note cancel fires `error` (`useVoiceNoteRecording.ts:241`). - `chatSounds.ts` returns early on web; `chat-pop` is identical on every bubble. - `DESIGN.md` "Press and haptics" table has stale rows. ## Phase 1: semantic layer (JS only) New `utils/feedback/` (name open): - `feedback.ts`: one function per event. Starting vocabulary, from what the code already does: `selectionChanged`, `thresholdReached` (swipe-to-reply, slide lock, call bar snap), `lifted` (long-press menu), `recordingStarted`, `actionSucceeded`, `actionFailed`, `actionCancelled`, `iraSpoke`, `iraReacted`, `callConnected`, `callEnded`, `rippleSent`. - Per-platform map in one table: - iOS: today's UIKit presets (no feel change except the fixes below). - Android: `Haptics.performAndroidHapticsAsync(AndroidHaptics.*)` equivalents (e.g. Confirm, Reject, Segment_Tick, Long_Press, Gesture_End); pick each on a real phone. - Web: no haptic. - `VibrationUtils` keeps the switch, storage and error handling; the event layer calls it. Components stop calling `light`/`medium` directly. - Migrate the ~70 call sites, `useHapticPick`, `useCallHaptics`, and `tests/hapticsMock.ts`. ## Phase 2: fixes and pruning - Voice note cancel -> `actionCancelled` (a soft/light impact), not the error pattern. - Trace the 16 `success` sites; move any that fire on tap to the confirmed outcome. - Review the 23 `selection` sites and the typing tick against "would removing it lose clarity"; list proposed removals for Saket before deleting any. - `chat-pop`: small bounded pitch/volume variation per bubble (playback rate on the existing player). - Rewrite the `DESIGN.md` table from the event map. ## Phase 3: sound scope - Sounds switch: `AsyncStorageManager` key beside `VIBRATION_ENABLED`, row in `components/IraPage/sections/GeneralSectionView.tsx`, read in `playChatSound`. i18n key in `en.json`. - Web: remove the `IS_WEB` return in `chatSounds.ts` and verify `expo-audio` web playback (browsers block audio until the first user gesture). - Own call sounds: synthesize ringback, connected, dropped and hang-up in `scripts/generate-chat-sounds.py` in the chime's voice; replace `assets/ringing-sound/*`, `assets/call-hang-up/*` and the native copies (`ios/Ira/`, `android/.../res/raw/`). Native rebuild. - Branded push sound: bundle the chime for iOS and Android. Android needs a new notification channel id (a channel's sound cannot change after creation) in `MessageNotificationHelper.java` and `utils/Notifications/NotificationTypes.js`. iOS needs the backend to name the sound in the push payload. Native rebuild + backend change; confirm with Rohan before shipping. ## Phase 4: prototype, then decide custom haptics In the Motion Lab (`components/MotionLab/demos/`), build the theme ripple two ways: presets on timers (today) vs a Core Haptics pattern on iOS / composition on Android. Compare on a real iPhone and a low-end Android. If custom wins, it becomes a small local module in `app/modules/` used only for the signature moments (ripple, payment confirmed, Ira's chime). ## Verification - `npx jest --findRelatedTests <changed> --ci --forceExit`, `npx tsc --noEmit`, `npm run lint` (existing: `tests/utils/VibrationUtils.test.ts`, `tests/hooks/hapticHooks.test.ts`, `tests/utils/Chat/chatSounds.test.ts`). - Haptics cannot be judged on a simulator: Saket checks each event on a real iPhone and an Android phone via a Motion Lab page that lists every event with a play button. - Web: chat sounds play after first interaction; sounds switch mutes them on all three platforms.

Drag to resize

Response not available

Drag to resize

Response not available

Drag to resize

Response not available

Drag to resize
Drag to resize