Add App Intents support for mini recorder control
This commit is contained in:
parent
405b7ed143
commit
35918eb473
33
VoiceInk/AppIntents/AppShortcuts.swift
Normal file
33
VoiceInk/AppIntents/AppShortcuts.swift
Normal file
@ -0,0 +1,33 @@
|
||||
import AppIntents
|
||||
import Foundation
|
||||
|
||||
struct AppShortcuts : AppShortcutsProvider {
|
||||
@AppShortcutsBuilder
|
||||
static var appShortcuts: [AppShortcut] {
|
||||
AppShortcut(
|
||||
intent: ToggleMiniRecorderIntent(),
|
||||
phrases: [
|
||||
"Toggle \(.applicationName) recorder",
|
||||
"Start \(.applicationName) recording",
|
||||
"Stop \(.applicationName) recording",
|
||||
"Toggle recorder in \(.applicationName)",
|
||||
"Start recording in \(.applicationName)",
|
||||
"Stop recording in \(.applicationName)"
|
||||
],
|
||||
shortTitle: "Toggle Recorder",
|
||||
systemImageName: "mic.circle"
|
||||
)
|
||||
|
||||
AppShortcut(
|
||||
intent: DismissMiniRecorderIntent(),
|
||||
phrases: [
|
||||
"Dismiss \(.applicationName) recorder",
|
||||
"Cancel \(.applicationName) recording",
|
||||
"Close \(.applicationName) recorder",
|
||||
"Hide \(.applicationName) recorder"
|
||||
],
|
||||
shortTitle: "Dismiss Recorder",
|
||||
systemImageName: "xmark.circle"
|
||||
)
|
||||
}
|
||||
}
|
||||
18
VoiceInk/AppIntents/DismissMiniRecorderIntent.swift
Normal file
18
VoiceInk/AppIntents/DismissMiniRecorderIntent.swift
Normal file
@ -0,0 +1,18 @@
|
||||
import AppIntents
|
||||
import Foundation
|
||||
import AppKit
|
||||
|
||||
struct DismissMiniRecorderIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Dismiss VoiceInk Recorder"
|
||||
static var description = IntentDescription("Dismiss the VoiceInk mini recorder and cancel any active recording.")
|
||||
|
||||
static var openAppWhenRun: Bool = false
|
||||
|
||||
@MainActor
|
||||
func perform() async throws -> some IntentResult & ProvidesDialog {
|
||||
NotificationCenter.default.post(name: .dismissMiniRecorder, object: nil)
|
||||
|
||||
let dialog = IntentDialog(stringLiteral: "VoiceInk recorder dismissed")
|
||||
return .result(dialog: dialog)
|
||||
}
|
||||
}
|
||||
32
VoiceInk/AppIntents/ToggleMiniRecorderIntent.swift
Normal file
32
VoiceInk/AppIntents/ToggleMiniRecorderIntent.swift
Normal file
@ -0,0 +1,32 @@
|
||||
import AppIntents
|
||||
import Foundation
|
||||
import AppKit
|
||||
|
||||
struct ToggleMiniRecorderIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Toggle VoiceInk Recorder"
|
||||
static var description = IntentDescription("Start or stop the VoiceInk mini recorder for voice transcription.")
|
||||
|
||||
static var openAppWhenRun: Bool = false
|
||||
|
||||
@MainActor
|
||||
func perform() async throws -> some IntentResult & ProvidesDialog {
|
||||
NotificationCenter.default.post(name: .toggleMiniRecorder, object: nil)
|
||||
|
||||
let dialog = IntentDialog(stringLiteral: "VoiceInk recorder toggled")
|
||||
return .result(dialog: dialog)
|
||||
}
|
||||
}
|
||||
|
||||
enum IntentError: Error, LocalizedError {
|
||||
case appNotAvailable
|
||||
case serviceNotAvailable
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .appNotAvailable:
|
||||
return "VoiceInk app is not available"
|
||||
case .serviceNotAvailable:
|
||||
return "VoiceInk recording service is not available"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ extension Notification.Name {
|
||||
static let languageDidChange = Notification.Name("languageDidChange")
|
||||
static let promptDidChange = Notification.Name("promptDidChange")
|
||||
static let toggleMiniRecorder = Notification.Name("toggleMiniRecorder")
|
||||
static let dismissMiniRecorder = Notification.Name("dismissMiniRecorder")
|
||||
static let didChangeModel = Notification.Name("didChangeModel")
|
||||
static let aiProviderKeyChanged = Notification.Name("aiProviderKeyChanged")
|
||||
static let licenseStatusChanged = Notification.Name("licenseStatusChanged")
|
||||
|
||||
@ -3,6 +3,7 @@ import SwiftData
|
||||
import Sparkle
|
||||
import AppKit
|
||||
import OSLog
|
||||
import AppIntents
|
||||
|
||||
@main
|
||||
struct VoiceInkApp: App {
|
||||
@ -82,6 +83,8 @@ struct VoiceInkApp: App {
|
||||
activeWindowService.configure(with: enhancementService)
|
||||
activeWindowService.configureWhisperState(whisperState)
|
||||
_activeWindowService = StateObject(wrappedValue: activeWindowService)
|
||||
|
||||
AppShortcuts.updateAppShortcutParameters()
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
|
||||
@ -90,6 +90,7 @@ extension WhisperState {
|
||||
|
||||
func setupNotifications() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleToggleMiniRecorder), name: .toggleMiniRecorder, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleDismissMiniRecorder), name: .dismissMiniRecorder, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleLicenseStatusChanged), name: .licenseStatusChanged, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handlePromptChange), name: .promptDidChange, object: nil)
|
||||
}
|
||||
@ -100,6 +101,12 @@ extension WhisperState {
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func handleDismissMiniRecorder() {
|
||||
Task {
|
||||
await dismissMiniRecorder()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func handleLicenseStatusChanged() {
|
||||
self.licenseViewModel = LicenseViewModel()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user