mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Multi file uploads (#4358)
* Allow MediaPickerScreen users to select the media selection mode (single or multiple) * Fix cancellation * Add support for multiple media URLs on the MediaUploadPreviewScreen. * Support processing more URLs on the `MediaUploadingPreprocessor` and sending more on the `MediaUploadPreviewScreen` * Add feature flag for `multipleAttachmentUploadEnabled` * Add a label showing the current preview item index in the MediaUploadPreviewScreen * Add support for dragging and dropping or pasting multiple items at the same time. * Support sharing more than one file through the share extension. * Limit the number of items that can be shared in one go to 5. * Fix unit tests * Fix incorrect fatal error when dealing with single selection media pickers. * Document the `multipleAttachmentUploadEnabled` usage in the context of the MediaPicker. * Use a task group for processing selected media in the photo library picker. * Use a task group for processing multiple selected media in the MediaUploadingPreprocessor * Switch the maximum number of items that can be shared to 10. * Allow multiple items to be pasted at the same time.
This commit is contained in:
@@ -27,7 +27,7 @@ enum ComposerToolbarViewModelAction {
|
||||
case editLastMessage
|
||||
case attach(ComposerAttachmentType)
|
||||
|
||||
case handlePasteOrDrop(provider: NSItemProvider)
|
||||
case handlePasteOrDrop(providers: [NSItemProvider])
|
||||
|
||||
case composerModeChanged(mode: ComposerMode)
|
||||
case composerFocusedChanged(isFocused: Bool)
|
||||
@@ -46,7 +46,7 @@ enum ComposerToolbarViewAction {
|
||||
case cancelReply
|
||||
case cancelEdit
|
||||
case attach(ComposerAttachmentType)
|
||||
case handlePasteOrDrop(provider: NSItemProvider)
|
||||
case handlePasteOrDrop(providers: [NSItemProvider])
|
||||
case enableTextFormatting
|
||||
case composerAction(action: ComposerAction)
|
||||
case selectedSuggestion(_ suggestion: SuggestionItem)
|
||||
|
||||
@@ -216,8 +216,8 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
||||
case .attach(let attachment):
|
||||
state.bindings.composerFocused = false
|
||||
actionsSubject.send(.attach(attachment))
|
||||
case .handlePasteOrDrop(let provider):
|
||||
actionsSubject.send(.handlePasteOrDrop(provider: provider))
|
||||
case .handlePasteOrDrop(let providers):
|
||||
actionsSubject.send(.handlePasteOrDrop(providers: providers))
|
||||
case .enableTextFormatting:
|
||||
state.bindings.composerFormattingEnabled = true
|
||||
state.bindings.composerFocused = true
|
||||
|
||||
@@ -181,8 +181,8 @@ struct ComposerToolbar: View {
|
||||
sendMessage()
|
||||
} editAction: {
|
||||
context.send(viewAction: .editLastMessage)
|
||||
} pasteAction: { provider in
|
||||
context.send(viewAction: .handlePasteOrDrop(provider: provider))
|
||||
} pasteAction: { providers in
|
||||
context.send(viewAction: .handlePasteOrDrop(providers: providers))
|
||||
} cancellationAction: {
|
||||
switch context.viewState.composerMode {
|
||||
case .edit:
|
||||
@@ -259,7 +259,7 @@ struct ComposerToolbar: View {
|
||||
viewModel: context.viewState.wysiwygViewModel,
|
||||
itemProviderHelper: ItemProviderHelper(),
|
||||
keyCommands: context.viewState.keyCommands) { provider in
|
||||
context.send(viewAction: .handlePasteOrDrop(provider: provider))
|
||||
context.send(viewAction: .handlePasteOrDrop(providers: [provider]))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
typealias GenericKeyHandler = (_ key: UIKeyboardHIDUsage) -> Void
|
||||
typealias PasteHandler = (NSItemProvider) -> Void
|
||||
typealias PasteHandler = ([NSItemProvider]) -> Void
|
||||
|
||||
struct MessageComposer: View {
|
||||
@Binding var plainComposerText: NSAttributedString
|
||||
|
||||
+10
-10
@@ -190,8 +190,8 @@ private struct UITextViewWrapper: UIViewRepresentable {
|
||||
textView.insertText("\n")
|
||||
}
|
||||
|
||||
func textView(_ textView: UITextView, didReceivePasteWith provider: NSItemProvider) {
|
||||
pasteHandler(provider)
|
||||
func textView(_ textView: UITextView, didReceivePasteWith providers: [NSItemProvider]) {
|
||||
pasteHandler(providers)
|
||||
}
|
||||
|
||||
func textViewDidChangeSelection(_ textView: UITextView) {
|
||||
@@ -207,7 +207,7 @@ private struct UITextViewWrapper: UIViewRepresentable {
|
||||
private protocol ElementTextViewDelegate: AnyObject {
|
||||
func textViewDidReceiveShiftEnterKeyPress(_ textView: UITextView)
|
||||
func textViewDidReceiveKeyPress(_ textView: UITextView, key: UIKeyboardHIDUsage)
|
||||
func textView(_ textView: UITextView, didReceivePasteWith provider: NSItemProvider)
|
||||
func textView(_ textView: UITextView, didReceivePasteWith providers: [NSItemProvider])
|
||||
}
|
||||
|
||||
private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate {
|
||||
@@ -280,19 +280,19 @@ private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate {
|
||||
return false
|
||||
}
|
||||
|
||||
return UIPasteboard.general.itemProviders.first?.isSupportedForPasteOrDrop ?? false
|
||||
return UIPasteboard.general.itemProviders.filter { !$0.isSupportedForPasteOrDrop }.isEmpty
|
||||
}
|
||||
|
||||
override func paste(_ sender: Any?) {
|
||||
guard let provider = UIPasteboard.general.itemProviders.first,
|
||||
provider.isSupportedForPasteOrDrop else {
|
||||
// If the item is not supported for media upload then
|
||||
// just try pasting its contents into the textfield
|
||||
let providers = UIPasteboard.general.itemProviders
|
||||
|
||||
// Use the default behavior if there are any unsupported providers
|
||||
guard providers.filter({ !$0.isSupportedForPasteOrDrop }).isEmpty else {
|
||||
super.paste(sender)
|
||||
return
|
||||
}
|
||||
|
||||
elementDelegate?.textView(self, didReceivePasteWith: provider)
|
||||
|
||||
elementDelegate?.textView(self, didReceivePasteWith: providers)
|
||||
}
|
||||
|
||||
// MARK: PillAttachmentViewProviderDelegate
|
||||
|
||||
Reference in New Issue
Block a user