Summary
Player haptics are currently produced by calling the platform Vibrator directly from MediaControllerViewModel (via VibrationEffect). We should delegate to Compose's native haptics — LocalHapticFeedback / HapticFeedback.performHapticFeedback(HapticFeedbackType.*) — instead of hand-rolling vibration timings/amplitudes.
Why
- Respects the user's system haptic settings and device-specific haptic tuning (direct
Vibrator calls bypass these).
- Platform-consistent feedback; no custom
VibrationEffect timings/amplitudes to maintain.
- Removes the
Vibrator / VibrationEffect plumbing from the ViewModel and keeps haptics in the UI layer where they belong.
Current state (MediaControllerViewModel)
activateHapticResponse() — double-pulse waveform (queue add / play-next)
softHaptic() — soft tick on committed player actions (play/pause, next/prev, seek-release, shuffle, repeat, favorite, seek-to-queue-item)
destructiveHaptic() — pronounced double-buzz on queue clear (drag-to-dismiss)
A few UI spots already use Compose haptics correctly (e.g. the long-press handler in AnimatedPlayerSheet).
Proposed approach
- Map each action to an appropriate
HapticFeedbackType (e.g. ContextClick/SegmentTick for soft actions, Reject/Confirm for the destructive clear, LongPress for long-press).
- The VM can't perform Compose haptics directly, so emit haptic events from the VM as a
Flow/Channel and collect them in the player composable to call performHapticFeedback(...) — keeping a single central trigger while delegating the actual feedback to Compose.
- Remove the three custom
Vibrator-based methods (and the Vibrator field / VIBRATE usage) once migrated.
Notes
- Needs a recent enough Compose Foundation for the richer
HapticFeedbackType set (Confirm/Reject/etc.) — confirm the version supports the types we pick.
- Context: the custom vibration approach was introduced/extended during the player-improvements work; this issue tracks consolidating it onto the Compose-native path.
Summary
Player haptics are currently produced by calling the platform
Vibratordirectly fromMediaControllerViewModel(viaVibrationEffect). We should delegate to Compose's native haptics —LocalHapticFeedback/HapticFeedback.performHapticFeedback(HapticFeedbackType.*)— instead of hand-rolling vibration timings/amplitudes.Why
Vibratorcalls bypass these).VibrationEffecttimings/amplitudes to maintain.Vibrator/VibrationEffectplumbing from the ViewModel and keeps haptics in the UI layer where they belong.Current state (
MediaControllerViewModel)activateHapticResponse()— double-pulse waveform (queue add / play-next)softHaptic()— soft tick on committed player actions (play/pause, next/prev, seek-release, shuffle, repeat, favorite, seek-to-queue-item)destructiveHaptic()— pronounced double-buzz on queue clear (drag-to-dismiss)A few UI spots already use Compose haptics correctly (e.g. the long-press handler in
AnimatedPlayerSheet).Proposed approach
HapticFeedbackType(e.g.ContextClick/SegmentTickfor soft actions,Reject/Confirmfor the destructive clear,LongPressfor long-press).Flow/Channeland collect them in the player composable to callperformHapticFeedback(...)— keeping a single central trigger while delegating the actual feedback to Compose.Vibrator-based methods (and theVibratorfield /VIBRATEusage) once migrated.Notes
HapticFeedbackTypeset (Confirm/Reject/etc.) — confirm the version supports the types we pick.