IceCubesApp/Packages/StatusKit/Sources/StatusKit/List/StatusesListView.swift

88 lines
2.4 KiB
Swift
Raw Normal View History

2023-01-17 10:36:01 +00:00
import DesignSystem
2023-02-04 16:17:38 +00:00
import Env
2022-12-19 06:17:01 +00:00
import Models
2023-02-18 06:26:48 +00:00
import Network
2022-12-19 06:17:01 +00:00
import Shimmer
2023-01-17 10:36:01 +00:00
import SwiftUI
2022-12-19 06:17:01 +00:00
2023-09-18 19:03:52 +00:00
@MainActor
2022-12-19 06:17:01 +00:00
public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
2023-09-18 19:03:52 +00:00
@Environment(Theme.self) private var theme
2023-03-13 12:38:28 +00:00
@State private var fetcher: Fetcher
// Whether this status is on a remote local timeline (many actions are unavailable if so)
private let isRemote: Bool
private let routerPath: RouterPath
private let client: Client
2023-03-13 12:38:28 +00:00
public init(fetcher: Fetcher,
client: Client,
routerPath: RouterPath,
2023-03-13 12:38:28 +00:00
isRemote: Bool = false)
{
_fetcher = .init(initialValue: fetcher)
self.isRemote = isRemote
self.client = client
self.routerPath = routerPath
2022-12-19 06:17:01 +00:00
}
2023-03-13 12:38:28 +00:00
2022-12-19 06:17:01 +00:00
public var body: some View {
switch fetcher.statusesState {
case .loading:
ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath))
.redacted(reason: .placeholder)
2023-09-18 16:55:11 +00:00
.allowsHitTesting(false)
}
case .error:
ErrorView(title: "status.error.title",
message: "status.error.loading.message",
2023-03-13 12:38:28 +00:00
buttonTitle: "action.retry")
{
Task {
await fetcher.fetchNewestStatuses(pullToRefresh: false)
2023-01-07 17:01:06 +00:00
}
}
2023-03-13 12:38:28 +00:00
.listRowBackground(theme.primaryBackgroundColor)
.listRowSeparator(.hidden)
case let .display(statuses, nextPageState):
2024-01-02 13:06:53 +00:00
ForEach(statuses, id: \.id) { status in
2024-01-01 20:29:03 +00:00
StatusRowView(viewModel: StatusRowViewModel(status: status,
client: client,
routerPath: routerPath,
isRemote: isRemote))
.onAppear {
fetcher.statusDidAppear(status: status)
}
.onDisappear {
fetcher.statusDidDisappear(status: status)
}
}
switch nextPageState {
case .hasNextPage:
loadingRow
.onAppear {
Task {
await fetcher.fetchNextPage()
2022-12-19 06:17:01 +00:00
}
}
case .loadingNextPage:
loadingRow
case .none:
EmptyView()
2022-12-19 06:17:01 +00:00
}
}
}
2023-03-13 12:38:28 +00:00
2022-12-19 06:17:01 +00:00
private var loadingRow: some View {
HStack {
Spacer()
ProgressView()
Spacer()
}
2023-01-03 17:22:08 +00:00
.padding(.horizontal, .layoutPadding)
.listRowBackground(theme.primaryBackgroundColor)
2022-12-19 06:17:01 +00:00
}
}