Don't Ddos servers for fetching each relatinoship individually

This commit is contained in:
Nathan Mattes 2023-10-23 12:18:03 +02:00
parent fa34df26df
commit 19d67d6dab
7 changed files with 52 additions and 40 deletions

View File

@ -12,7 +12,7 @@ import MastodonSDK
enum UserItem: Hashable {
case user(record: ManagedObjectRecord<MastodonUser>)
case account(account: Mastodon.Entity.Account)
case account(account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?)
case bottomLoader
case bottomHeader(text: String)
}

View File

@ -31,39 +31,11 @@ extension UserSection {
return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
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
cell.configure(tableView: tableView, account: account, delegate: userTableViewCellDelegate)
cell.userView.setButtonState(.loading)
Task {
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)
}
}
}
cell.configure(tableView: tableView, account: account, relationship: relationship, delegate: userTableViewCellDelegate)
return cell

View File

@ -9,6 +9,7 @@ import UIKit
import MastodonAsset
import MastodonCore
import MastodonLocalization
import MastodonSDK
extension FollowingListViewModel {
func setupDiffableDataSource(
@ -37,7 +38,14 @@ extension FollowingListViewModel {
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
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)
if let currentState = self.stateMachine.currentState {

View File

@ -126,24 +126,34 @@ extension FollowingListViewModel.State {
Task {
do {
let response = try await viewModel.context.apiService.following(
let accountResponse = try await viewModel.context.apiService.following(
userID: userID,
maxID: maxID,
authenticationBox: viewModel.authContext.mastodonAuthenticationBox
)
var hasNewAppend = false
let newRelationships = try await viewModel.context.apiService.relationship(forAccounts: accountResponse.value, authenticationBox: viewModel.authContext.mastodonAuthenticationBox)
var accounts = viewModel.accounts
for user in response.value {
for user in accountResponse.value {
guard accounts.contains(user) == false else { continue }
accounts.append(user)
hasNewAppend = true
}
var relationships = viewModel.relationships
for relationship in newRelationships.value {
guard relationships.contains(relationship) == false else { continue }
relationships.append(relationship)
}
let maxID = accountResponse.link?.maxID
let maxID = response.link?.maxID
if hasNewAppend, maxID != nil {
await enter(state: Idle.self)
} else {
@ -151,6 +161,7 @@ extension FollowingListViewModel.State {
}
viewModel.accounts = accounts
viewModel.relationships = relationships
self.maxID = maxID
} catch {
await enter(state: Fail.self)

View File

@ -21,6 +21,8 @@ final class FollowingListViewModel {
let context: AppContext
let authContext: AuthContext
@Published var accounts: [Mastodon.Entity.Account]
@Published var relationships: [Mastodon.Entity.Relationship]
let listBatchFetchViewModel: ListBatchFetchViewModel
@Published var domain: String?
@ -52,6 +54,7 @@ final class FollowingListViewModel {
self.domain = domain
self.userID = userID
self.accounts = []
self.relationships = []
self.listBatchFetchViewModel = ListBatchFetchViewModel()
}
}

View File

@ -35,10 +35,28 @@ extension UserTableViewCell {
me: MastodonUser? = nil,
tableView: UITableView,
account: Mastodon.Entity.Account,
relationship: Mastodon.Entity.Relationship?,
delegate: UserTableViewCellDelegate?
) {
//TODO: Implement
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)
}

View File

@ -16,7 +16,7 @@ extension Mastodon.Entity {
/// 2021/1/29
/// # Reference
/// [Document](https://docs.joinmastodon.org/entities/relationship/)
public struct Relationship: Codable, Sendable {
public struct Relationship: Codable, Sendable, Equatable, Hashable {
public typealias ID = String
public let id: ID