Configure barbutton-items on profile-screen (IOS-192)

This commit is contained in:
Nathan Mattes 2023-12-24 14:25:32 +01:00
parent d189119014
commit 099cb724d0
2 changed files with 155 additions and 138 deletions

View File

@ -202,33 +202,38 @@ extension ProfileViewController {
}
.store(in: &disposeBag)
Publishers.CombineLatest4 (
viewModel.account.suspended.publisher,
// build items
Publishers.CombineLatest4(
viewModel.$relationship,
profileHeaderViewController.viewModel.$isTitleViewDisplaying,
editingAndUpdatingPublisher.eraseToAnyPublisher(),
barButtonItemHiddenPublisher.eraseToAnyPublisher()
editingAndUpdatingPublisher,
barButtonItemHiddenPublisher
)
.receive(on: DispatchQueue.main)
.sink { [weak self] isSuspended, isTitleViewDisplaying, tuple1, tuple2 in
guard let self = self else { return }
.sink { [weak self] account, isTitleViewDisplaying, tuple1, tuple2 in
guard let self else { return }
let (isEditing, _) = tuple1
let (isMeBarButtonItemsHidden, isReplyBarButtonItemHidden, isMoreMenuBarButtonItemHidden) = tuple2
var items: [UIBarButtonItem] = []
defer {
self.navigationItem.rightBarButtonItems = !items.isEmpty ? items : nil
if items.isNotEmpty {
self.navigationItem.rightBarButtonItems = items
} else {
self.navigationItem.rightBarButtonItems = nil
}
}
guard !isSuspended else {
if let suspended = self.viewModel.account.suspended, suspended == true {
return
}
guard !isEditing else {
guard isEditing == false else {
items.append(self.cancelEditingBarButtonItem)
return
}
guard !isTitleViewDisplaying else {
guard isTitleViewDisplaying == false else {
return
}
@ -274,8 +279,6 @@ extension ProfileViewController {
bindTitleView()
bindMoreBarButtonItem()
bindPager()
viewModel.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
@ -286,7 +289,8 @@ extension ProfileViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
viewModel.viewDidAppear.send()
setNeedsStatusBarAppearanceUpdate()
}
@ -296,7 +300,6 @@ extension ProfileViewController {
private func bindViewModel() {
// header
#warning("TODO: Implement")
let headerViewModel = profileHeaderViewController.viewModel!
viewModel.$account
.assign(to: \.account, on: headerViewModel)
@ -307,9 +310,6 @@ extension ProfileViewController {
viewModel.$isUpdating
.assign(to: \.isUpdating, on: headerViewModel)
.store(in: &disposeBag)
// viewModel.relationshipViewModel.$isMyself
// .assign(to: \.isMyself, on: headerViewModel)
// .store(in: &disposeBag)
viewModel.$relationship
.assign(to: \.relationship, on: headerViewModel)
.store(in: &disposeBag)
@ -330,9 +330,9 @@ extension ProfileViewController {
// about
let aboutViewModel = viewModel.profileAboutViewModel
// viewModel.$account
// .assign(to: \.account, on: aboutViewModel)
// .store(in: &disposeBag)
viewModel.$account
.assign(to: \.account, on: aboutViewModel)
.store(in: &disposeBag)
viewModel.$isEditing
.assign(to: \.isEditing, on: aboutViewModel)
.store(in: &disposeBag)
@ -373,21 +373,32 @@ extension ProfileViewController {
self.navigationItem.title = name
}
.store(in: &disposeBag)
Publishers.CombineLatest(
profileHeaderViewController.viewModel.$account,
profileHeaderViewController.profileHeaderView.viewModel.viewDidAppear
)
.sink { [weak self] (user, _) in
guard let self, let domain = user.domainFromAcct else { return }
Task {
_ = try await self.context.apiService.fetchUser(
username: user.username,
domain: domain,
authenticationBox: self.authContext.mastodonAuthenticationBox
)
}
}
.store(in: &disposeBag)
profileHeaderViewController.profileHeaderView.viewModel.viewDidAppear
.sink(receiveValue: { [weak self] _ in
guard let self else { return }
let account = self.viewModel.account
guard let domain = account.domainFromAcct else { return }
Task {
let account = try await self.context.apiService.fetchUser(
username: account.username,
domain: domain,
authenticationBox: self.authContext.mastodonAuthenticationBox
)
guard let account else { return }
let relationship = try await self.context.apiService.relationship(forAccounts: [account], authenticationBox: self.authContext.mastodonAuthenticationBox).value.first
guard let relationship else { return }
// they don't run as there's not a change, probably?
self.viewModel.relationship = relationship
self.viewModel.account = account
}
})
.store(in: &disposeBag)
}
private func bindMoreBarButtonItem() {
@ -667,78 +678,82 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
profileHeaderView: ProfileHeaderView,
relationshipButtonDidPressed button: ProfileRelationshipActionButton
) {
// let relationshipActionSet = viewModel.relationshipViewModel.optionSet ?? .none
#warning("TODO: Implement")
// handle edit logic for editable profile
// handle relationship logic for non-editable profile
// if relationshipActionSet.contains(.edit) {
if let me = viewModel.me, me == viewModel.account {
// // do nothing when updating
// guard !viewModel.isUpdating else { return }
//
// guard let profileHeaderViewModel = profileHeaderViewController.viewModel else { return }
// guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
//
// let isEdited = profileHeaderViewModel.isEdited || profileAboutViewModel.isEdited
//
// if isEdited {
// // update profile when edited
// viewModel.isUpdating = true
// Task { @MainActor in
// do {
// // TODO: handle error
// _ = try await viewModel.updateProfileInfo(
// headerProfileInfo: profileHeaderViewModel.profileInfoEditing,
// aboutProfileInfo: profileAboutViewModel.profileInfoEditing
// )
// self.viewModel.isEditing = false
//
// } catch {
// let alertController = UIAlertController(
// for: error,
// title: L10n.Common.Alerts.EditProfileFailure.title,
// preferredStyle: .alert
// )
// let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
// alertController.addAction(okAction)
// self.present(alertController, animated: true)
// }
//
// // finish updating
// self.viewModel.isUpdating = false
// } // end Task
// } else {
// // set `updating` then toggle `edit` state
// viewModel.isUpdating = true
// viewModel.fetchEditProfileInfo()
// .receive(on: DispatchQueue.main)
// .sink { [weak self] completion in
// guard let self = self else { return }
// defer {
// // finish updating
// self.viewModel.isUpdating = false
// }
// switch completion {
// case .failure(let error):
// let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.EditProfileFailure.title, preferredStyle: .alert)
// let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
// alertController.addAction(okAction)
// _ = self.coordinator.present(
// scene: .alertController(alertController: alertController),
// from: nil,
// transition: .alertController(animated: true, completion: nil)
// )
// case .finished:
// // enter editing mode
// self.viewModel.isEditing.toggle()
// }
// } receiveValue: { [weak self] response in
// guard let self = self else { return }
// self.viewModel.accountForEdit = response.value
// }
// .store(in: &disposeBag)
// }
// } else {
guard !viewModel.isUpdating else { return }
guard let profileHeaderViewModel = profileHeaderViewController.viewModel else { return }
guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
let isEdited = profileHeaderViewModel.isEdited || profileAboutViewModel.isEdited
if isEdited {
// update profile when edited
viewModel.isUpdating = true
Task { @MainActor in
do {
// TODO: handle error
_ = try await viewModel.updateProfileInfo(
headerProfileInfo: profileHeaderViewModel.profileInfoEditing,
aboutProfileInfo: profileAboutViewModel.profileInfoEditing
)
self.viewModel.isEditing = false
} catch {
let alertController = UIAlertController(
for: error,
title: L10n.Common.Alerts.EditProfileFailure.title,
preferredStyle: .alert
)
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
alertController.addAction(okAction)
self.present(alertController, animated: true)
}
// finish updating
self.viewModel.isUpdating = false
} // end Task
} else {
// set `updating` then toggle `edit` state
viewModel.isUpdating = true
viewModel.fetchEditProfileInfo()
.receive(on: DispatchQueue.main)
.sink { [weak self] completion in
guard let self = self else { return }
defer {
// finish updating
self.viewModel.isUpdating = false
}
switch completion {
case .failure(let error):
let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.EditProfileFailure.title, preferredStyle: .alert)
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
alertController.addAction(okAction)
_ = self.coordinator.present(
scene: .alertController(alertController: alertController),
from: nil,
transition: .alertController(animated: true, completion: nil)
)
case .finished:
// enter editing mode
self.viewModel.isEditing.toggle()
}
} receiveValue: { [weak self] response in
guard let self = self else { return }
self.viewModel.accountForEdit = response.value
}
.store(in: &disposeBag)
}
} else {
// guard let relationshipAction = relationshipActionSet.highPriorityAction(except: .editOptions) else { return }
guard let relationship = viewModel.relationship else { return }
print(relationship)
// switch relationshipAction {
// case .none:
// break
@ -800,8 +815,7 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
// case .blocked, .showReblogs, .isMyself,.followingBy, .blockingBy, .suspended, .edit, .editing, .updating:
// break
// }
// }
}
}
func profileHeaderViewController(

View File

@ -100,24 +100,31 @@ class ProfileViewModel: NSObject {
$userIdentifier.assign(to: &mediaUserTimelineViewModel.$userIdentifier)
// bind bar button items
#warning("TODO: Implement")
// relationshipViewModel.$optionSet
// .sink { [weak self] optionSet in
// guard let self = self else { return }
// guard let optionSet = optionSet, !optionSet.contains(.none) else {
// self.isReplyBarButtonItemHidden = true
// self.isMoreMenuBarButtonItemHidden = true
// self.isMeBarButtonItemsHidden = true
// return
// }
//
// let isMyself = optionSet.contains(.isMyself)
// self.isReplyBarButtonItemHidden = isMyself
// self.isMoreMenuBarButtonItemHidden = isMyself
// self.isMeBarButtonItemsHidden = !isMyself
// }
// .store(in: &disposeBag)
Publishers.CombineLatest3($account, $me, $relationship)
.sink(receiveValue: { [weak self] account, me, relationship in
guard let self else {
self?.isReplyBarButtonItemHidden = true
self?.isMoreMenuBarButtonItemHidden = true
self?.isMeBarButtonItemsHidden = true
return
}
let isMyself = (account == me)
self.isReplyBarButtonItemHidden = isMyself
self.isMoreMenuBarButtonItemHidden = isMyself
self.isMeBarButtonItemsHidden = (isMyself == false)
})
.store(in: &disposeBag)
viewDidAppear
.sink { [weak self] _ in
guard let self else { return }
self.isReplyBarButtonItemHidden = self.isReplyBarButtonItemHidden
self.isMoreMenuBarButtonItemHidden = self.isMoreMenuBarButtonItemHidden
self.isMeBarButtonItemsHidden = self.isMeBarButtonItemsHidden
}
.store(in: &disposeBag)
// query relationship
#warning("TODO: Implement")
// let pendingRetryPublisher = CurrentValueSubject<TimeInterval, Never>(1)
@ -151,26 +158,22 @@ class ProfileViewModel: NSObject {
// }
// .store(in: &disposeBag)
// let isBlockingOrBlocked = Publishers.CombineLatest(
// relationshipViewModel.$isBlocking,
// relationshipViewModel.$isBlockingBy
// )
// .map { $0 || $1 }
// .share()
//
// Publishers.CombineLatest(
// isBlockingOrBlocked,
// $isEditing
// )
// .map { !$0 && !$1 }
// .assign(to: &$isPagingEnabled)
let isBlockingOrBlocked = Publishers.CombineLatest3(
(relationship?.blocking ?? false).publisher,
(relationship?.blockedBy ?? false).publisher,
(relationship?.domainBlocking ?? false).publisher
)
.map { $0 || $1 || $2 }
.share()
Publishers.CombineLatest(
isBlockingOrBlocked,
$isEditing
)
.map { !$0 && !$1 }
.assign(to: &$isPagingEnabled)
}
func viewDidLoad() {
}
// fetch profile info before edit
func fetchEditProfileInfo() -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Account>, Error> {
guard let me, let domain = me.domain else {