mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-22 00:01:00 +00:00
Browse files for attachments
This commit is contained in:
parent
487e8a766c
commit
377bf6aecc
4 changed files with 80 additions and 35 deletions
|
@ -46,6 +46,9 @@
|
|||
"compose.attachment.uploading" = "Uploading";
|
||||
"compose.prompt" = "What's on your mind?";
|
||||
"compose.mark-media-sensitive" = "Mark media as sensitive";
|
||||
"compose.photo-library" = "Photo Library";
|
||||
"compose.take-photo-or-video" = "Take Photo or Video";
|
||||
"compose.browse" = "Browse";
|
||||
"error" = "Error";
|
||||
"favorites" = "Favorites";
|
||||
"registration.review-terms-of-use-and-privacy-policy-%@" = "Please review %@'s Terms of Use and Privacy Policy to continue";
|
||||
|
|
|
@ -20,6 +20,7 @@ final class NewStatusViewController: UIViewController {
|
|||
action: nil)
|
||||
private let mediaSelections = PassthroughSubject<[PHPickerResult], Never>()
|
||||
private let imagePickerResults = PassthroughSubject<[UIImagePickerController.InfoKey: Any]?, Never>()
|
||||
private let documentPickerResuls = PassthroughSubject<[URL]?, Never>()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init(viewModel: NewStatusViewModel) {
|
||||
|
@ -110,6 +111,16 @@ extension NewStatusViewController: UIImagePickerControllerDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
extension NewStatusViewController: UIDocumentPickerDelegate {
|
||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
documentPickerResuls.send(urls)
|
||||
}
|
||||
|
||||
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
|
||||
documentPickerResuls.send(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Required by UIImagePickerController
|
||||
extension NewStatusViewController: UINavigationControllerDelegate {}
|
||||
|
||||
|
@ -122,6 +133,8 @@ private extension NewStatusViewController {
|
|||
#if !IS_SHARE_EXTENSION
|
||||
presentCamera(compositionViewModel: compositionViewModel)
|
||||
#endif
|
||||
case let .presentDocumentPicker(compositionViewModel):
|
||||
presentDocumentPicker(compositionViewModel: compositionViewModel)
|
||||
case let .editAttachment(attachmentViewModel, compositionViewModel):
|
||||
presentAttachmentEditor(
|
||||
attachmentViewModel: attachmentViewModel,
|
||||
|
@ -301,6 +314,28 @@ private extension NewStatusViewController {
|
|||
}
|
||||
#endif
|
||||
|
||||
func presentDocumentPicker(compositionViewModel: CompositionViewModel) {
|
||||
documentPickerResuls.first().sink { [weak self] in
|
||||
guard let self = self,
|
||||
let result = $0?.first,
|
||||
result.startAccessingSecurityScopedResource(),
|
||||
let itemProvider = NSItemProvider(contentsOf: result)
|
||||
else { return }
|
||||
|
||||
self.viewModel.attach(itemProvider: itemProvider, to: compositionViewModel)
|
||||
result.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
let documentPickerController = UIDocumentPickerViewController(forOpeningContentTypes: [.image, .movie, .audio])
|
||||
|
||||
documentPickerController.delegate = self
|
||||
documentPickerController.allowsMultipleSelection = false
|
||||
documentPickerController.modalPresentationStyle = .overFullScreen
|
||||
|
||||
present(documentPickerController, animated: true)
|
||||
}
|
||||
|
||||
func presentAttachmentEditor(attachmentViewModel: AttachmentViewModel, compositionViewModel: CompositionViewModel) {
|
||||
let editAttachmentsView = EditAttachmentView { (attachmentViewModel, compositionViewModel) }
|
||||
let editAttachmentViewController = UIHostingController(rootView: editAttachmentsView)
|
||||
|
|
|
@ -53,6 +53,7 @@ public extension NewStatusViewModel {
|
|||
enum Event {
|
||||
case presentMediaPicker(CompositionViewModel)
|
||||
case presentCamera(CompositionViewModel)
|
||||
case presentDocumentPicker(CompositionViewModel)
|
||||
case editAttachment(AttachmentViewModel, CompositionViewModel)
|
||||
}
|
||||
|
||||
|
@ -89,6 +90,10 @@ public extension NewStatusViewModel {
|
|||
eventsSubject.send(.presentCamera(viewModel))
|
||||
}
|
||||
|
||||
func presentDocumentPicker(viewModel: CompositionViewModel) {
|
||||
eventsSubject.send(.presentDocumentPicker(viewModel))
|
||||
}
|
||||
|
||||
func remove(viewModel: CompositionViewModel) {
|
||||
compositionViewModels.removeAll { $0 === viewModel }
|
||||
}
|
||||
|
|
|
@ -45,40 +45,44 @@ private extension CompositionInputAccessoryView {
|
|||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.spacing = .defaultSpacing
|
||||
|
||||
let mediaButton = UIButton()
|
||||
|
||||
stackView.addArrangedSubview(mediaButton)
|
||||
mediaButton.setImage(
|
||||
UIImage(
|
||||
systemName: "photo",
|
||||
withConfiguration: UIImage.SymbolConfiguration(scale: .medium)),
|
||||
for: .normal)
|
||||
mediaButton.addAction(UIAction { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.parentViewModel.presentMediaPicker(viewModel: self.viewModel)
|
||||
},
|
||||
for: .touchUpInside)
|
||||
|
||||
let cameraButton = UIButton()
|
||||
|
||||
#if !IS_SHARE_EXTENSION
|
||||
if AVCaptureDevice.authorizationStatus(for: .video) != .restricted {
|
||||
stackView.addArrangedSubview(cameraButton)
|
||||
cameraButton.setImage(
|
||||
UIImage(
|
||||
systemName: "camera",
|
||||
withConfiguration: UIImage.SymbolConfiguration(scale: .medium)),
|
||||
for: .normal)
|
||||
cameraButton.addAction(UIAction { [weak self] _ in
|
||||
var attachmentActions = [
|
||||
UIAction(
|
||||
title: NSLocalizedString("compose.browse", comment: ""),
|
||||
image: UIImage(systemName: "ellipsis")) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.parentViewModel.presentCamera(viewModel: self.viewModel)
|
||||
self.parentViewModel.presentDocumentPicker(viewModel: self.viewModel)
|
||||
},
|
||||
for: .touchUpInside)
|
||||
}
|
||||
UIAction(
|
||||
title: NSLocalizedString("compose.photo-library", comment: ""),
|
||||
image: UIImage(systemName: "rectangle.on.rectangle")) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.parentViewModel.presentMediaPicker(viewModel: self.viewModel)
|
||||
}
|
||||
]
|
||||
|
||||
#if !IS_SHARE_EXTENSION
|
||||
attachmentActions.insert(UIAction(
|
||||
title: NSLocalizedString("compose.take-photo-or-video", comment: ""),
|
||||
image: UIImage(systemName: "camera.fill")) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.parentViewModel.presentCamera(viewModel: self.viewModel)
|
||||
},
|
||||
at: 1)
|
||||
#endif
|
||||
|
||||
let attachmentButton = UIButton()
|
||||
stackView.addArrangedSubview(attachmentButton)
|
||||
attachmentButton.setImage(
|
||||
UIImage(
|
||||
systemName: "paperclip",
|
||||
withConfiguration: UIImage.SymbolConfiguration(scale: .medium)),
|
||||
for: .normal)
|
||||
attachmentButton.showsMenuAsPrimaryAction = true
|
||||
attachmentButton.menu = UIMenu(children: attachmentActions)
|
||||
|
||||
let pollButton = UIButton()
|
||||
|
||||
stackView.addArrangedSubview(pollButton)
|
||||
|
@ -126,11 +130,9 @@ private extension CompositionInputAccessoryView {
|
|||
self.parentViewModel.insert(after: self.viewModel)
|
||||
}, for: .touchUpInside)
|
||||
|
||||
viewModel.$canAddAttachment.sink {
|
||||
mediaButton.isEnabled = $0
|
||||
cameraButton.isEnabled = $0
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
viewModel.$canAddAttachment
|
||||
.sink { attachmentButton.isEnabled = $0 }
|
||||
.store(in: &cancellables)
|
||||
|
||||
viewModel.$remainingCharacters.sink {
|
||||
charactersLabel.text = String($0)
|
||||
|
@ -148,7 +150,7 @@ private extension CompositionInputAccessoryView {
|
|||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
for button in [mediaButton, pollButton, visibilityButton, contentWarningButton, addButton] {
|
||||
for button in [attachmentButton, pollButton, visibilityButton, contentWarningButton, addButton] {
|
||||
button.heightAnchor.constraint(greaterThanOrEqualToConstant: .minimumButtonDimension).isActive = true
|
||||
button.widthAnchor.constraint(greaterThanOrEqualToConstant: .minimumButtonDimension).isActive = true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue