refactor: own daily currency calculation lifetime
This commit is contained in:
@@ -17,11 +17,7 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
|
||||
private var results: [Application] = []
|
||||
private var calculation: CalculatorResult?
|
||||
private var isCurrencyCalculation = false
|
||||
private var currencyRates: CurrencyRates?
|
||||
private var currencyFetchedAt: Date?
|
||||
private var currencyTask: Task<Void, Never>?
|
||||
private var currencyError: String?
|
||||
private var currencyFailureQuery: String?
|
||||
private let currency = CurrencyCalculation()
|
||||
private var locationLabels: [URL: String] = [:]
|
||||
private var discoveryTask: Task<Void, Never>?
|
||||
private var isLaunching = false
|
||||
@@ -104,6 +100,7 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
|
||||
if NSApp.isActive { self.window?.makeFirstResponder(self.searchField) }
|
||||
else { self.dismiss(restoringFocus: false) }
|
||||
}
|
||||
currency.changed = { [weak self] in self?.updateResults(preservingSelection: true) }
|
||||
restorePosition()
|
||||
}
|
||||
|
||||
@@ -111,10 +108,6 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
|
||||
fatalError("Conjure creates its window programmatically")
|
||||
}
|
||||
|
||||
deinit {
|
||||
currencyTask?.cancel()
|
||||
}
|
||||
|
||||
func present(command: Application.Command? = nil) {
|
||||
guard !isLaunching, window?.attachedSheet == nil else { return }
|
||||
if launcherFrameBeforeReview != nil {
|
||||
@@ -413,28 +406,6 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshCurrencyRates() {
|
||||
guard currencyTask == nil else { return }
|
||||
currencyTask = Task { [weak self] in
|
||||
let result: Result<CurrencyRates, any Error>
|
||||
do { result = .success(try await CurrencyAPI.fetch()) }
|
||||
catch { result = .failure(error) }
|
||||
guard !Task.isCancelled, let self else { return }
|
||||
self.currencyTask = nil
|
||||
switch result {
|
||||
case .success(let rates):
|
||||
self.currencyRates = rates
|
||||
self.currencyFetchedAt = Date()
|
||||
self.currencyError = nil
|
||||
self.currencyFailureQuery = nil
|
||||
case .failure(let error):
|
||||
self.currencyError = error.localizedDescription
|
||||
self.currencyFailureQuery = self.searchField.stringValue
|
||||
}
|
||||
self.updateResults(preservingSelection: true, allowingCurrencyFetch: false)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateLocationLabels() {
|
||||
var nameCounts: [String: Int] = [:]
|
||||
nameCounts.reserveCapacity(applications.count)
|
||||
@@ -457,38 +428,14 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
|
||||
}
|
||||
}
|
||||
|
||||
private func updateResults(preservingSelection: Bool = false, allowingCurrencyFetch: Bool = true) {
|
||||
private func updateResults(preservingSelection: Bool = false) {
|
||||
guard !isCommandOpen else { return }
|
||||
let selectedURL = preservingSelection && results.indices.contains(tableView.selectedRow)
|
||||
? results[tableView.selectedRow].id : nil
|
||||
let query = searchField.stringValue
|
||||
if currencyFailureQuery != query {
|
||||
currencyError = nil
|
||||
currencyFailureQuery = nil
|
||||
}
|
||||
isCurrencyCalculation = Calculator.isCurrencyQuery(query, currencyRates: currencyRates)
|
||||
let needsCurrencyRefresh = isCurrencyCalculation && (currencyFetchedAt.map {
|
||||
!Calendar.current.isDate($0, inSameDayAs: Date())
|
||||
} ?? true)
|
||||
if allowingCurrencyFetch, needsCurrencyRefresh, currencyError == nil {
|
||||
refreshCurrencyRates()
|
||||
}
|
||||
calculation = Calculator.evaluate(query, currencyRates: currencyRates)
|
||||
if isCurrencyCalculation, let currencyError {
|
||||
let cached = currencyRates.map { " Cached snapshot \($0.date) is not used." } ?? ""
|
||||
calculation = CalculatorResult(
|
||||
displayValue: "Currency rates unavailable", copyValue: nil,
|
||||
detail: "Daily rates: \(currencyError). Change the query to retry.\(cached)"
|
||||
)
|
||||
} else if isCurrencyCalculation, currencyRates != nil, let answer = calculation {
|
||||
let cacheStatus = needsCurrencyRefresh
|
||||
? (currencyTask == nil ? "Stale cached daily rates" : "Stale cache; refreshing daily rates…")
|
||||
: "Cached daily rates"
|
||||
calculation = CalculatorResult(
|
||||
displayValue: answer.displayValue, copyValue: answer.copyValue,
|
||||
detail: "\(answer.detail) · \(cacheStatus)"
|
||||
)
|
||||
}
|
||||
currency.update(query)
|
||||
isCurrencyCalculation = currency.isCurrency
|
||||
calculation = currency.result
|
||||
if calculation != nil { (window as? LauncherPanel)?.resetNumberHints() }
|
||||
if calculation != nil {
|
||||
results = []
|
||||
|
||||
Reference in New Issue
Block a user