Initial commit of Edison Voice menu-bar dictation app

This commit is contained in:
2026-09-09 23:49:51 +02:00
commit ad02cfb638
40 changed files with 3305 additions and 0 deletions
@@ -0,0 +1,52 @@
import AVFoundation
import AppKit
import ApplicationServices
import Foundation
/// Edison Voice needs two grants, and neither can be worked around:
/// - **Microphone** — obviously.
/// - **Accessibility** — for both the `CGEventTap` (hotkey) and the AX text insert.
///
/// Accessibility has no programmatic request; the OS only shows the prompt, and the user
/// must toggle it in System Settings. TCC also keys on the code signature, so re-signing
/// the app resets the grant.
@MainActor
public enum Permissions {
public static var hasAccessibility: Bool {
AXIsProcessTrusted()
}
public static var hasMicrophone: Bool {
AVCaptureDevice.authorizationStatus(for: .audio) == .authorized
}
/// Shows the system Accessibility prompt if the app isn't yet trusted.
@discardableResult
public static func promptForAccessibility() -> Bool {
// Spelled out rather than using `kAXTrustedCheckOptionPrompt`, which imports as a
// mutable global and so isn't usable from concurrency-checked code.
let options = ["AXTrustedCheckOptionPrompt": true] as CFDictionary
return AXIsProcessTrustedWithOptions(options)
}
public static func requestMicrophone() async -> Bool {
switch AVCaptureDevice.authorizationStatus(for: .audio) {
case .authorized:
return true
case .notDetermined:
return await AVCaptureDevice.requestAccess(for: .audio)
default:
return false
}
}
public static func openAccessibilitySettings() {
let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")!
NSWorkspace.shared.open(url)
}
public static func openMicrophoneSettings() {
let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone")!
NSWorkspace.shared.open(url)
}
}