Browse Source

fix(mac): explicit AXIsProcessTrustedWithOptions prompt trigger with TCC reset and stable codesign identifier

main
Ali Alavi 21 hours ago
parent
commit
c23a2a5c08
  1. 5
      mac/package.sh
  2. 29
      mac/src/AppDelegate.swift

5
mac/package.sh

@ -25,8 +25,8 @@ cp "$BUILD_DIR/SonioxVoice" "$APP_BUNDLE/Contents/MacOS/SonioxVoice"
cp "$PROJECT_DIR/Info.plist" "$APP_BUNDLE/Contents/Info.plist" cp "$PROJECT_DIR/Info.plist" "$APP_BUNDLE/Contents/Info.plist"
cp "$PROJECT_DIR/resources/AppIcon.icns" "$APP_BUNDLE/Contents/Resources/AppIcon.icns" cp "$PROJECT_DIR/resources/AppIcon.icns" "$APP_BUNDLE/Contents/Resources/AppIcon.icns"
# 3. Ad-hoc Codesign
codesign --force --deep --sign - "$APP_BUNDLE"
# 3. Stable Codesign with explicit identifier
codesign --force --deep --sign - --identifier "com.soniox.voice" "$APP_BUNDLE"
echo "✅ App bundle assembled at $APP_BUNDLE" echo "✅ App bundle assembled at $APP_BUNDLE"
@ -52,4 +52,3 @@ rm -rf "/Applications/$APP_NAME.app"
cp -R "$APP_BUNDLE" "/Applications/$APP_NAME.app" cp -R "$APP_BUNDLE" "/Applications/$APP_NAME.app"
echo "🎉 All Done Successfully!" echo "🎉 All Done Successfully!"
ls -lh "$BUILD_DIR"

29
mac/src/AppDelegate.swift

@ -10,6 +10,7 @@ public final class AppDelegate: NSObject, NSApplicationDelegate {
private var isBusyFinalizing = false private var isBusyFinalizing = false
private var currentAudioLevel: Float = 0.0 private var currentAudioLevel: Float = 0.0
private var latestPartialText: String? = nil private var latestPartialText: String? = nil
private var permissionPollTimer: Timer?
// Remote Android Phone Local Receiver (Port 8999) // Remote Android Phone Local Receiver (Port 8999)
private var remoteListener: NWListener? private var remoteListener: NWListener?
@ -135,6 +136,34 @@ public final class AppDelegate: NSObject, NSApplicationDelegate {
} }
private func checkInitialPermissions() { private func checkInitialPermissions() {
// 1. Force macOS to trigger the system Accessibility prompt dialog!
let axOptions = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] as CFDictionary
let axTrusted = AXIsProcessTrustedWithOptions(axOptions)
print("AppDelegate: 🔒 Accessibility Permission Status (trusted: \(axTrusted))")
if !axTrusted {
print("AppDelegate: ⚠️ Accessibility not yet granted! Prompting user and monitoring...")
// Open Accessibility pane directly
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") {
NSWorkspace.shared.open(url)
}
}
// Poll every 1.5 seconds until user toggles the switch
permissionPollTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: true) { [weak self] timer in
let nowTrusted = AXIsProcessTrusted()
if nowTrusted {
print("AppDelegate: 🟢 Accessibility Permission GRANTED by user!")
timer.invalidate()
self?.permissionPollTimer = nil
HotkeyManager.shared.registerHotkeys()
HUDOverlayController.shared.show(state: .success(text: "دسترسی Accessibility تایید شد ✅"))
}
}
}
// 2. Microphone permission
audioRecorder.requestMicrophonePermission { granted in audioRecorder.requestMicrophonePermission { granted in
if !granted { if !granted {
print("Warning: Microphone permission not granted.") print("Warning: Microphone permission not granted.")

Loading…
Cancel
Save