Move identity changing button

This commit is contained in:
Justin Mazzocchi 2021-01-26 17:42:32 -08:00
parent 127fef7078
commit 664acc097c
No known key found for this signature in database
GPG Key ID: E223E6937AAFB01C
3 changed files with 63 additions and 60 deletions

View File

@ -28,6 +28,11 @@ final class NewStatusViewController: UIViewController {
self.viewModel = viewModel self.viewModel = viewModel
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
NotificationCenter.default.publisher(for: UIResponder.keyboardDidChangeFrameNotification)
.merge(with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification))
.sink { [weak self] in self?.adjustContentInset(notification: $0) }
.store(in: &cancellables)
} }
@available(*, unavailable) @available(*, unavailable)
@ -66,7 +71,10 @@ final class NewStatusViewController: UIViewController {
activityIndicatorView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor) activityIndicatorView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor)
]) ])
setupBarButtonItems(identityContext: viewModel.identityContext) navigationItem.leftBarButtonItem = UIBarButtonItem(
systemItem: .cancel,
primaryAction: UIAction { [weak self] _ in self?.dismiss() })
navigationItem.rightBarButtonItem = postButton
postButton.primaryAction = UIAction(title: NSLocalizedString("post", comment: "")) { [weak self] _ in postButton.primaryAction = UIAction(title: NSLocalizedString("post", comment: "")) { [weak self] _ in
self?.viewModel.post() self?.viewModel.post()
@ -84,11 +92,6 @@ final class NewStatusViewController: UIViewController {
} }
#endif #endif
NotificationCenter.default.publisher(for: UIResponder.keyboardDidChangeFrameNotification)
.merge(with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification))
.sink { [weak self] in self?.adjustContentInset(notification: $0) }
.store(in: &cancellables)
setupViewModelBindings() setupViewModelBindings()
} }
} }
@ -150,6 +153,8 @@ private extension NewStatusViewController {
presentAttachmentEditor( presentAttachmentEditor(
attachmentViewModel: attachmentViewModel, attachmentViewModel: attachmentViewModel,
compositionViewModel: compositionViewModel) compositionViewModel: compositionViewModel)
case let .changeIdentity(identity):
changeIdentity(identity)
} }
} }
@ -234,9 +239,6 @@ private extension NewStatusViewController {
viewModel.$compositionViewModels viewModel.$compositionViewModels
.sink { [weak self] in self?.set(compositionViewModels: $0) } .sink { [weak self] in self?.set(compositionViewModels: $0) }
.store(in: &cancellables) .store(in: &cancellables)
viewModel.$identityContext
.sink { [weak self] in self?.setupBarButtonItems(identityContext: $0) }
.store(in: &cancellables)
viewModel.$postingState viewModel.$postingState
.sink { [weak self] in self?.apply(postingState: $0) } .sink { [weak self] in self?.apply(postingState: $0) }
.store(in: &cancellables) .store(in: &cancellables)
@ -250,18 +252,6 @@ private extension NewStatusViewController {
.store(in: &cancellables) .store(in: &cancellables)
} }
func setupBarButtonItems(identityContext: IdentityContext) {
let cancelButton = UIBarButtonItem(
systemItem: .cancel,
primaryAction: UIAction { [weak self] _ in self?.dismiss() })
navigationItem.leftBarButtonItem = cancelButton
navigationItem.titleView = viewModel.canChangeIdentity
? changeIdentityButton(identityContext: identityContext)
: nil
navigationItem.rightBarButtonItem = postButton
}
func presentMediaPicker(compositionViewModel: CompositionViewModel) { func presentMediaPicker(compositionViewModel: CompositionViewModel) {
mediaSelections.first().sink { [weak self] results in mediaSelections.first().sink { [weak self] results in
guard let self = self, let result = results.first else { return } guard let self = self, let result = results.first else { return }
@ -422,44 +412,6 @@ private extension NewStatusViewController {
} }
} }
func changeIdentityButton(identityContext: IdentityContext) -> UIButton {
let changeIdentityButton = UIButton()
let downsampled = KingfisherOptionsInfo.downsampled(
dimension: .barButtonItemDimension,
scaleFactor: UIScreen.main.scale)
let menuItems = viewModel.authenticatedIdentities
.filter { $0.id != identityContext.identity.id }
.map { identity in
UIDeferredMenuElement { completion in
let action = UIAction(title: identity.handle) { [weak self] _ in
self?.changeIdentity(identity)
}
if let image = identity.image {
KingfisherManager.shared.retrieveImage(with: image, options: downsampled) {
if case let .success(value) = $0 {
action.image = value.image
}
completion([action])
}
} else {
completion([action])
}
}
}
changeIdentityButton.kf.setImage(
with: identityContext.identity.image,
for: .normal,
options: downsampled)
changeIdentityButton.showsMenuAsPrimaryAction = true
changeIdentityButton.menu = UIMenu(children: menuItems)
return changeIdentityButton
}
func changeIdentity(_ identity: Identity) { func changeIdentity(_ identity: Identity) {
if viewModel.compositionViewModels.contains(where: { !$0.attachmentViewModels.isEmpty }) { if viewModel.compositionViewModels.contains(where: { !$0.attachmentViewModels.isEmpty }) {
let alertController = UIAlertController( let alertController = UIAlertController(

View File

@ -67,6 +67,10 @@ public final class NewStatusViewModel: ObservableObject {
allIdentitiesService.authenticatedIdentitiesPublisher() allIdentitiesService.authenticatedIdentitiesPublisher()
.assignErrorsToAlertItem(to: \.alertItem, on: self) .assignErrorsToAlertItem(to: \.alertItem, on: self)
.combineLatest($identityContext)
.map { authenticatedIdentities, currentIdentity in
authenticatedIdentities.filter { $0.id != currentIdentity.identity.id }
}
.assign(to: &$authenticatedIdentities) .assign(to: &$authenticatedIdentities)
$compositionViewModels.flatMap { Publishers.MergeMany($0.map(\.$isPostable)) } $compositionViewModels.flatMap { Publishers.MergeMany($0.map(\.$isPostable)) }
.receive(on: DispatchQueue.main) // hack to punt to next run loop, consider refactoring .receive(on: DispatchQueue.main) // hack to punt to next run loop, consider refactoring
@ -87,6 +91,7 @@ public extension NewStatusViewModel {
case presentDocumentPicker(CompositionViewModel) case presentDocumentPicker(CompositionViewModel)
case presentEmojiPicker(Int) case presentEmojiPicker(Int)
case editAttachment(AttachmentViewModel, CompositionViewModel) case editAttachment(AttachmentViewModel, CompositionViewModel)
case changeIdentity(Identity)
} }
enum PostingState { enum PostingState {
@ -159,6 +164,10 @@ public extension NewStatusViewModel {
post(viewModel: unposted, inReplyToId: inReplyToViewModel?.id) post(viewModel: unposted, inReplyToId: inReplyToViewModel?.id)
} }
func changeIdentity(_ identity: Identity) {
eventsSubject.send(.changeIdentity(identity))
}
} }
private extension NewStatusViewModel { private extension NewStatusViewModel {

View File

@ -6,7 +6,8 @@ import UIKit
import ViewModels import ViewModels
final class CompositionView: UIView { final class CompositionView: UIView {
let avatarImageView = UIImageView() let avatarImageView = AnimatedImageView()
let changeIdentityButton = UIButton()
let spoilerTextField = UITextField() let spoilerTextField = UITextField()
let textView = UITextView() let textView = UITextView()
let textViewPlaceholder = UILabel() let textViewPlaceholder = UILabel()
@ -64,6 +65,13 @@ private extension CompositionView {
avatarImageView.clipsToBounds = true avatarImageView.clipsToBounds = true
avatarImageView.setContentHuggingPriority(.required, for: .horizontal) avatarImageView.setContentHuggingPriority(.required, for: .horizontal)
changeIdentityButton.translatesAutoresizingMaskIntoConstraints = false
avatarImageView.addSubview(changeIdentityButton)
avatarImageView.isUserInteractionEnabled = true
changeIdentityButton.setBackgroundImage(.highlightedButtonBackground, for: .highlighted)
changeIdentityButton.showsMenuAsPrimaryAction = true
changeIdentityButton.menu = changeIdentityMenu(identities: parentViewModel.authenticatedIdentities)
let stackView = UIStackView() let stackView = UIStackView()
addSubview(stackView) addSubview(stackView)
@ -179,6 +187,10 @@ private extension CompositionView {
.sink { [weak self] in self?.avatarImageView.kf.setImage(with: $0) } .sink { [weak self] in self?.avatarImageView.kf.setImage(with: $0) }
.store(in: &cancellables) .store(in: &cancellables)
parentViewModel.$authenticatedIdentities
.sink { [weak self] in self?.changeIdentityButton.menu = self?.changeIdentityMenu(identities: $0) }
.store(in: &cancellables)
viewModel.$attachmentViewModels viewModel.$attachmentViewModels
.receive(on: RunLoop.main) .receive(on: RunLoop.main)
.sink { [weak self] attachmentViewModels in .sink { [weak self] attachmentViewModels in
@ -209,6 +221,10 @@ private extension CompositionView {
avatarImageView.topAnchor.constraint(equalTo: guide.topAnchor), avatarImageView.topAnchor.constraint(equalTo: guide.topAnchor),
avatarImageView.leadingAnchor.constraint(equalTo: guide.leadingAnchor), avatarImageView.leadingAnchor.constraint(equalTo: guide.leadingAnchor),
avatarImageView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor), avatarImageView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor),
changeIdentityButton.leadingAnchor.constraint(equalTo: avatarImageView.leadingAnchor),
changeIdentityButton.topAnchor.constraint(equalTo: avatarImageView.topAnchor),
changeIdentityButton.bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor),
changeIdentityButton.trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor),
stackView.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: .defaultSpacing), stackView.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: .defaultSpacing),
stackView.topAnchor.constraint(greaterThanOrEqualTo: guide.topAnchor), stackView.topAnchor.constraint(greaterThanOrEqualTo: guide.topAnchor),
stackView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor), stackView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor),
@ -228,4 +244,30 @@ private extension CompositionView {
NSLayoutConstraint.activate(constraints) NSLayoutConstraint.activate(constraints)
} }
func changeIdentityMenu(identities: [Identity]) -> UIMenu {
UIMenu(children: identities.map { identity in
UIDeferredMenuElement { completion in
let action = UIAction(title: identity.handle) { [weak self] _ in
self?.parentViewModel.changeIdentity(identity)
}
if let image = identity.image {
KingfisherManager.shared.retrieveImage(
with: image,
options: KingfisherOptionsInfo.downsampled(
dimension: .barButtonItemDimension,
scaleFactor: UIScreen.main.scale)) {
if case let .success(value) = $0 {
action.image = value.image
}
completion([action])
}
} else {
completion([action])
}
}
})
}
} }