mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-25 01:31:02 +00:00
Account list edits
This commit is contained in:
parent
1fabcb41cc
commit
6b4e17e41e
8 changed files with 61 additions and 27 deletions
|
@ -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,23 +27,26 @@ 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) }
|
||||
}
|
||||
.map { [.init(items: $0.map { CollectionItem.account($0, endpoint.configuration) })] }
|
||||
.eraseToAnyPublisher()
|
||||
sections = accountsSubject
|
||||
.map { [.init(items: $0.map { CollectionItem.account($0, endpoint.configuration) })] }
|
||||
.eraseToAnyPublisher()
|
||||
nextPageMaxId = nextPageMaxIdSubject.eraseToAnyPublisher()
|
||||
navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ extension AccountView: UITextViewDelegate {
|
|||
}
|
||||
|
||||
private extension AccountView {
|
||||
// swiftlint:disable:next function_body_length
|
||||
func initialSetup() {
|
||||
let stackView = UIStackView()
|
||||
|
||||
|
|
Loading…
Reference in a new issue