Don't Ddos servers for fetching each relatinoship individually
This commit is contained in:
parent
fa34df26df
commit
19d67d6dab
|
@ -12,7 +12,7 @@ import MastodonSDK
|
||||||
|
|
||||||
enum UserItem: Hashable {
|
enum UserItem: Hashable {
|
||||||
case user(record: ManagedObjectRecord<MastodonUser>)
|
case user(record: ManagedObjectRecord<MastodonUser>)
|
||||||
case account(account: Mastodon.Entity.Account)
|
case account(account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?)
|
||||||
case bottomLoader
|
case bottomLoader
|
||||||
case bottomHeader(text: String)
|
case bottomHeader(text: String)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,39 +31,11 @@ extension UserSection {
|
||||||
|
|
||||||
return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
|
return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
|
||||||
switch item {
|
switch item {
|
||||||
case .account(let account):
|
case .account(let account, let relationship):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
|
||||||
cell.configure(tableView: tableView, account: account, delegate: userTableViewCellDelegate)
|
|
||||||
cell.userView.setButtonState(.loading)
|
cell.userView.setButtonState(.loading)
|
||||||
Task {
|
cell.configure(tableView: tableView, account: account, relationship: relationship, delegate: userTableViewCellDelegate)
|
||||||
do {
|
|
||||||
|
|
||||||
guard let relationship = try await context.apiService.relationship(forAccounts: [account], authenticationBox: authContext.mastodonAuthenticationBox).value.first else {
|
|
||||||
return await MainActor.run {
|
|
||||||
cell.userView.setButtonState(.none)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let buttonState: UserView.ButtonState
|
|
||||||
if relationship.following {
|
|
||||||
buttonState = .unfollow
|
|
||||||
} else if relationship.blocking || (relationship.domainBlocking ?? false) {
|
|
||||||
buttonState = .blocked
|
|
||||||
} else if relationship.requested ?? false {
|
|
||||||
buttonState = .pending
|
|
||||||
} else {
|
|
||||||
buttonState = .follow
|
|
||||||
}
|
|
||||||
|
|
||||||
await MainActor.run {
|
|
||||||
cell.userView.setButtonState(buttonState)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
await MainActor.run {
|
|
||||||
cell.userView.setButtonState(.none)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import UIKit
|
||||||
import MastodonAsset
|
import MastodonAsset
|
||||||
import MastodonCore
|
import MastodonCore
|
||||||
import MastodonLocalization
|
import MastodonLocalization
|
||||||
|
import MastodonSDK
|
||||||
|
|
||||||
extension FollowingListViewModel {
|
extension FollowingListViewModel {
|
||||||
func setupDiffableDataSource(
|
func setupDiffableDataSource(
|
||||||
|
@ -37,7 +38,14 @@ extension FollowingListViewModel {
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
|
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
|
||||||
snapshot.appendSections([.main])
|
snapshot.appendSections([.main])
|
||||||
let items = accounts.map { UserItem.account(account: $0) }
|
|
||||||
|
let accountsWithRelationship: [(account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?)] = accounts.compactMap { account in
|
||||||
|
guard let relationship = self.relationships.first(where: {$0.id == account.id }) else { return (account: account, relationship: nil)}
|
||||||
|
|
||||||
|
return (account: account, relationship: relationship)
|
||||||
|
}
|
||||||
|
|
||||||
|
let items = accountsWithRelationship.map { UserItem.account(account: $0.account, relationship: $0.relationship) }
|
||||||
snapshot.appendItems(items, toSection: .main)
|
snapshot.appendItems(items, toSection: .main)
|
||||||
|
|
||||||
if let currentState = self.stateMachine.currentState {
|
if let currentState = self.stateMachine.currentState {
|
||||||
|
|
|
@ -126,23 +126,33 @@ extension FollowingListViewModel.State {
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let response = try await viewModel.context.apiService.following(
|
let accountResponse = try await viewModel.context.apiService.following(
|
||||||
userID: userID,
|
userID: userID,
|
||||||
maxID: maxID,
|
maxID: maxID,
|
||||||
authenticationBox: viewModel.authContext.mastodonAuthenticationBox
|
authenticationBox: viewModel.authContext.mastodonAuthenticationBox
|
||||||
)
|
)
|
||||||
|
|
||||||
var hasNewAppend = false
|
var hasNewAppend = false
|
||||||
|
|
||||||
|
|
||||||
|
let newRelationships = try await viewModel.context.apiService.relationship(forAccounts: accountResponse.value, authenticationBox: viewModel.authContext.mastodonAuthenticationBox)
|
||||||
|
|
||||||
var accounts = viewModel.accounts
|
var accounts = viewModel.accounts
|
||||||
|
|
||||||
for user in response.value {
|
for user in accountResponse.value {
|
||||||
guard accounts.contains(user) == false else { continue }
|
guard accounts.contains(user) == false else { continue }
|
||||||
accounts.append(user)
|
accounts.append(user)
|
||||||
hasNewAppend = true
|
hasNewAppend = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var relationships = viewModel.relationships
|
||||||
|
|
||||||
let maxID = response.link?.maxID
|
for relationship in newRelationships.value {
|
||||||
|
guard relationships.contains(relationship) == false else { continue }
|
||||||
|
relationships.append(relationship)
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxID = accountResponse.link?.maxID
|
||||||
|
|
||||||
if hasNewAppend, maxID != nil {
|
if hasNewAppend, maxID != nil {
|
||||||
await enter(state: Idle.self)
|
await enter(state: Idle.self)
|
||||||
|
@ -151,6 +161,7 @@ extension FollowingListViewModel.State {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.accounts = accounts
|
viewModel.accounts = accounts
|
||||||
|
viewModel.relationships = relationships
|
||||||
self.maxID = maxID
|
self.maxID = maxID
|
||||||
} catch {
|
} catch {
|
||||||
await enter(state: Fail.self)
|
await enter(state: Fail.self)
|
||||||
|
|
|
@ -21,6 +21,8 @@ final class FollowingListViewModel {
|
||||||
let context: AppContext
|
let context: AppContext
|
||||||
let authContext: AuthContext
|
let authContext: AuthContext
|
||||||
@Published var accounts: [Mastodon.Entity.Account]
|
@Published var accounts: [Mastodon.Entity.Account]
|
||||||
|
@Published var relationships: [Mastodon.Entity.Relationship]
|
||||||
|
|
||||||
let listBatchFetchViewModel: ListBatchFetchViewModel
|
let listBatchFetchViewModel: ListBatchFetchViewModel
|
||||||
|
|
||||||
@Published var domain: String?
|
@Published var domain: String?
|
||||||
|
@ -52,6 +54,7 @@ final class FollowingListViewModel {
|
||||||
self.domain = domain
|
self.domain = domain
|
||||||
self.userID = userID
|
self.userID = userID
|
||||||
self.accounts = []
|
self.accounts = []
|
||||||
|
self.relationships = []
|
||||||
self.listBatchFetchViewModel = ListBatchFetchViewModel()
|
self.listBatchFetchViewModel = ListBatchFetchViewModel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,28 @@ extension UserTableViewCell {
|
||||||
me: MastodonUser? = nil,
|
me: MastodonUser? = nil,
|
||||||
tableView: UITableView,
|
tableView: UITableView,
|
||||||
account: Mastodon.Entity.Account,
|
account: Mastodon.Entity.Account,
|
||||||
|
relationship: Mastodon.Entity.Relationship?,
|
||||||
delegate: UserTableViewCellDelegate?
|
delegate: UserTableViewCellDelegate?
|
||||||
) {
|
) {
|
||||||
//TODO: Implement
|
//TODO: Implement
|
||||||
userView.configure(with: account)
|
userView.configure(with: account)
|
||||||
|
|
||||||
|
let buttonState: UserView.ButtonState
|
||||||
|
if let relationship {
|
||||||
|
if relationship.following {
|
||||||
|
buttonState = .unfollow
|
||||||
|
} else if relationship.blocking || (relationship.domainBlocking ?? false) {
|
||||||
|
buttonState = .blocked
|
||||||
|
} else if relationship.requested ?? false {
|
||||||
|
buttonState = .pending
|
||||||
|
} else {
|
||||||
|
buttonState = .follow
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buttonState = .none
|
||||||
|
}
|
||||||
|
|
||||||
|
userView.setButtonState(buttonState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ extension Mastodon.Entity {
|
||||||
/// 2021/1/29
|
/// 2021/1/29
|
||||||
/// # Reference
|
/// # Reference
|
||||||
/// [Document](https://docs.joinmastodon.org/entities/relationship/)
|
/// [Document](https://docs.joinmastodon.org/entities/relationship/)
|
||||||
public struct Relationship: Codable, Sendable {
|
public struct Relationship: Codable, Sendable, Equatable, Hashable {
|
||||||
public typealias ID = String
|
public typealias ID = String
|
||||||
|
|
||||||
public let id: ID
|
public let id: ID
|
||||||
|
|
Loading…
Reference in New Issue