Account list edits

This commit is contained in:
Justin Mazzocchi 2021-01-26 16:15:52 -08:00
parent 1fabcb41cc
commit 6b4e17e41e
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
8 changed files with 61 additions and 27 deletions

View file

@ -12,7 +12,7 @@ public struct AccountListService {
public let navigationService: NavigationService
public let canRefresh = false
private let accountsSubject = PassthroughSubject<[Account], Error>()
private let accountsSubject = CurrentValueSubject<[Account], Error>([])
private let endpoint: AccountsEndpoint
private let mastodonAPIClient: MastodonAPIClient
private let contentDatabase: ContentDatabase
@ -27,11 +27,7 @@ public struct AccountListService {
self.mastodonAPIClient = mastodonAPIClient
self.contentDatabase = contentDatabase
self.titleComponents = titleComponents
sections = accountsSubject.scan([]) {
let presentIds = Set($0.map(\.id))
return $0 + $1.filter { !presentIds.contains($0.id) }
}
sections = accountsSubject
.map { [.init(items: $0.map { CollectionItem.account($0, endpoint.configuration) })] }
.eraseToAnyPublisher()
nextPageMaxId = nextPageMaxIdSubject.eraseToAnyPublisher()
@ -39,11 +35,18 @@ public struct AccountListService {
}
}
public extension AccountListService {
func remove(id: Account.Id) {
accountsSubject.value.removeAll { $0.id == id }
}
}
extension AccountListService: CollectionService {
public func request(maxId: String?, minId: String?, search: Search?) -> AnyPublisher<Never, Error> {
mastodonAPIClient.pagedRequest(endpoint, maxId: maxId, minId: minId)
.handleEvents(receiveOutput: {
accountsSubject.send($0.result)
let presentIds = Set(accountsSubject.value.map(\.id))
accountsSubject.value.append(contentsOf: $0.result.filter { !presentIds.contains($0.id) })
guard let maxId = $0.info.maxId else { return }

View file

@ -334,6 +334,8 @@ private extension TableViewController {
confirmDelete(statusViewModel: statusViewModel, redraft: redraft)
case let .report(reportViewModel):
report(reportViewModel: reportViewModel)
case let .accountListEdit(accountViewModel, edit):
accountListEdit(accountViewModel: accountViewModel, edit: edit)
}
}
@ -454,6 +456,10 @@ private extension TableViewController {
present(alertController, animated: true)
}
func accountListEdit(accountViewModel: AccountViewModel, edit: CollectionItemEvent.AccountListEdit) {
viewModel.applyAccountListEdit(viewModel: accountViewModel, edit: edit)
}
func set(expandAllState: ExpandAllState) {
switch expandAllState {
case .hidden:

View file

@ -12,4 +12,12 @@ public enum CollectionItemEvent {
case confirmDelete(StatusViewModel, redraft: Bool)
case report(ReportViewModel)
case share(URL)
case accountListEdit(AccountViewModel, AccountListEdit)
}
public extension CollectionItemEvent {
enum AccountListEdit {
case acceptFollowRequest
case rejectFollowRequest
}
}

View file

@ -21,6 +21,8 @@ public final class AccountViewModel: CollectionItemViewModel, ObservableObject {
}
public extension AccountViewModel {
var id: Account.Id { accountService.account.id }
var headerURL: URL {
if !identityContext.appPreferences.shouldReduceMotion, identityContext.appPreferences.animateHeaders {
return accountService.account.header
@ -140,27 +142,11 @@ public extension AccountViewModel {
}
func acceptFollowRequest() {
ignorableOutputEvent(
accountService.acceptFollowRequest()
.collect()
.flatMap { [weak self] _ -> AnyPublisher<Never, Error> in
guard let self = self else { return Empty().eraseToAnyPublisher() }
return self.identityContext.service.verifyCredentials()
}
.eraseToAnyPublisher())
accountListEdit(accountService.acceptFollowRequest(), event: .acceptFollowRequest)
}
func rejectFollowRequest() {
ignorableOutputEvent(
accountService.rejectFollowRequest()
.collect()
.flatMap { [weak self] _ -> AnyPublisher<Never, Error> in
guard let self = self else { return Empty().eraseToAnyPublisher() }
return self.identityContext.service.verifyCredentials()
}
.eraseToAnyPublisher())
accountListEdit(accountService.rejectFollowRequest(), event: .rejectFollowRequest)
}
func domainBlock() {
@ -176,4 +162,15 @@ private extension AccountViewModel {
func ignorableOutputEvent(_ action: AnyPublisher<Never, Error>) {
eventsSubject.send(action.map { _ in .ignorableOutput }.eraseToAnyPublisher())
}
func accountListEdit(_ action: AnyPublisher<Never, Error>, event: CollectionItemEvent.AccountListEdit) {
eventsSubject.send(
action.collect()
.map { [weak self] _ -> CollectionItemEvent in
guard let self = self else { return .ignorableOutput }
return .accountListEdit(self, .acceptFollowRequest)
}
.eraseToAnyPublisher())
}
}

View file

@ -321,6 +321,20 @@ extension CollectionItemsViewModel: CollectionViewModel {
.store(in: &cancellables)
}
}
public func applyAccountListEdit(viewModel: AccountViewModel, edit: CollectionItemEvent.AccountListEdit) {
(collectionService as? AccountListService)?.remove(id: viewModel.id)
switch edit {
case .acceptFollowRequest, .rejectFollowRequest:
identityContext.service.verifyCredentials()
.assignErrorsToAlertItem(to: \.alertItem, on: self)
.sink { _ in }
.store(in: &cancellables)
default:
break
}
}
}
private extension CollectionItemsViewModel {

View file

@ -21,4 +21,5 @@ public protocol CollectionViewModel {
func canSelect(indexPath: IndexPath) -> Bool
func viewModel(indexPath: IndexPath) -> CollectionItemViewModel
func toggleExpandAll()
func applyAccountListEdit(viewModel: AccountViewModel, edit: CollectionItemEvent.AccountListEdit)
}

View file

@ -139,4 +139,8 @@ extension ProfileViewModel: CollectionViewModel {
public func toggleExpandAll() {
collectionViewModel.value.toggleExpandAll()
}
public func applyAccountListEdit(viewModel: AccountViewModel, edit: CollectionItemEvent.AccountListEdit) {
collectionViewModel.value.applyAccountListEdit(viewModel: viewModel, edit: edit)
}
}

View file

@ -80,6 +80,7 @@ extension AccountView: UITextViewDelegate {
}
private extension AccountView {
// swiftlint:disable:next function_body_length
func initialSetup() {
let stackView = UIStackView()