2022-12-17 12:37:46 +00:00
|
|
|
import SwiftUI
|
|
|
|
import Models
|
2022-12-18 19:30:19 +00:00
|
|
|
import DesignSystem
|
2022-12-22 09:53:36 +00:00
|
|
|
import Env
|
2022-12-25 06:43:02 +00:00
|
|
|
import Shimmer
|
|
|
|
import NukeUI
|
2023-01-12 05:58:04 +00:00
|
|
|
import EmojiText
|
2022-12-17 12:37:46 +00:00
|
|
|
|
|
|
|
struct AccountDetailHeaderView: View {
|
2022-12-24 14:09:17 +00:00
|
|
|
@EnvironmentObject private var theme: Theme
|
2022-12-22 09:56:24 +00:00
|
|
|
@EnvironmentObject private var quickLook: QuickLook
|
2022-12-20 08:37:07 +00:00
|
|
|
@EnvironmentObject private var routeurPath: RouterPath
|
2022-12-17 12:37:46 +00:00
|
|
|
@Environment(\.redactionReasons) private var reasons
|
|
|
|
|
2023-01-12 06:36:19 +00:00
|
|
|
@ObservedObject var viewModel: AccountDetailViewModel
|
2022-12-20 08:37:07 +00:00
|
|
|
let account: Account
|
2022-12-27 08:11:12 +00:00
|
|
|
let scrollViewProxy: ScrollViewProxy?
|
2022-12-23 15:21:31 +00:00
|
|
|
|
2022-12-21 11:47:07 +00:00
|
|
|
@Binding var scrollOffset: CGFloat
|
|
|
|
|
|
|
|
private var bannerHeight: CGFloat {
|
|
|
|
200 + (scrollOffset > 0 ? scrollOffset * 2 : 0)
|
|
|
|
}
|
2022-12-20 08:37:07 +00:00
|
|
|
|
2022-12-17 12:37:46 +00:00
|
|
|
var body: some View {
|
|
|
|
VStack(alignment: .leading) {
|
|
|
|
headerImageView
|
|
|
|
accountInfoView
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private var headerImageView: some View {
|
2022-12-20 08:37:07 +00:00
|
|
|
GeometryReader { proxy in
|
2022-12-20 16:11:12 +00:00
|
|
|
ZStack(alignment: .bottomTrailing) {
|
2023-01-06 11:14:05 +00:00
|
|
|
if reasons.contains(.placeholder) {
|
|
|
|
Rectangle()
|
|
|
|
.foregroundColor(.gray)
|
|
|
|
.frame(height: bannerHeight)
|
|
|
|
} else {
|
|
|
|
LazyImage(url: account.header) { state in
|
|
|
|
if let image = state.image {
|
|
|
|
image
|
|
|
|
.resizingMode(.aspectFill)
|
2023-01-09 17:57:31 +00:00
|
|
|
.overlay(.black.opacity(0.50))
|
2023-01-06 11:14:05 +00:00
|
|
|
} else if state.isLoading {
|
|
|
|
Color.gray
|
|
|
|
.frame(height: bannerHeight)
|
|
|
|
.shimmering()
|
|
|
|
} else {
|
|
|
|
Color.gray
|
|
|
|
.frame(height: bannerHeight)
|
|
|
|
}
|
2022-12-20 16:11:12 +00:00
|
|
|
}
|
2023-01-06 11:14:05 +00:00
|
|
|
.frame(height: bannerHeight)
|
2022-12-25 06:43:02 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 06:36:19 +00:00
|
|
|
if viewModel.relationship?.followedBy == true {
|
2022-12-20 16:11:12 +00:00
|
|
|
Text("Follows You")
|
|
|
|
.font(.footnote)
|
|
|
|
.fontWeight(.semibold)
|
|
|
|
.padding(4)
|
|
|
|
.background(.ultraThinMaterial)
|
|
|
|
.cornerRadius(4)
|
|
|
|
.padding(8)
|
2022-12-20 08:37:07 +00:00
|
|
|
}
|
2022-12-20 16:11:12 +00:00
|
|
|
}
|
2022-12-20 08:37:07 +00:00
|
|
|
.background(Color.gray)
|
|
|
|
}
|
2022-12-21 11:47:07 +00:00
|
|
|
.frame(height: bannerHeight)
|
|
|
|
.offset(y: scrollOffset > 0 ? -scrollOffset : 0)
|
2022-12-20 08:37:07 +00:00
|
|
|
.contentShape(Rectangle())
|
|
|
|
.onTapGesture {
|
2022-12-22 09:56:24 +00:00
|
|
|
Task {
|
|
|
|
await quickLook.prepareFor(urls: [account.header], selectedURL: account.header)
|
|
|
|
}
|
2022-12-20 08:37:07 +00:00
|
|
|
}
|
2022-12-17 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private var accountAvatarView: some View {
|
|
|
|
HStack {
|
2022-12-23 09:41:55 +00:00
|
|
|
AvatarView(url: account.avatar, size: .account)
|
2022-12-20 08:37:07 +00:00
|
|
|
.onTapGesture {
|
2022-12-22 09:56:24 +00:00
|
|
|
Task {
|
|
|
|
await quickLook.prepareFor(urls: [account.avatar], selectedURL: account.avatar)
|
|
|
|
}
|
2022-12-20 08:37:07 +00:00
|
|
|
}
|
2022-12-17 12:37:46 +00:00
|
|
|
Spacer()
|
|
|
|
Group {
|
2022-12-27 08:11:12 +00:00
|
|
|
Button {
|
|
|
|
withAnimation {
|
|
|
|
scrollViewProxy?.scrollTo("status", anchor: .top)
|
|
|
|
}
|
|
|
|
} label: {
|
|
|
|
makeCustomInfoLabel(title: "Posts", count: account.statusesCount)
|
|
|
|
}
|
2022-12-23 17:47:19 +00:00
|
|
|
NavigationLink(value: RouteurDestinations.following(id: account.id)) {
|
|
|
|
makeCustomInfoLabel(title: "Following", count: account.followingCount)
|
|
|
|
}
|
|
|
|
NavigationLink(value: RouteurDestinations.followers(id: account.id)) {
|
|
|
|
makeCustomInfoLabel(title: "Followers", count: account.followersCount)
|
|
|
|
}
|
2022-12-17 12:37:46 +00:00
|
|
|
}.offset(y: 20)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private var accountInfoView: some View {
|
|
|
|
Group {
|
|
|
|
accountAvatarView
|
2022-12-20 16:11:12 +00:00
|
|
|
HStack {
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
2023-01-12 20:12:47 +00:00
|
|
|
EmojiTextApp(account.safeDisplayName.asMarkdown, emojis: account.emojis)
|
2022-12-20 16:11:12 +00:00
|
|
|
.font(.headline)
|
2022-12-24 12:41:25 +00:00
|
|
|
Text("@\(account.acct)")
|
2022-12-20 16:11:12 +00:00
|
|
|
.font(.callout)
|
|
|
|
.foregroundColor(.gray)
|
|
|
|
}
|
|
|
|
Spacer()
|
2023-01-12 06:36:19 +00:00
|
|
|
if let relationship = viewModel.relationship, !viewModel.isCurrentUser {
|
|
|
|
HStack {
|
|
|
|
FollowButton(viewModel: .init(accountId: account.id,
|
2023-01-12 07:30:47 +00:00
|
|
|
relationship: relationship,
|
|
|
|
shouldDisplayNotify: true))
|
2023-01-12 06:36:19 +00:00
|
|
|
}
|
2022-12-20 16:11:12 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-12 20:12:47 +00:00
|
|
|
EmojiTextApp(account.note.asMarkdown, emojis: account.emojis)
|
2022-12-17 12:37:46 +00:00
|
|
|
.font(.body)
|
|
|
|
.padding(.top, 8)
|
2022-12-23 14:28:22 +00:00
|
|
|
.environment(\.openURL, OpenURLAction { url in
|
|
|
|
routeurPath.handle(url: url)
|
|
|
|
})
|
2022-12-17 12:37:46 +00:00
|
|
|
}
|
2023-01-03 06:41:29 +00:00
|
|
|
.padding(.horizontal, .layoutPadding)
|
2022-12-17 12:37:46 +00:00
|
|
|
.offset(y: -40)
|
|
|
|
}
|
|
|
|
|
|
|
|
private func makeCustomInfoLabel(title: String, count: Int) -> some View {
|
|
|
|
VStack {
|
2022-12-18 19:30:19 +00:00
|
|
|
Text("\(count)")
|
|
|
|
.font(.headline)
|
2022-12-24 14:09:17 +00:00
|
|
|
.foregroundColor(theme.tintColor)
|
2022-12-17 12:37:46 +00:00
|
|
|
Text(title)
|
|
|
|
.font(.footnote)
|
|
|
|
.foregroundColor(.gray)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct AccountDetailHeaderView_Previews: PreviewProvider {
|
|
|
|
static var previews: some View {
|
2023-01-12 06:36:19 +00:00
|
|
|
AccountDetailHeaderView(viewModel: .init(account: .placeholder()),
|
2022-12-20 16:11:12 +00:00
|
|
|
account: .placeholder(),
|
2022-12-27 08:11:12 +00:00
|
|
|
scrollViewProxy: nil,
|
2022-12-21 11:47:07 +00:00
|
|
|
scrollOffset: .constant(0))
|
2022-12-17 12:37:46 +00:00
|
|
|
}
|
|
|
|
}
|