NetNewsWire/Multiplatform/Shared/RefreshProgressModel.swift

87 lines
2.5 KiB
Swift

//
// RefreshProgressModel.swift
// NetNewsWire
//
// Created by Phil Viso on 7/2/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import SwiftUI
import Combine
import RSCore
import Account
class RefreshProgressModel: ObservableObject {
enum State {
case refreshProgress(Float)
case lastRefreshDateText(String)
case none
}
@Published var state = State.none
private static var dateFormatter: RelativeDateTimeFormatter = {
let formatter = RelativeDateTimeFormatter()
formatter.dateTimeStyle = .named
return formatter
}()
private static let lastRefreshDateTextUpdateInterval = 60
private static let lastRefreshDateTextRelativeDateFormattingThreshold = 60.0
func startup() {
updateState()
observeRefreshProgress()
scheduleLastRefreshDateTextUpdate()
}
// MARK: Observing account changes
private func observeRefreshProgress() {
NotificationCenter.default.addObserver(self, selector: #selector(accountRefreshProgressDidChange), name: .AccountRefreshProgressDidChange, object: nil)
}
// MARK: Refreshing state
@objc private func accountRefreshProgressDidChange() {
CoalescingQueue.standard.add(self, #selector(updateState))
}
@objc private func updateState() {
let progress = AccountManager.shared.combinedRefreshProgress
if !progress.isComplete {
let fractionCompleted = Float(progress.numberCompleted) / Float(progress.numberOfTasks)
self.state = .refreshProgress(fractionCompleted)
} else if let lastRefreshDate = AccountManager.shared.lastArticleFetchEndTime {
let text = localizedLastRefreshText(lastRefreshDate: lastRefreshDate)
self.state = .lastRefreshDateText(text)
} else {
self.state = .none
}
}
private func scheduleLastRefreshDateTextUpdate() {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(Self.lastRefreshDateTextUpdateInterval)) {
self.updateState()
self.scheduleLastRefreshDateTextUpdate()
}
}
private func localizedLastRefreshText(lastRefreshDate: Date) -> String {
let now = Date()
if now > lastRefreshDate.addingTimeInterval(Self.lastRefreshDateTextRelativeDateFormattingThreshold) {
let localizedDate = Self.dateFormatter.localizedString(for: lastRefreshDate, relativeTo: now)
let formatString = NSLocalizedString("Updated %@", comment: "Updated") as NSString
return NSString.localizedStringWithFormat(formatString, localizedDate) as String
} else {
return NSLocalizedString("Updated Just Now", comment: "Updated Just Now")
}
}
}