IceCubesApp/Packages/Account/Sources/Account/AccountsList/AccountsListView.swift

156 lines
4.1 KiB
Swift
Raw Normal View History

2023-01-17 10:36:01 +00:00
import DesignSystem
2022-12-23 17:47:19 +00:00
import Env
2023-01-17 10:36:01 +00:00
import Models
import Network
import SwiftUI
2022-12-23 17:47:19 +00:00
2023-09-18 19:03:52 +00:00
@MainActor
2022-12-23 17:47:19 +00:00
public struct AccountsListView: View {
2023-09-18 19:03:52 +00:00
@Environment(Theme.self) private var theme
@Environment(Client.self) private var client
@Environment(CurrentAccount.self) private var currentAccount
@State private var viewModel: AccountsListViewModel
2022-12-23 17:47:19 +00:00
@State private var didAppear: Bool = false
2023-01-17 10:36:01 +00:00
2022-12-24 12:41:25 +00:00
public init(mode: AccountsListMode) {
_viewModel = .init(initialValue: .init(mode: mode))
2022-12-23 17:47:19 +00:00
}
2023-01-17 10:36:01 +00:00
2022-12-23 17:47:19 +00:00
public var body: some View {
2024-01-09 12:28:51 +00:00
listView
#if !os(visionOS)
2022-12-29 09:39:34 +00:00
.scrollContentBackground(.hidden)
.background(theme.primaryBackgroundColor)
#endif
2022-12-23 17:47:19 +00:00
.listStyle(.plain)
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text(viewModel.mode.title)
.font(.headline)
if let count = viewModel.totalCount {
Text(String(count))
.font(.footnote)
.foregroundStyle(.secondary)
}
}
}
}
2022-12-24 12:41:25 +00:00
.navigationTitle(viewModel.mode.title)
2022-12-23 17:47:19 +00:00
.navigationBarTitleDisplayMode(.inline)
.task {
viewModel.client = client
2023-01-17 10:36:01 +00:00
guard !didAppear else { return }
2022-12-23 17:47:19 +00:00
didAppear = true
await viewModel.fetch()
}
}
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
@ViewBuilder
private var listView: some View {
if currentAccount.account?.id == viewModel.accountId {
searchableList
} else {
standardList
}
}
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
private var searchableList: some View {
List {
listContent
}
.searchable(text: $viewModel.searchQuery,
placement: .navigationBarDrawer(displayMode: .always))
.task(id: viewModel.searchQuery) {
if !viewModel.searchQuery.isEmpty {
await viewModel.search()
}
}
.onChange(of: viewModel.searchQuery) { _, newValue in
if newValue.isEmpty {
Task {
await viewModel.fetch()
}
}
}
}
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
private var standardList: some View {
List {
listContent
}
}
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
@ViewBuilder
private var listContent: some View {
switch viewModel.state {
case .loading:
ForEach(Account.placeholders()) { _ in
AccountsListRow(viewModel: .init(account: .placeholder(), relationShip: .placeholder()))
.redacted(reason: .placeholder)
.allowsHitTesting(false)
2024-02-14 11:48:14 +00:00
#if !os(visionOS)
2024-01-09 12:28:51 +00:00
.listRowBackground(theme.primaryBackgroundColor)
2024-02-14 11:48:14 +00:00
#endif
2024-01-09 12:28:51 +00:00
}
case let .display(accounts, relationships, nextPageState):
if case .followers = viewModel.mode,
!currentAccount.followRequests.isEmpty
{
Section(
header: Text("account.follow-requests.pending-requests"),
footer: Text("account.follow-requests.instructions")
.font(.scaledFootnote)
.foregroundColor(.secondary)
.offset(y: -8)
) {
ForEach(currentAccount.followRequests) { account in
AccountsListRow(
viewModel: .init(account: account),
isFollowRequest: true,
requestUpdated: {
Task {
await viewModel.fetch()
}
}
)
#if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor)
#endif
}
}
}
Section {
ForEach(accounts) { account in
if let relationship = relationships.first(where: { $0.id == account.id }) {
AccountsListRow(viewModel: .init(account: account,
relationShip: relationship))
2024-02-14 11:48:14 +00:00
#if !os(visionOS)
2024-01-09 12:28:51 +00:00
.listRowBackground(theme.primaryBackgroundColor)
2024-02-14 11:48:14 +00:00
#endif
2024-01-09 12:28:51 +00:00
}
}
}
switch nextPageState {
case .hasNextPage:
NextPageView {
try await viewModel.fetchNextPage()
}
#if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor)
#endif
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
case .none:
EmptyView()
}
case let .error(error):
Text(error.localizedDescription)
2024-02-14 11:48:14 +00:00
#if !os(visionOS)
2024-01-09 12:28:51 +00:00
.listRowBackground(theme.primaryBackgroundColor)
2024-02-14 11:48:14 +00:00
#endif
2024-01-09 12:28:51 +00:00
}
}
2022-12-23 17:47:19 +00:00
}