Watch: keep Recent past 10 behind an N more row with a full list, and settle all in one call
This commit is contained in:
1 parent
2a127327bf
commit
a5222e14e8
13 files changed
+384
-52
No files matched your search
@@ -30,18 +30,26 @@ final class AppModel {
|
||||
private(set) var settling: Set<String> = []
|
||||
/// Why settling an item failed, by item id. Its row shows the message.
|
||||
private(set) var settleErrors: [String: String] = [:]
|
||||
/// Every thread in Recent, for the full Recent screen, which loads it when it appears.
|
||||
private(set) var allRecent: [FeedItem]?
|
||||
private(set) var allRecentError: String?
|
||||
/// True while Settle all is out. Completed Recent threads are hidden meanwhile.
|
||||
private(set) var settlingAll = false
|
||||
/// Why Settle all failed, or how many threads it could not settle. The Recent header shows it.
|
||||
private(set) var settleAllError: String?
|
||||
private var apnsToken: String?
|
||||
private var refreshing = false
|
||||
/// The counts the complication was last told about.
|
||||
private var sharedSummary: Summary?
|
||||
|
||||
init(mode: Mode, feed: Feed? = nil, path: [Route] = []) {
|
||||
init(mode: Mode, feed: Feed? = nil, allRecent: [FeedItem]? = nil, path: [Route] = []) {
|
||||
self.mode = mode
|
||||
self.feed = feed
|
||||
self.allRecent = allRecent
|
||||
self.path = path
|
||||
}
|
||||
|
||||
/// `-demo` starts in demo mode. `-screen new|status|notifications`, `-host <hostId>` or
|
||||
/// `-demo` starts in demo mode. `-screen new|recent|status|notifications`, `-host <hostId>` or
|
||||
/// `-thread <hostId>/<threadId>` opens that screen, which is how the screenshots in
|
||||
/// watch/screenshots are taken.
|
||||
convenience init(launchArguments args: [String]) {
|
||||
@@ -55,6 +63,7 @@ final class AppModel {
|
||||
var path: [Route] = []
|
||||
switch argument("-screen") {
|
||||
case "new": path = [.newThread]
|
||||
case "recent": path = [.recent]
|
||||
case "status": path = [.status]
|
||||
case "notifications": path = [.status, .notifications]
|
||||
default: break
|
||||
@@ -182,11 +191,56 @@ final class AppModel {
|
||||
for (id, error) in failures {
|
||||
settleErrors[id] = message(for: error)
|
||||
}
|
||||
feed?.recent.removeAll { ids.contains($0.id) && failures[$0.id] == nil }
|
||||
let settled = ids.filter { failures[$0] == nil }
|
||||
removeFromRecent(settled.count) { settled.contains($0.id) }
|
||||
settling.subtract(ids)
|
||||
await refreshFeed()
|
||||
}
|
||||
|
||||
/// Recent threads to show: those not being settled.
|
||||
func visibleRecent(_ items: [FeedItem]) -> [FeedItem] {
|
||||
items.filter { !settling.contains($0.id) && !(settlingAll && $0.phase == .completed) }
|
||||
}
|
||||
|
||||
/// `GET /v1/recent`, for the full Recent screen.
|
||||
func loadAllRecent() async {
|
||||
guard mode != .unpaired else { return }
|
||||
do {
|
||||
allRecent = try await api.recent().items
|
||||
allRecentError = nil
|
||||
} catch {
|
||||
allRecentError = message(for: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Settles every completed thread in Recent with one call, including those past the feed's first
|
||||
/// 10. They leave at once. Then the feed, and the full list when it was loaded, refresh.
|
||||
func settleAllRecent() async {
|
||||
settlingAll = true
|
||||
settleAllError = nil
|
||||
do {
|
||||
let result = try await api.settleRecent()
|
||||
removeFromRecent(result.settled) { $0.phase == .completed }
|
||||
if result.failed > 0 {
|
||||
settleAllError = result.failed == 1 ? "1 thread didn't settle." : "\(result.failed) threads didn't settle."
|
||||
}
|
||||
} catch {
|
||||
settleAllError = message(for: error)
|
||||
}
|
||||
settlingAll = false
|
||||
await refreshFeed()
|
||||
if allRecent != nil { await loadAllRecent() }
|
||||
}
|
||||
|
||||
/// Drops settled threads from the feed and the full list until the next refresh confirms it.
|
||||
private func removeFromRecent(_ count: Int, where settled: (FeedItem) -> Bool) {
|
||||
allRecent?.removeAll(where: settled)
|
||||
guard var feed else { return }
|
||||
feed.recent.removeAll(where: settled)
|
||||
feed.recentTotal = max(feed.recent.count, feed.recentTotal - count)
|
||||
self.feed = feed
|
||||
}
|
||||
|
||||
func open(_ route: Route) {
|
||||
path = [route]
|
||||
}
|
||||
@@ -262,6 +316,6 @@ final class AppModel {
|
||||
extension AppModel {
|
||||
/// A demo model with the fixture feed already loaded, for previews.
|
||||
static func preview(path: [Route] = []) -> AppModel {
|
||||
AppModel(mode: .demo, feed: DemoFixtures.previewFeed(), path: path)
|
||||
AppModel(mode: .demo, feed: DemoFixtures.previewFeed(), allRecent: DemoFixtures.previewRecent(), path: path)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user