Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Leader Key.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
6D9B9C012DBA000000000001 /* ConfigOutlineEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9B9C002DBA000000000001 /* ConfigOutlineEditorView.swift */; };
6D9B9C042DBA000000000002 /* KeyCapture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9B9C032DBA000000000002 /* KeyCapture.swift */; };
6D9B9C062DBA000000000003 /* ConfigEditorShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9B9C052DBA000000000003 /* ConfigEditorShared.swift */; };
CC0000012E9A000000000008 /* StatsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000012E9A000000000007 /* StatsManager.swift */; };
CC0000012E9A00000000000A /* StatsPane.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000012E9A000000000009 /* StatsPane.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -114,6 +116,8 @@
6D9B9C002DBA000000000001 /* ConfigOutlineEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigOutlineEditorView.swift; sourceTree = "<group>"; };
6D9B9C032DBA000000000002 /* KeyCapture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyCapture.swift; sourceTree = "<group>"; };
6D9B9C052DBA000000000003 /* ConfigEditorShared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigEditorShared.swift; sourceTree = "<group>"; };
CC0000012E9A000000000007 /* StatsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsManager.swift; sourceTree = "<group>"; };
CC0000012E9A000000000009 /* StatsPane.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsPane.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -158,10 +162,19 @@
children = (
427C18242BD31E2E00955B98 /* GeneralPane.swift */,
42FDC3192D51687B004F5C5C /* AdvancedPane.swift */,
CC0000012E9A000000000009 /* StatsPane.swift */,
);
path = Settings;
sourceTree = "<group>";
};
CC0000012E9A000000000004 /* Stats */ = {
isa = PBXGroup;
children = (
CC0000012E9A000000000007 /* StatsManager.swift */,
);
path = Stats;
sourceTree = "<group>";
};
427C17DE2BD311B400955B98 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -206,6 +219,7 @@
427C184F2BD6652500955B98 /* Util.swift */,
427C17EE2BD311B500955B98 /* Assets.xcassets */,
423632242D68CC5D00878D92 /* Settings */,
CC0000012E9A000000000004 /* Stats */,
427C18362BD3243C00955B98 /* Support */,
423632232D68CB0F00878D92 /* Themes */,
427C18392BD3268000955B98 /* Views */,
Expand Down Expand Up @@ -443,6 +457,8 @@
42F4CDCD2D45B13600D0DD76 /* KeyButton.swift in Sources */,
606C56EF2DAB875A00198B9F /* Cheater.swift in Sources */,
427C181C2BD314B500955B98 /* Constants.swift in Sources */,
CC0000012E9A000000000008 /* StatsManager.swift in Sources */,
CC0000012E9A00000000000A /* StatsPane.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Leader Key/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ class AppDelegate: NSObject, NSApplicationDelegate,
contentView: {
AdvancedPane().environmentObject(self.config)
}),
Settings.Pane(
identifier: .stats, title: "Stats",
toolbarIcon: NSImage(
systemSymbolName: "chart.bar.fill", accessibilityDescription: "Stats")!,
contentView: {
StatsPane().environmentObject(self.config)
}),
],
style: .segmentedControl,
)
Expand Down
83 changes: 60 additions & 23 deletions Leader Key/Controller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,24 +160,34 @@ class Controller {
switch hit {
case .action(let action):
if execute {
// Capture keyPath BEFORE hiding (which clears navigation state)
let keyPath = statsKeyPath(leafKey: action.key)

if let mods = modifiers, isInStickyMode(mods) {
runAction(action)
runAction(action, keyPath: keyPath)
} else {
hide {
self.runAction(action)
self.runAction(action, keyPath: keyPath)
}
}
}
// If execute is false, just stay visible showing the matched action
case .group(let group):
if execute, let mods = modifiers, shouldRunGroupSequenceWithModifiers(mods) {
hide {
self.runGroup(group)
}
} else {
userState.display = group.key
userState.navigateToGroup(group)
}
case .group(let group):
if execute, let mods = modifiers, shouldRunGroupSequenceWithModifiers(mods) {
// Capture keyPath BEFORE hiding
let parentPath = statsKeyPath(leafKey: nil)
hide {
self.runGroup(group, parentPath: parentPath)
}
} else {
// Record group navigation for stats
if let keyPath = statsKeyPath(leafKey: group.key) {
StatsManager.shared.recordGroupNavigation(group: group, keyPath: keyPath)
}

userState.display = group.key
userState.navigateToGroup(group)
}
case .none:
window.notFound()
}
Expand Down Expand Up @@ -288,20 +298,47 @@ class Controller {
}
}

private func runGroup(_ group: Group) {
for groupOrAction in group.actions {
switch groupOrAction {
case .group(let group):
runGroup(group)
private func runGroup(_ group: Group, parentPath: String? = nil) {
let currentPath: String
if let parent = parentPath, let groupKey = group.key {
currentPath = parent + "/" + groupKey
} else if let groupKey = group.key {
currentPath = groupKey
} else {
currentPath = ""
}

for groupOrAction in group.actions {
switch groupOrAction {
case .group(let subGroup):
runGroup(subGroup, parentPath: currentPath)
case .action(let action):
runAction(action)
let actionPath: String?
if !currentPath.isEmpty, let actionKey = action.key {
actionPath = currentPath + "/" + actionKey
} else if let actionKey = action.key {
actionPath = actionKey
} else {
actionPath = nil
}
runAction(action, keyPath: actionPath)
}
}
}

private func runAction(_ action: Action) {
switch action.type {
case .application:
}
}

private func statsKeyPath(leafKey: String?) -> String? {
guard let leafKey, !leafKey.isEmpty else { return nil }
let components = userState.navigationPath.compactMap(\.key).filter { !$0.isEmpty } + [leafKey]
return components.joined(separator: "/")
}

private func runAction(_ action: Action, keyPath: String?) {
if let keyPath = keyPath {
StatsManager.shared.recordExecution(action: action, keyPath: keyPath)
}

switch action.type {
case .application:
NSWorkspace.shared.openApplication(
at: URL(fileURLWithPath: action.value),
configuration: NSWorkspace.OpenConfiguration())
Expand Down
1 change: 1 addition & 0 deletions Leader Key/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import Settings
extension Settings.PaneIdentifier {
static let general = Self("general")
static let advanced = Self("advanced")
static let stats = Self("stats")
}
Loading