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
@@ -27,12 +27,7 @@ actor DemoGateway: GatewayAPI {
|
||||
}
|
||||
|
||||
func feed() async throws -> Feed {
|
||||
let items = items.filter { !settled.contains($0.id) }
|
||||
let needsYou = items.filter(\.phase.needsYou).sorted { $0.updatedAt < $1.updatedAt }
|
||||
let working = items.filter(\.phase.isWorking).sorted { $0.updatedAt > $1.updatedAt }
|
||||
let recent = items.filter { $0.phase == .completed || $0.phase == .failed }
|
||||
.sorted { $0.updatedAt > $1.updatedAt }
|
||||
return Feed(needsYou: needsYou, working: working, recent: Array(recent.prefix(10)), hosts: hosts)
|
||||
DemoFixtures.feed(items.filter { !settled.contains($0.id) }, hosts: hosts)
|
||||
}
|
||||
|
||||
func summary() async throws -> Summary {
|
||||
@@ -93,6 +88,16 @@ actor DemoGateway: GatewayAPI {
|
||||
settled.insert(item.id)
|
||||
}
|
||||
|
||||
func recent() async throws -> RecentResponse {
|
||||
RecentResponse(items: DemoFixtures.recent(items.filter { !settled.contains($0.id) }))
|
||||
}
|
||||
|
||||
func settleRecent() async throws -> SettleRecentResponse {
|
||||
let completed = DemoFixtures.recent(items.filter { !settled.contains($0.id) }).filter { $0.phase == .completed }
|
||||
settled.formUnion(completed.map(\.id))
|
||||
return SettleRecentResponse(settled: completed.count, failed: 0)
|
||||
}
|
||||
|
||||
func projects() async throws -> ProjectsResponse {
|
||||
ProjectsResponse(hosts: projectHosts)
|
||||
}
|
||||
@@ -254,7 +259,28 @@ struct DemoFixtures {
|
||||
projectTitle: "Panama", title: "Fix hyprlock crash", phase: .completed, updatedAt: ago(95),
|
||||
lastMessage: "Fixed. hyprlock no longer crashes when a monitor sleeps.", request: nil)
|
||||
|
||||
items = [approval, question, release, homelab, scaffold, containerfile, statusScreens, nextjs, hyprlock, cdn]
|
||||
// Older finished threads, past the feed's first 10 in Recent. The gateway has not read most of
|
||||
// them, so they have no last message.
|
||||
func older(_ host: HostSummary, _ id: String, _ project: String, _ title: String, hours: Double, failed: Bool = false) -> FeedItem {
|
||||
FeedItem(
|
||||
hostId: host.id, hostLabel: host.label, threadId: id, projectId: "p-\(project)", projectTitle: project,
|
||||
title: title, phase: failed ? .failed : .completed, updatedAt: ago(hours * 60), lastMessage: nil, request: nil)
|
||||
}
|
||||
let (mac, server, laptop) = (hosts[0], hosts[1], hosts[2])
|
||||
let olderRecent = [
|
||||
older(laptop, "t-icons", "wristcode", "App icon variants", hours: 4),
|
||||
older(mac, "t-receipts", "bill-tracker", "Receipt upload form", hours: 6),
|
||||
older(server, "t-backup", "homelab", "Nightly restic backup", hours: 9, failed: true),
|
||||
older(mac, "t-tailwind", "gbrown.org", "Tailwind 5 migration", hours: 20),
|
||||
older(server, "t-caddy", "homelab", "Caddy wildcard certs", hours: 27),
|
||||
older(laptop, "t-readme", "wristcode", "README pass", hours: 30),
|
||||
older(mac, "t-csv", "bill-tracker", "CSV export", hours: 50),
|
||||
older(server, "t-immich", "homelab", "Immich upgrade", hours: 72),
|
||||
older(mac, "t-lint", "cdn", "Clippy warnings", hours: 96),
|
||||
older(laptop, "t-pair", "wristcode", "Pairing code expiry", hours: 120),
|
||||
]
|
||||
|
||||
items = [approval, question, release, homelab, scaffold, containerfile, statusScreens, nextjs, hyprlock, cdn] + olderRecent
|
||||
|
||||
func m(_ id: String, _ role: Message.Role, _ minutes: Double, _ text: String) -> Message {
|
||||
Message(id: id, role: role, text: text, createdAt: ago(minutes))
|
||||
@@ -359,13 +385,31 @@ struct DemoFixtures {
|
||||
device: .init(name: "Apple Watch", pairedAt: days(-3), pushRegistered: true, apnsEnvironment: .production))
|
||||
}
|
||||
|
||||
/// The feed the gateway builds from these threads: needs-you oldest first, working and Recent
|
||||
/// newest first, and only the first 10 of Recent.
|
||||
static func feed(_ items: [FeedItem], hosts: [HostSummary]) -> Feed {
|
||||
let recent = recent(items)
|
||||
return Feed(
|
||||
needsYou: items.filter(\.phase.needsYou).sorted { $0.updatedAt < $1.updatedAt },
|
||||
working: items.filter(\.phase.isWorking).sorted { $0.updatedAt > $1.updatedAt },
|
||||
recent: Array(recent.prefix(10)),
|
||||
recentTotal: recent.count,
|
||||
hosts: hosts)
|
||||
}
|
||||
|
||||
/// Every finished or failed thread, newest first, as `GET /v1/recent` lists them.
|
||||
static func recent(_ items: [FeedItem]) -> [FeedItem] {
|
||||
items.filter { $0.phase == .completed || $0.phase == .failed }.sorted { $0.updatedAt > $1.updatedAt }
|
||||
}
|
||||
|
||||
/// A feed for previews, without going through the actor.
|
||||
static func previewFeed(now: Date = .now) -> Feed {
|
||||
let fixtures = DemoFixtures(now: now)
|
||||
return Feed(
|
||||
needsYou: fixtures.items.filter(\.phase.needsYou),
|
||||
working: fixtures.items.filter(\.phase.isWorking),
|
||||
recent: fixtures.items.filter { !$0.phase.needsYou && !$0.phase.isWorking },
|
||||
hosts: fixtures.hosts)
|
||||
return feed(fixtures.items, hosts: fixtures.hosts)
|
||||
}
|
||||
|
||||
/// The full Recent list for previews.
|
||||
static func previewRecent(now: Date = .now) -> [FeedItem] {
|
||||
recent(DemoFixtures(now: now).items)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user