mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-22 08:20:59 +00:00
Account detail: Add also followed by section
This commit is contained in:
parent
084dd18362
commit
fc77dd14fe
5 changed files with 94 additions and 25 deletions
|
@ -34,8 +34,10 @@ public struct AccountDetailView: View {
|
|||
ScrollViewOffsetReader { offset in
|
||||
self.scrollOffset = offset
|
||||
} content: {
|
||||
LazyVStack {
|
||||
LazyVStack(alignment: .leading) {
|
||||
headerView
|
||||
familliarFollowers
|
||||
.offset(y: -36)
|
||||
featuredTagsView
|
||||
.offset(y: -36)
|
||||
if isCurrentUser {
|
||||
|
@ -151,6 +153,31 @@ public struct AccountDetailView: View {
|
|||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var familliarFollowers: some View {
|
||||
if !viewModel.familliarFollowers.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text("Also followed by")
|
||||
.font(.headline)
|
||||
.padding(.leading, DS.Constants.layoutPadding)
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
LazyHStack(spacing: 0) {
|
||||
ForEach(viewModel.familliarFollowers) { account in
|
||||
AvatarView(url: account.avatar, size: .badge)
|
||||
.onTapGesture {
|
||||
routeurPath.navigate(to: .accountDetailWithAccount(account: account))
|
||||
}
|
||||
.padding(.leading, -4)
|
||||
}
|
||||
}
|
||||
.padding(.leading, DS.Constants.layoutPadding + 4)
|
||||
}
|
||||
}
|
||||
.padding(.top, 2)
|
||||
.padding(.bottom, 12)
|
||||
}
|
||||
}
|
||||
|
||||
private var fieldSheetView: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
|
|
|
@ -50,6 +50,7 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
|||
@Published var followedTags: [Tag] = []
|
||||
@Published var featuredTags: [FeaturedTag] = []
|
||||
@Published var fields: [Account.Field] = []
|
||||
@Published var familliarFollowers: [Account] = []
|
||||
@Published var selectedTab = Tab.statuses {
|
||||
didSet {
|
||||
reloadTabState()
|
||||
|
@ -77,18 +78,25 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
|||
func fetchAccount() async {
|
||||
guard let client else { return }
|
||||
do {
|
||||
let account: Account = try await client.get(endpoint: Accounts.accounts(id: accountId))
|
||||
self.fields = account.fields
|
||||
if isCurrentUser {
|
||||
self.followedTags = try await client.get(endpoint: Accounts.followedTags)
|
||||
} else {
|
||||
let relationships: [Relationshionship] = try await client.get(endpoint: Accounts.relationships(id: accountId))
|
||||
self.relationship = relationships.first
|
||||
}
|
||||
self.featuredTags = try await client.get(endpoint: Accounts.featuredTags(id: accountId))
|
||||
async let account: Account = client.get(endpoint: Accounts.accounts(id: accountId))
|
||||
async let followedTags: [Tag] = client.get(endpoint: Accounts.followedTags)
|
||||
async let relationships: [Relationshionship] = client.get(endpoint: Accounts.relationships(id: accountId))
|
||||
async let featuredTags: [FeaturedTag] = client.get(endpoint: Accounts.featuredTags(id: accountId))
|
||||
async let familliarFollowers: [FamilliarAccounts] = client.get(endpoint: Accounts.familiarFollowers(withAccount: accountId))
|
||||
let loadedAccount = try await account
|
||||
self.featuredTags = try await featuredTags
|
||||
self.featuredTags.sort { $0.statusesCountInt > $1.statusesCountInt }
|
||||
self.title = account.displayName
|
||||
accountState = .data(account: account)
|
||||
self.fields = loadedAccount.fields
|
||||
self.title = loadedAccount.displayName
|
||||
if isCurrentUser {
|
||||
self.followedTags = try await followedTags
|
||||
} else {
|
||||
let relationships = try await relationships
|
||||
self.relationship = relationships.first
|
||||
self.familliarFollowers = try await familliarFollowers.first?.accounts ?? []
|
||||
}
|
||||
self.account = loadedAccount
|
||||
accountState = .data(account: loadedAccount)
|
||||
} catch {
|
||||
accountState = .error(error: error)
|
||||
}
|
||||
|
|
|
@ -1,32 +1,56 @@
|
|||
import SwiftUI
|
||||
|
||||
public struct AvatarView: View {
|
||||
public enum Size {
|
||||
case profile, badge
|
||||
|
||||
var size: CGSize {
|
||||
switch self {
|
||||
case .profile:
|
||||
return .init(width: 40, height: 40)
|
||||
case .badge:
|
||||
return .init(width: 28, height: 28)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Environment(\.redactionReasons) private var reasons
|
||||
public let url: URL
|
||||
public let size: Size
|
||||
|
||||
public init(url: URL) {
|
||||
public init(url: URL, size: Size = .profile) {
|
||||
self.url = url
|
||||
self.size = size
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
if reasons == .placeholder {
|
||||
RoundedRectangle(cornerRadius: 4)
|
||||
RoundedRectangle(cornerRadius: size == .profile ? 4 : size.size.width / 2)
|
||||
.fill(.gray)
|
||||
.frame(maxWidth: 40, maxHeight: 40)
|
||||
.frame(maxWidth: size.size.width, maxHeight: size.size.height)
|
||||
} else {
|
||||
AsyncImage(
|
||||
url: url,
|
||||
content: { image in
|
||||
AsyncImage(url: url) { phase in
|
||||
switch phase {
|
||||
case .empty:
|
||||
if size == .badge {
|
||||
Circle()
|
||||
.fill(.gray)
|
||||
.frame(maxWidth: size.size.width, maxHeight: size.size.height)
|
||||
} else {
|
||||
ProgressView()
|
||||
.frame(maxWidth: size.size.width, maxHeight: size.size.height)
|
||||
}
|
||||
case let .success(image):
|
||||
image.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.cornerRadius(4)
|
||||
.frame(maxWidth: 40, maxHeight: 40)
|
||||
},
|
||||
placeholder: {
|
||||
ProgressView()
|
||||
.frame(maxWidth: 40, maxHeight: 40)
|
||||
.cornerRadius(size == .profile ? 4 : size.size.width / 2)
|
||||
.frame(maxWidth: size.size.width, maxHeight: size.size.height)
|
||||
case .failure:
|
||||
EmptyView()
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,3 +49,8 @@ public struct Account: Codable, Identifiable, Equatable, Hashable {
|
|||
emojis: [])
|
||||
}
|
||||
}
|
||||
|
||||
public struct FamilliarAccounts: Codable {
|
||||
public let id: String
|
||||
public let accounts: [Account]
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ public enum Accounts: Endpoint {
|
|||
case relationships(id: String)
|
||||
case follow(id: String)
|
||||
case unfollow(id: String)
|
||||
case familiarFollowers(withAccount: String)
|
||||
|
||||
public func path() -> String {
|
||||
switch self {
|
||||
|
@ -31,6 +32,8 @@ public enum Accounts: Endpoint {
|
|||
return "accounts/\(id)/follow"
|
||||
case .unfollow(let id):
|
||||
return "accounts/\(id)/unfollow"
|
||||
case .familiarFollowers:
|
||||
return "accounts/familiar_followers"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +50,8 @@ public enum Accounts: Endpoint {
|
|||
return params
|
||||
case let .relationships(id):
|
||||
return [.init(name: "id", value: id)]
|
||||
case let .familiarFollowers(withAccount):
|
||||
return [.init(name: "id[]", value: withAccount)]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue