62 lines
2.0 KiB
Swift
62 lines
2.0 KiB
Swift
// The full Recent list, opened from the feed's "N more" row. It loads `GET /v1/recent` when it
|
|
// appears; nothing polls. Rows look and swipe like the feed's, and the header has Settle all.
|
|
|
|
import SwiftUI
|
|
|
|
struct RecentView: View {
|
|
@Environment(AppModel.self) private var model
|
|
/// Snapshots render the rows without their List, which ImageRenderer leaves blank.
|
|
var scrolls = true
|
|
|
|
var body: some View {
|
|
Group {
|
|
if scrolls {
|
|
List { rows }
|
|
.listStyle(.plain)
|
|
.refreshable { await model.loadAllRecent() }
|
|
.task { await model.loadAllRecent() }
|
|
} else {
|
|
VStack(spacing: 6) { rows }
|
|
.padding(.horizontal, 4)
|
|
}
|
|
}
|
|
.navigationTitle("Recent")
|
|
}
|
|
|
|
@ViewBuilder private var rows: some View {
|
|
if let all = model.allRecent {
|
|
let items = model.visibleRecent(all)
|
|
RecentHeader(title: items.count == 1 ? "1 thread" : "\(items.count) threads", recent: items)
|
|
.feedRow()
|
|
ForEach(items) { item in
|
|
RecentRow(item: item).feedRow()
|
|
}
|
|
} else if model.allRecentError == nil {
|
|
ProgressView()
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.top, 20)
|
|
.feedRow()
|
|
}
|
|
if let error = model.allRecentError {
|
|
Text(error)
|
|
.font(.system(size: 12))
|
|
.foregroundStyle(Theme.secondaryText)
|
|
.padding(.horizontal, 8)
|
|
.feedRow()
|
|
if model.allRecent == nil {
|
|
Button("Try again") { Task { await model.loadAllRecent() } }
|
|
.buttonStyle(PillButtonStyle(fill: Theme.control, foreground: .white))
|
|
.feedRow()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview("Recent") {
|
|
NavigationStack {
|
|
RecentView()
|
|
}
|
|
.environment(AppModel.preview())
|
|
.fontDesign(.rounded)
|
|
}
|