The mic icon in AddTaskSheet was a static Image with no action and no
speech service behind it. Full implementation:
SpeechRecognizer.swift (new):
- @MainActor ObservableObject wrapping SFSpeechRecognizer + AVAudioEngine
- Requests speech recognition then microphone permission in sequence
- Streams partial results into @Published transcript; final result stops engine
- Suppresses transient error 301 (no speech detected)
- reset() cleans up on sheet dismiss
- [VOICE] log trail at every step: tapped → granted → started → transcript → saved
TodayView.swift — AddTaskSheet:
- @StateObject private var speech = SpeechRecognizer()
- onChange(speech.transcript) writes transcript to rawText (task field)
- Mic Image → Button { speech.toggle() } with mic.fill + pulse animation while recording
- .safeAreaInset shows a red dismissible error banner on permission denial
- submit() stops recording before saving; logs task title
- .onDisappear resets speech state
project.yml:
- NSMicrophoneUsageDescription
- NSSpeechRecognitionUsageDescription
Co-Authored-By: Kutesir <tqwyy79vzn@privaterelay.appleid.com>
134 lines
4.7 KiB
YAML
134 lines
4.7 KiB
YAML
name: KisaniCal
|
|
options:
|
|
bundleIdPrefix: com.kutesir
|
|
deploymentTarget:
|
|
iOS: "16.0"
|
|
xcodeVersion: "15.0"
|
|
createIntermediateGroups: true
|
|
|
|
settings:
|
|
base:
|
|
DEVELOPMENT_TEAM: K8BLMMR883
|
|
MARKETING_VERSION: "2.0"
|
|
CURRENT_PROJECT_VERSION: "9"
|
|
|
|
schemes:
|
|
KisaniCal:
|
|
build:
|
|
targets:
|
|
KisaniCal: all
|
|
run:
|
|
config: Debug
|
|
test:
|
|
config: Debug
|
|
targets:
|
|
- KisaniCalTests
|
|
profile:
|
|
config: Release
|
|
analyze:
|
|
config: Debug
|
|
archive:
|
|
config: Release
|
|
|
|
targets:
|
|
KisaniCal:
|
|
type: application
|
|
platform: iOS
|
|
deploymentTarget: "16.0"
|
|
sources:
|
|
- path: KisaniCal
|
|
dependencies:
|
|
- target: KisaniCalWidgets
|
|
embed: true
|
|
# WenzaWatch is built/embedded only when the watchOS platform is installed.
|
|
# Re-enable shipping it on the Watch by uncommenting the embed below (requires
|
|
# Xcode > Settings > Components > watchOS):
|
|
# - target: WenzaWatch
|
|
# embed: true
|
|
settings:
|
|
base:
|
|
SWIFT_VERSION: 5.9
|
|
TARGETED_DEVICE_FAMILY: "1,2"
|
|
GENERATE_INFOPLIST_FILE: YES
|
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation: YES
|
|
INFOPLIST_KEY_UILaunchStoryboardName: LaunchScreen
|
|
INFOPLIST_KEY_CFBundleDisplayName: "Wenza"
|
|
INFOPLIST_KEY_UIStatusBarStyle: UIStatusBarStyleDefault
|
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad: "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"
|
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone: "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"
|
|
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
|
|
INFOPLIST_KEY_NSSupportsLiveActivities: YES
|
|
CODE_SIGN_STYLE: Automatic
|
|
CODE_SIGN_ENTITLEMENTS: KisaniCal/KisaniCal.entitlements
|
|
ENABLE_PREVIEWS: YES
|
|
INFOPLIST_KEY_NSCalendarsUsageDescription: "Wenza shows your calendar events alongside tasks."
|
|
INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription: "Wenza shows your calendar events alongside tasks."
|
|
INFOPLIST_KEY_NSHealthShareUsageDescription: "Wenza reads your steps, energy, heart rate, and workouts to show health stats on your dashboard."
|
|
INFOPLIST_KEY_NSHealthUpdateUsageDescription: "Wenza saves workouts you complete to the Health app."
|
|
INFOPLIST_KEY_NSMicrophoneUsageDescription: "Wenza uses your microphone to convert speech into task text."
|
|
INFOPLIST_KEY_NSSpeechRecognitionUsageDescription: "Wenza uses speech recognition so you can add tasks by voice."
|
|
|
|
KisaniCalTests:
|
|
type: bundle.unit-test
|
|
platform: iOS
|
|
deploymentTarget: "16.0"
|
|
sources:
|
|
- path: KisaniCalTests
|
|
dependencies:
|
|
- target: KisaniCal
|
|
settings:
|
|
base:
|
|
SWIFT_VERSION: 5.9
|
|
GENERATE_INFOPLIST_FILE: YES
|
|
|
|
KisaniCalWidgets:
|
|
type: app-extension
|
|
platform: iOS
|
|
deploymentTarget: "18.0"
|
|
sources:
|
|
- path: KisaniCalWidgets
|
|
- path: KisaniCal/Managers/AppGroup.swift
|
|
- path: KisaniCal/Managers/TaskActivityAttributes.swift
|
|
info:
|
|
path: KisaniCalWidgets/Info.plist
|
|
properties:
|
|
CFBundleDisplayName: "Wenza Widgets"
|
|
CFBundleShortVersionString: "$(MARKETING_VERSION)"
|
|
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)"
|
|
NSExtension:
|
|
NSExtensionPointIdentifier: com.apple.widgetkit-extension
|
|
settings:
|
|
base:
|
|
SWIFT_VERSION: 5.9
|
|
CODE_SIGN_STYLE: Automatic
|
|
GENERATE_INFOPLIST_FILE: NO
|
|
PRODUCT_BUNDLE_IDENTIFIER: com.kutesir.KisaniCal.KisaniCalWidgets
|
|
LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"
|
|
APPLICATION_EXTENSION_API_ONLY: YES
|
|
CODE_SIGN_ENTITLEMENTS: KisaniCalWidgets/KisaniCalWidgets.entitlements
|
|
|
|
WenzaWatch:
|
|
type: application
|
|
platform: watchOS
|
|
deploymentTarget: "10.0"
|
|
sources:
|
|
- path: WenzaWatch
|
|
info:
|
|
path: WenzaWatch/Info.plist
|
|
properties:
|
|
CFBundleDisplayName: "Wenza"
|
|
CFBundleShortVersionString: "$(MARKETING_VERSION)"
|
|
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)"
|
|
WKApplication: true
|
|
WKCompanionAppBundleIdentifier: com.kutesir.KisaniCal
|
|
settings:
|
|
base:
|
|
SWIFT_VERSION: 5.9
|
|
GENERATE_INFOPLIST_FILE: NO
|
|
PRODUCT_BUNDLE_IDENTIFIER: com.kutesir.KisaniCal.watchkitapp
|
|
TARGETED_DEVICE_FAMILY: "4"
|
|
CODE_SIGN_STYLE: Automatic
|
|
CODE_SIGN_ENTITLEMENTS: WenzaWatch/WenzaWatch.entitlements
|
|
INFOPLIST_KEY_CFBundleDisplayName: "Wenza"
|