IceCubesApp/Packages/Account/Sources/Account/AccountDetailView.swift

139 lines
4 KiB
Swift
Raw Normal View History

2022-11-29 11:18:06 +00:00
import SwiftUI
import Models
import Network
2022-12-18 19:30:19 +00:00
import Status
import Shimmer
import DesignSystem
import Routeur
2022-11-29 11:18:06 +00:00
public struct AccountDetailView: View {
2022-12-20 19:33:45 +00:00
@Environment(\.redactionReasons) private var reasons
2022-11-29 11:18:06 +00:00
@EnvironmentObject private var client: Client
@EnvironmentObject private var routeurPath: RouterPath
2022-11-29 11:18:06 +00:00
@StateObject private var viewModel: AccountDetailViewModel
2022-12-20 08:37:07 +00:00
@State private var scrollOffset: CGFloat = 0
2022-11-29 11:18:06 +00:00
2022-12-20 15:08:09 +00:00
private let isCurrentUser: Bool
/// When coming from a URL like a mention tap in a status.
2022-11-29 11:18:06 +00:00
public init(accountId: String) {
_viewModel = StateObject(wrappedValue: .init(accountId: accountId))
2022-12-20 15:08:09 +00:00
isCurrentUser = false
2022-11-29 11:18:06 +00:00
}
/// When the account is already fetched by the parent caller.
2022-12-20 15:08:09 +00:00
public init(account: Account, isCurrentUser: Bool = false) {
2022-12-20 16:11:12 +00:00
_viewModel = StateObject(wrappedValue: .init(account: account,
isCurrentUser: isCurrentUser))
2022-12-20 15:08:09 +00:00
self.isCurrentUser = isCurrentUser
2022-12-17 12:37:46 +00:00
}
2022-11-29 11:18:06 +00:00
public var body: some View {
2022-12-20 08:37:07 +00:00
ScrollViewOffsetReader { offset in
self.scrollOffset = offset
} content: {
2022-12-17 12:37:46 +00:00
LazyVStack {
2022-12-18 19:30:19 +00:00
headerView
if isCurrentUser {
Picker("", selection: $viewModel.selectedTab) {
ForEach(AccountDetailViewModel.Tab.allCases, id: \.self) { tab in
Text(tab.title).tag(tab)
}
}
.pickerStyle(.segmented)
.padding(.horizontal, DS.Constants.layoutPadding)
2022-12-20 08:37:07 +00:00
.offset(y: -20)
} else {
Divider()
.offset(y: -20)
}
switch viewModel.tabState {
case .statuses:
StatusesListView(fetcher: viewModel)
case let .followedTags(tags):
makeTagsListView(tags: tags)
}
2022-11-29 11:18:06 +00:00
}
}
.task {
2022-12-20 19:33:45 +00:00
guard reasons != .placeholder else { return }
2022-11-29 11:18:06 +00:00
viewModel.client = client
await viewModel.fetchAccount()
2022-12-20 15:08:09 +00:00
if viewModel.statuses.isEmpty {
await viewModel.fetchStatuses()
}
}
.refreshable {
Task {
await viewModel.fetchAccount()
await viewModel.fetchStatuses()
}
2022-12-18 19:30:19 +00:00
}
2022-12-20 08:37:07 +00:00
.edgesIgnoringSafeArea(.top)
.navigationTitle(Text(scrollOffset < -20 ? viewModel.title : ""))
2022-12-18 19:30:19 +00:00
}
@ViewBuilder
private var headerView: some View {
switch viewModel.accountState {
2022-12-18 19:30:19 +00:00
case .loading:
2022-12-20 16:11:12 +00:00
AccountDetailHeaderView(isCurrentUser: isCurrentUser,
account: .placeholder(),
relationship: .constant(.placeholder()),
2022-12-21 11:47:07 +00:00
following: .constant(false),
scrollOffset: $scrollOffset)
2022-12-18 19:30:19 +00:00
.redacted(reason: .placeholder)
case let .data(account):
2022-12-20 16:11:12 +00:00
AccountDetailHeaderView(isCurrentUser: isCurrentUser,
account: account,
relationship: $viewModel.relationship,
following:
.init(get: {
viewModel.relationship?.following ?? false
}, set: { following in
Task {
if following {
await viewModel.follow()
} else {
await viewModel.unfollow()
}
}
2022-12-21 11:47:07 +00:00
}),
scrollOffset: $scrollOffset)
2022-12-18 19:30:19 +00:00
case let .error(error):
Text("Error: \(error.localizedDescription)")
}
}
private func makeTagsListView(tags: [Tag]) -> some View {
Group {
ForEach(tags) { tag in
HStack {
VStack(alignment: .leading) {
Text("#\(tag.name)")
.font(.headline)
2022-12-21 11:39:29 +00:00
Text("\(tag.totalUses) posts from \(tag.totalAccounts) participants")
.font(.footnote)
.foregroundColor(.gray)
}
Spacer()
}
.padding(.horizontal, DS.Constants.layoutPadding)
.padding(.vertical, 8)
.onTapGesture {
routeurPath.navigate(to: .hashTag(tag: tag.name))
}
}
}
}
2022-12-17 12:37:46 +00:00
}
struct AccountDetailView_Previews: PreviewProvider {
static var previews: some View {
AccountDetailView(account: .placeholder())
2022-11-29 11:18:06 +00:00
}
}
2022-12-17 12:37:46 +00:00