diff options
| author | Christian Cleberg <[email protected]> | 2026-07-25 16:34:16 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-07-25 16:34:16 -0500 |
| commit | 1839c49700b079dbc7026cfadbe40a8336d38f93 (patch) | |
| tree | 0218543be57eabd4f6bcf41d1a0bc6f7eb38e2dc | |
| parent | 8f0f2b4b4f4b747b5d5fcc5a433f2f4b5109c940 (diff) | |
| download | daybyday-1839c49700b079dbc7026cfadbe40a8336d38f93.tar.gz daybyday-1839c49700b079dbc7026cfadbe40a8336d38f93.tar.bz2 daybyday-1839c49700b079dbc7026cfadbe40a8336d38f93.zip | |
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 <[email protected]>
| -rw-r--r-- | DayByDay.xcodeproj/project.pbxproj | 8 | ||||
| -rw-r--r-- | DayByDay.xcodeproj/project.xcworkspace/xcuserdata/cmc.xcuserdatad/UserInterfaceState.xcuserstate | bin | 0 -> 12344 bytes | |||
| -rw-r--r-- | DayByDay/SpeechSynthesizer.swift | 7 |
3 files changed, 11 insertions, 4 deletions
diff --git a/DayByDay.xcodeproj/project.pbxproj b/DayByDay.xcodeproj/project.pbxproj index a2d2497..f81c41f 100644 --- a/DayByDay.xcodeproj/project.pbxproj +++ b/DayByDay.xcodeproj/project.pbxproj @@ -338,7 +338,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 6; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = ZCNAX3VL9D; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -353,7 +353,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.3.2; + MARKETING_VERSION = 1.3.3; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DayByDay; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; @@ -372,7 +372,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 6; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = ZCNAX3VL9D; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -387,7 +387,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.3.2; + MARKETING_VERSION = 1.3.3; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.DayByDay; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; diff --git a/DayByDay.xcodeproj/project.xcworkspace/xcuserdata/cmc.xcuserdatad/UserInterfaceState.xcuserstate b/DayByDay.xcodeproj/project.xcworkspace/xcuserdata/cmc.xcuserdatad/UserInterfaceState.xcuserstate Binary files differnew file mode 100644 index 0000000..e151aff --- /dev/null +++ b/DayByDay.xcodeproj/project.xcworkspace/xcuserdata/cmc.xcuserdatad/UserInterfaceState.xcuserstate 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) |
