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
|
|
|
|
|
|
|
public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
|
2023-01-30 20:41:42 +00:00
|
|
|
@EnvironmentObject private var theme: Theme
|
2023-03-13 12:38:28 +00:00
|
|
|
|
2022-12-19 06:17:01 +00:00
|
|
|
@ObservedObject private var fetcher: Fetcher
|
2023-07-03 05:40:49 +00:00
|
|
|
// Whether this status is on a remote local timeline (many actions are unavailable if so)
|
2023-01-06 11:14:05 +00:00
|
|
|
private let isRemote: Bool
|
2023-02-15 07:46:14 +00:00
|
|
|
private let routerPath: RouterPath
|
|
|
|
private let client: Client
|
2023-03-13 12:38:28 +00:00
|
|
|
|
2023-03-01 18:27:56 +00:00
|
|
|
public init(fetcher: Fetcher,
|
|
|
|
client: Client,
|
|
|
|
routerPath: RouterPath,
|
2023-03-13 12:38:28 +00:00
|
|
|
isRemote: Bool = false)
|
|
|
|
{
|
2022-12-19 06:17:01 +00:00
|
|
|
self.fetcher = fetcher
|
2023-01-06 11:14:05 +00:00
|
|
|
self.isRemote = isRemote
|
2023-02-15 07:46:14 +00:00
|
|
|
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 {
|
2023-01-30 20:41:42 +00:00
|
|
|
switch fetcher.statusesState {
|
|
|
|
case .loading:
|
|
|
|
ForEach(Status.placeholders()) { status in
|
2023-02-24 12:25:21 +00:00
|
|
|
StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
|
2023-01-30 20:41:42 +00:00
|
|
|
.redacted(reason: .placeholder)
|
|
|
|
}
|
|
|
|
case .error:
|
|
|
|
ErrorView(title: "status.error.title",
|
|
|
|
message: "status.error.loading.message",
|
2023-03-13 12:38:28 +00:00
|
|
|
buttonTitle: "action.retry")
|
|
|
|
{
|
2023-01-30 20:41:42 +00:00
|
|
|
Task {
|
2023-02-25 09:10:27 +00:00
|
|
|
await fetcher.fetchNewestStatuses()
|
2023-01-07 17:01:06 +00:00
|
|
|
}
|
2023-01-30 20:41:42 +00:00
|
|
|
}
|
2023-03-13 12:38:28 +00:00
|
|
|
.listRowSeparator(.hidden)
|
|
|
|
|
2023-01-30 20:41:42 +00:00
|
|
|
case let .display(statuses, nextPageState):
|
|
|
|
ForEach(statuses, id: \.viewId) { status in
|
2023-02-24 12:25:21 +00:00
|
|
|
StatusRowView(viewModel: { StatusRowViewModel(status: status,
|
|
|
|
client: client,
|
|
|
|
routerPath: routerPath,
|
|
|
|
isRemote: isRemote)
|
2023-03-13 12:38:28 +00:00
|
|
|
|
|
|
|
})
|
|
|
|
.id(status.id)
|
|
|
|
.onAppear {
|
|
|
|
fetcher.statusDidAppear(status: status)
|
|
|
|
}
|
|
|
|
.onDisappear {
|
|
|
|
fetcher.statusDidDisappear(status: status)
|
|
|
|
}
|
2023-01-30 20:41:42 +00:00
|
|
|
}
|
|
|
|
switch nextPageState {
|
|
|
|
case .hasNextPage:
|
|
|
|
loadingRow
|
|
|
|
.onAppear {
|
|
|
|
Task {
|
|
|
|
await fetcher.fetchNextPage()
|
2022-12-19 06:17:01 +00:00
|
|
|
}
|
2023-01-30 20:41:42 +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)
|
2022-12-19 06:17:01 +00:00
|
|
|
}
|
|
|
|
}
|