Move identity changing button
This commit is contained in:
parent
127fef7078
commit
664acc097c
|
@ -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(
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue