From 1839c49700b079dbc7026cfadbe40a8336d38f93 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Sat, 25 Jul 2026 16:34:16 -0500 Subject: feat: add haptic feedback on card tap Fire a rigid impact haptic in SpeechSynthesizer.speak(), which every card tap routes through, giving consistent tactile feedback across all categories. Co-Authored-By: Claude Opus 4.8 --- DayByDay/SpeechSynthesizer.swift | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'DayByDay') diff --git a/DayByDay/SpeechSynthesizer.swift b/DayByDay/SpeechSynthesizer.swift index ab6421b..fa0316c 100644 --- a/DayByDay/SpeechSynthesizer.swift +++ b/DayByDay/SpeechSynthesizer.swift @@ -4,6 +4,7 @@ // import AVFoundation +import UIKit /// Wrapper around AVSpeechSynthesizer that selects the highest-quality /// en-US neural voice available on the device. Falls back gracefully if @@ -13,6 +14,7 @@ final class SpeechSynthesizer { private let synthesizer = AVSpeechSynthesizer() private let voice: AVSpeechSynthesisVoice? + private let haptics = UIImpactFeedbackGenerator(style: .rigid) private init() { self.voice = Self.bestAvailableVoice() @@ -24,6 +26,11 @@ final class SpeechSynthesizer { } func speak(_ text: String) { + // Every speak() call is a card tap, so give a gentle tactile bump + // alongside the audio. Prepared just before firing for lowest latency. + haptics.prepare() + haptics.impactOccurred() + // Ensure speech plays through the speaker even when the silent switch is on. try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default) try? AVAudioSession.sharedInstance().setActive(true) -- cgit v1.2.3