Migrate UserList to use Accounts (IOS-192)

This commit is contained in:
Nathan Mattes 2023-12-14 13:48:59 +01:00
parent f51d5b7fe2
commit 3abb80a5df
6 changed files with 66 additions and 39 deletions

View File

@ -7,8 +7,6 @@
import Foundation
import Combine
import CoreData
import CoreDataStack
import GameplayKit
import MastodonSDK
import MastodonCore

View File

@ -21,10 +21,10 @@ extension FavoritedByViewController: DataSourceProvider {
}
switch item {
case .user(let record):
return .user(record: record)
default:
return nil
case .user(_), .bottomHeader(_), .bottomLoader:
return nil
case .account(let account, let relationship):
return .account(account: account, relationship: relationship)
}
}

View File

@ -20,12 +20,12 @@ extension RebloggedByViewController: DataSourceProvider {
guard let item = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else {
return nil
}
switch item {
case .user(let record):
return .user(record: record)
default:
return nil
case .user(_), .bottomHeader(_), .bottomLoader:
return nil
case .account(let account, let relationship):
return .account(account: account, relationship: relationship)
}
}

View File

@ -9,6 +9,7 @@ import UIKit
import MastodonAsset
import MastodonLocalization
import Combine
import MastodonSDK
extension UserListViewModel {
@MainActor
@ -33,15 +34,23 @@ extension UserListViewModel {
// trigger initial loading
stateMachine.enter(UserListViewModel.State.Reloading.self)
userFetchedResultsController.$records
$accounts
.receive(on: DispatchQueue.main)
.sink { [weak self] records in
.sink { [weak self] accounts in
guard let self = self else { return }
guard let diffableDataSource = self.diffableDataSource else { return }
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
snapshot.appendSections([.main])
let items = records.map { UserItem.user(record: $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

@ -30,7 +30,7 @@ extension UserListViewModel {
extension UserListViewModel.State {
class Initial: UserListViewModel.State {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
guard let _ = viewModel else { return false }
guard viewModel != nil else { return false }
switch stateClass {
case is Reloading.Type:
return true
@ -52,10 +52,10 @@ extension UserListViewModel.State {
override func didEnter(from previousState: GKState?) {
super.didEnter(from: previousState)
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
guard let viewModel, let stateMachine else { return }
// reset
viewModel.userFetchedResultsController.userIDs = []
viewModel.accounts = []
stateMachine.enter(Loading.self)
}
@ -74,8 +74,8 @@ extension UserListViewModel.State {
override func didEnter(from previousState: GKState?) {
super.didEnter(from: previousState)
guard let _ = viewModel, let stateMachine = stateMachine else { return }
guard viewModel != nil, let stateMachine else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
stateMachine.enter(Loading.self)
}
@ -117,10 +117,11 @@ extension UserListViewModel.State {
maxID = nil
}
guard let viewModel = viewModel else { return }
guard let viewModel else { return }
let maxID = self.maxID
let authenticationBox = viewModel.authContext.mastodonAuthenticationBox
Task {
do {
let response: Mastodon.Response.Content<[Mastodon.Entity.Account]>
@ -129,24 +130,45 @@ extension UserListViewModel.State {
response = try await viewModel.context.apiService.favoritedBy(
status: status,
query: .init(maxID: maxID, limit: nil),
authenticationBox: viewModel.authContext.mastodonAuthenticationBox
authenticationBox: authenticationBox
)
case .rebloggedBy(let status):
response = try await viewModel.context.apiService.rebloggedBy(
status: status,
query: .init(maxID: maxID, limit: nil),
authenticationBox: viewModel.authContext.mastodonAuthenticationBox
authenticationBox: authenticationBox
)
}
if response.value.isEmpty {
await enter(state: NoMore.self)
viewModel.accounts = []
viewModel.relationships = []
return
}
let newRelationships = try await viewModel.context.apiService.relationship(
forAccounts: response.value,
authenticationBox: authenticationBox
)
var hasNewAppend = false
var userIDs = viewModel.userFetchedResultsController.userIDs
for user in response.value {
guard !userIDs.contains(user.id) else { continue }
userIDs.append(user.id)
var accounts = viewModel.accounts
for account in response.value {
guard !accounts.contains(account) else { continue }
accounts.append(account)
hasNewAppend = true
}
var relationships = viewModel.relationships
for relationship in newRelationships.value {
guard relationships.contains(relationship) == false else { continue }
relationships.append(relationship)
}
let maxID = response.link?.maxID
if hasNewAppend, maxID != nil {
@ -155,8 +177,9 @@ extension UserListViewModel.State {
await enter(state: NoMore.self)
}
self.maxID = maxID
viewModel.userFetchedResultsController.userIDs = userIDs
viewModel.relationships = relationships
viewModel.accounts = accounts
} catch {
await enter(state: Fail.self)
}
@ -177,9 +200,9 @@ extension UserListViewModel.State {
override func didEnter(from previousState: GKState?) {
super.didEnter(from: previousState)
guard let viewModel = viewModel else { return }
guard let viewModel else { return }
// trigger reload
viewModel.userFetchedResultsController.userIDs = viewModel.userFetchedResultsController.userIDs
viewModel.accounts = viewModel.accounts
}
}
}

View File

@ -19,7 +19,8 @@ final class UserListViewModel {
let context: AppContext
let authContext: AuthContext
let kind: Kind
let userFetchedResultsController: UserFetchedResultsController
@Published var accounts: [Mastodon.Entity.Account]
@Published var relationships: [Mastodon.Entity.Relationship]
let listBatchFetchViewModel = ListBatchFetchViewModel()
// output
@ -44,12 +45,8 @@ final class UserListViewModel {
self.context = context
self.authContext = authContext
self.kind = kind
self.userFetchedResultsController = UserFetchedResultsController(
managedObjectContext: context.managedObjectContext,
domain: authContext.mastodonAuthenticationBox.domain,
additionalPredicate: nil
)
// end init
self.accounts = []
self.relationships = []
}
}