Summary
When Leader Key is first launched (or reloaded), pressing the global hotkey immediately shows an empty root menu. Subsequent triggers work fine. This is a race condition between the async config load and hotkey activation.
Steps to reproduce
- Launch (or relaunch) Leader Key
- Press the global trigger hotkey within ~1 second of launch
- The root group panel appears empty — no actions listed
Root cause
The config is loaded on a background dispatch queue, but the global shortcut can fire before the main thread has received the populated root value.
In AppDelegate.swift:
config.ensureAndLoad() // async — returns immediately
state = UserState(userConfig: config)
controller = Controller(...) // user can trigger here before root is ready
In UserConfig.swift, loadConfig() reads the file on configIOQueue then dispatches back to the main thread:
@Published var root = emptyRoot // starts as empty
configIOQueue.async {
// file I/O + JSON decode ...
DispatchQueue.main.async {
self.root = decodedRoot // populated later, asynchronously
}
}
In Cheatsheet.swift, the panel renders userState.userConfig.root.actions — which is still emptyRoot.actions = [] during that window.
Suggested fix
Delay registration of the global hotkey until isLoading becomes false — e.g. observe userConfig.$isLoading and register shortcuts only after the first false emission. This ensures the user can never trigger the panel before root is populated.
Environment
- Leader Key 1.17.3
- macOS 15 (Sequoia)
Summary
When Leader Key is first launched (or reloaded), pressing the global hotkey immediately shows an empty root menu. Subsequent triggers work fine. This is a race condition between the async config load and hotkey activation.
Steps to reproduce
Root cause
The config is loaded on a background dispatch queue, but the global shortcut can fire before the main thread has received the populated
rootvalue.In
AppDelegate.swift:In
UserConfig.swift,loadConfig()reads the file onconfigIOQueuethen dispatches back to the main thread:In
Cheatsheet.swift, the panel rendersuserState.userConfig.root.actions— which is stillemptyRoot.actions = []during that window.Suggested fix
Delay registration of the global hotkey until
isLoadingbecomesfalse— e.g. observeuserConfig.$isLoadingand register shortcuts only after the firstfalseemission. This ensures the user can never trigger the panel beforerootis populated.Environment