Update when the app launches or becomes active and it's been a day since last update

This commit is contained in:
Brandon Evans 2020-12-24 11:54:55 -07:00
parent 9b26688255
commit b342baff02
No known key found for this signature in database
GPG key ID: D58A4B8DB64F8E93
4 changed files with 30 additions and 1 deletions

View file

@ -167,12 +167,22 @@ class AppState: ObservableObject {
updatePublisher = update()
.sink(
receiveCompletion: { [unowned self] _ in
Current.defaults.setDate(Current.date(), forKey: "lastUpdated")
self.updatePublisher = nil
},
receiveValue: { _ in }
)
}
func updateIfNeeded() {
guard
let lastUpdated = Current.defaults.date(forKey: "lastUpdated"),
// This is bad date math but for this use case it doesn't need to be exact
lastUpdated < Current.date().addingTimeInterval(-60 * 60 * 24)
else { return }
update() as Void
}
private func update() -> AnyPublisher<[Xcode], Never> {
signInIfNeeded()
.flatMap {

View file

@ -19,6 +19,7 @@ public struct Environment {
public var logging = Logging()
public var keychain = Keychain()
public var defaults = Defaults()
public var date: () -> Date = Date.init
}
public var Current = Environment()
@ -153,6 +154,16 @@ public struct Defaults {
string(key)
}
public var date: (String) -> Date? = { Date(timeIntervalSince1970: UserDefaults.standard.double(forKey: $0)) }
public func date(forKey key: String) -> Date? {
date(key)
}
public var setDate: (Date?, String) -> Void = { UserDefaults.standard.set($0?.timeIntervalSince1970, forKey: $1) }
public func setDate(_ value: Date?, forKey key: String) {
setDate(value, key)
}
public var set: (Any?, String) -> Void = { UserDefaults.standard.set($0, forKey: $1) }
public func set(_ value: Any?, forKey key: String) {
set(value, key)

View file

@ -106,7 +106,6 @@ struct XcodeListView: View {
}
.navigationSubtitle(Text("Updated \(Date().addingTimeInterval(-600), style: .relative) ago"))
.frame(minWidth: 200, maxWidth: .infinity, minHeight: 300, maxHeight: .infinity)
.onAppear(perform: appState.update)
.alert(item: $appState.error) { error in
Alert(title: Text(error.title),
message: Text(verbatim: error.message),

View file

@ -4,12 +4,21 @@ import AppKit
@main
struct XcodesApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate: AppDelegate
@SwiftUI.Environment(\.scenePhase) private var scenePhase: ScenePhase
@StateObject private var appState = AppState()
var body: some Scene {
WindowGroup("Xcodes") {
XcodeListView()
.environmentObject(appState)
// This is intentionally used on a View, and not on a WindowGroup,
// so that it's triggered when an individual window's phase changes instead of all window phases.
// When used on a View it's also invoked on launch, which doesn't occur with a WindowGroup.
.onChange(of: scenePhase) { newScenePhase in
if case .active = newScenePhase {
appState.updateIfNeeded()
}
}
}
.commands {
CommandGroup(replacing: .appInfo) {