feat: learn launch suggestions and preserve selection during refresh

This commit is contained in:
2026-10-11 20:52:00 +02:00
parent 01cf6cc8c4
commit e9ac609884
5 changed files with 163 additions and 9 deletions
+16 -6
View File
@@ -8,12 +8,14 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
private let statusLabel = NSTextField(labelWithString: "Finding applications…")
private let emptyLabel = NSTextField(labelWithString: "Finding applications…")
private let openButton = NSButton(title: "Open Application", target: nil, action: nil)
private let history: LaunchHistory
private var applications: [Application] = []
private var results: [Application] = []
private var discoveryTask: Task<Void, Never>?
private var isLaunching = false
init() {
init(history: LaunchHistory = LaunchHistory()) {
self.history = history
let window = LauncherPanel(
contentRect: NSRect(x: 0, y: 0, width: 750, height: 474),
styleMask: [.borderless],
@@ -227,16 +229,23 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
guard let self else { return }
self.applications = applications
self.discoveryTask = nil
self.updateResults()
self.updateResults(preservingSelection: true)
}
}
private func updateResults() {
results = ApplicationSearch.results(for: searchField.stringValue, in: applications)
private func updateResults(preservingSelection: Bool = false) {
let selectedURL = preservingSelection && results.indices.contains(tableView.selectedRow)
? results[tableView.selectedRow].id : nil
if searchField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
results = history.suggestions(in: applications)
} else {
results = ApplicationSearch.results(for: searchField.stringValue, in: applications)
}
tableView.reloadData()
if !results.isEmpty {
tableView.selectRowIndexes(IndexSet(integer: 0), byExtendingSelection: false)
tableView.scrollRowToVisible(0)
let row = selectedURL.flatMap { url in results.firstIndex { $0.id == url } } ?? 0
tableView.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
tableView.scrollRowToVisible(row)
}
emptyLabel.isHidden = !results.isEmpty
if discoveryTask != nil {
@@ -350,6 +359,7 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
Task {
do {
try await AppLauncher.launch(application.url)
history.recordLaunch(of: application)
window?.orderOut(nil)
} catch {
let alert = NSAlert(error: error)