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
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)
@ -66,7 +71,10 @@ final class NewStatusViewController: UIViewController {
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
self?.viewModel.post()
@ -84,11 +92,6 @@ final class NewStatusViewController: UIViewController {
}
#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()
}
}
@ -150,6 +153,8 @@ private extension NewStatusViewController {
presentAttachmentEditor(
attachmentViewModel: attachmentViewModel,
compositionViewModel: compositionViewModel)
case let .changeIdentity(identity):
changeIdentity(identity)
}
}
@ -234,9 +239,6 @@ private extension NewStatusViewController {
viewModel.$compositionViewModels
.sink { [weak self] in self?.set(compositionViewModels: $0) }
.store(in: &cancellables)
viewModel.$identityContext
.sink { [weak self] in self?.setupBarButtonItems(identityContext: $0) }
.store(in: &cancellables)
viewModel.$postingState
.sink { [weak self] in self?.apply(postingState: $0) }
.store(in: &cancellables)
@ -250,18 +252,6 @@ private extension NewStatusViewController {
.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) {
mediaSelections.first().sink { [weak self] results in
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) {
if viewModel.compositionViewModels.contains(where: { !$0.attachmentViewModels.isEmpty }) {
let alertController = UIAlertController(

View file

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

View file

@ -6,7 +6,8 @@ import UIKit
import ViewModels
final class CompositionView: UIView {
let avatarImageView = UIImageView()
let avatarImageView = AnimatedImageView()
let changeIdentityButton = UIButton()
let spoilerTextField = UITextField()
let textView = UITextView()
let textViewPlaceholder = UILabel()
@ -64,6 +65,13 @@ private extension CompositionView {
avatarImageView.clipsToBounds = true
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()
addSubview(stackView)
@ -179,6 +187,10 @@ private extension CompositionView {
.sink { [weak self] in self?.avatarImageView.kf.setImage(with: $0) }
.store(in: &cancellables)
parentViewModel.$authenticatedIdentities
.sink { [weak self] in self?.changeIdentityButton.menu = self?.changeIdentityMenu(identities: $0) }
.store(in: &cancellables)
viewModel.$attachmentViewModels
.receive(on: RunLoop.main)
.sink { [weak self] attachmentViewModels in
@ -209,6 +221,10 @@ private extension CompositionView {
avatarImageView.topAnchor.constraint(equalTo: guide.topAnchor),
avatarImageView.leadingAnchor.constraint(equalTo: guide.leadingAnchor),
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.topAnchor.constraint(greaterThanOrEqualTo: guide.topAnchor),
stackView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor),
@ -228,4 +244,30 @@ private extension CompositionView {
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])
}
}
})
}
}