Files
conjure/Sources/ConjureKit/LaunchHistory.swift
T

56 lines
2.1 KiB
Swift

import Foundation
@MainActor
public final class LaunchHistory {
private struct Usage {
var count: Int
var lastLaunch: Date
}
private static let storageKey = "applicationLaunchHistory"
private let defaults: UserDefaults
private let now: () -> Date
private var usage: [URL: Usage] = [:]
public init(defaults: UserDefaults = .standard, now: @escaping () -> Date = Date.init) {
self.defaults = defaults
self.now = now
for (identifier, value) in defaults.dictionary(forKey: Self.storageKey) ?? [:] {
guard let url = URL(string: identifier), url.isFileURL,
let record = value as? [String: Any],
let count = record["count"] as? Int, count > 0,
let lastLaunch = record["lastLaunch"] as? Date,
lastLaunch.timeIntervalSinceReferenceDate.isFinite else { continue }
usage[url] = Usage(count: count, lastLaunch: lastLaunch)
}
}
public func recordLaunch(of application: Application) {
let timestamp = now()
var record = usage[application.id] ?? Usage(count: 0, lastLaunch: timestamp)
if record.count < Int.max { record.count += 1 }
record.lastLaunch = timestamp
usage[application.id] = record
var saved: [String: [String: Any]] = [:]
saved.reserveCapacity(usage.count)
for (url, record) in usage {
saved[url.absoluteString] = ["count": record.count, "lastLaunch": record.lastLaunch]
}
defaults.set(saved, forKey: Self.storageKey)
}
public func suggestions(in applications: [Application]) -> [Application] {
applications.sorted { lhs, rhs in
let left = usage[lhs.id]
let right = usage[rhs.id]
let leftCount = left?.count ?? 0
let rightCount = right?.count ?? 0
if leftCount != rightCount { return leftCount > rightCount }
if let left, let right, left.lastLaunch != right.lastLaunch {
return left.lastLaunch > right.lastLaunch
}
return alphabetical(lhs, rhs)
}
}
}