Fix: Auto-initialize app after accessibility permission grant
Problem:
- When user first launches the app without accessibility permissions,
the system shows a permission dialog
- After granting permissions, the app was already running but not
fully initialized
- User couldn't reopen the app (already running) and functionality
wasn't available
Solution:
- Implemented permission monitoring with Timer (checks every 1 second)
- Deferred app initialization until permissions are granted
- Split initialization into initializeApp() method
- Automatically initialize once permissions are detected
User Experience:
- User grants permission in System Preferences
- App automatically detects permission change
- App initializes and starts working without restart
- Updated alert message to inform user about auto-start
Technical Changes:
- Added permissionCheckTimer for monitoring
- Added initializeApp() for deferred initialization
- Store config and keyMapper as instance variables
- Use Task { @MainActor } for timer callback
- Changed alert style from warning to informational
🤖 Generated with [Qoder](https://qoder.com)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
.qoder
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.AppleDouble
|
.AppleDouble
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
private var statusBarController: StatusBarController?
|
private var statusBarController: StatusBarController?
|
||||||
private var eventTapManager: EventTapManager?
|
private var eventTapManager: EventTapManager?
|
||||||
|
private var config: Config?
|
||||||
|
private var keyMapper: KeyMapper?
|
||||||
|
private var permissionCheckTimer: Timer?
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||||
Logger.setup()
|
Logger.setup()
|
||||||
@@ -13,19 +16,37 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
Logger.info("================================")
|
Logger.info("================================")
|
||||||
Logger.info("App bundle path: \(Bundle.main.bundlePath)")
|
Logger.info("App bundle path: \(Bundle.main.bundlePath)")
|
||||||
|
|
||||||
let config = loadConfig()
|
config = loadConfig()
|
||||||
Logger.logLevel = config.log.level
|
Logger.logLevel = config!.log.level
|
||||||
|
|
||||||
let keyMapper = KeyMapper(fromConfig: config)
|
|
||||||
keyMapper.printMappings()
|
|
||||||
|
|
||||||
Logger.info("Checking accessibility permissions...")
|
Logger.info("Checking accessibility permissions...")
|
||||||
if !checkAccessibilityPermissions() {
|
if !checkAccessibilityPermissions() {
|
||||||
Logger.error("Accessibility permissions not granted!")
|
Logger.warning("Accessibility permissions not granted, waiting for user to grant permissions...")
|
||||||
showAccessibilityAlert()
|
showAccessibilityAlert()
|
||||||
|
startPermissionMonitoring()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info("Accessibility permissions granted")
|
Logger.info("Accessibility permissions granted")
|
||||||
|
initializeApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationWillTerminate(_ notification: Notification) {
|
||||||
|
permissionCheckTimer?.invalidate()
|
||||||
|
eventTapManager?.stop()
|
||||||
|
Logger.info("Application terminated")
|
||||||
|
Logger.cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func initializeApp() {
|
||||||
|
guard let config = config else {
|
||||||
|
Logger.error("Configuration not loaded")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let keyMapper = KeyMapper(fromConfig: config)
|
||||||
|
self.keyMapper = keyMapper
|
||||||
|
keyMapper.printMappings()
|
||||||
|
|
||||||
eventTapManager = EventTapManager(keyMapper: keyMapper)
|
eventTapManager = EventTapManager(keyMapper: keyMapper)
|
||||||
statusBarController = StatusBarController(eventTapManager: eventTapManager!, config: config)
|
statusBarController = StatusBarController(eventTapManager: eventTapManager!, config: config)
|
||||||
@@ -42,10 +63,22 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
Logger.info("Application ready")
|
Logger.info("Application ready")
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(_ notification: Notification) {
|
private func startPermissionMonitoring() {
|
||||||
eventTapManager?.stop()
|
Logger.info("Starting permission monitoring...")
|
||||||
Logger.info("Application terminated")
|
|
||||||
Logger.cleanup()
|
permissionCheckTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
||||||
|
Task { @MainActor in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
let trusted = AXIsProcessTrusted()
|
||||||
|
if trusted {
|
||||||
|
Logger.info("Accessibility permissions granted! Initializing app...")
|
||||||
|
self.permissionCheckTimer?.invalidate()
|
||||||
|
self.permissionCheckTimer = nil
|
||||||
|
self.initializeApp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func loadConfig() -> Config {
|
private func loadConfig() -> Config {
|
||||||
@@ -87,9 +120,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
private func showAccessibilityAlert() {
|
private func showAccessibilityAlert() {
|
||||||
let alert = NSAlert()
|
let alert = NSAlert()
|
||||||
alert.messageText = "Accessibility Permissions Required"
|
alert.messageText = "Accessibility Permissions Required"
|
||||||
alert.informativeText = "uskey needs accessibility permissions to remap keyboard keys.\n\nPlease grant permissions in:\nSystem Preferences > Privacy & Security > Accessibility\n\nAfter granting permissions, restart the app."
|
alert.informativeText = "uskey needs accessibility permissions to remap keyboard keys.\n\nPlease:\n1. Click 'Open System Preferences' in the dialog that appeared\n2. Enable uskey in the Accessibility list\n\nThe app will automatically start once permissions are granted."
|
||||||
alert.alertStyle = .warning
|
alert.alertStyle = .informational
|
||||||
alert.addButton(withTitle: "OK")
|
alert.addButton(withTitle: "OK")
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
alert.runModal()
|
alert.runModal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user