User can now select video when selecting Gallery to send attachments to a room
This commit is contained in:
parent
570cffd3ed
commit
30a54cfdbc
|
@ -9,6 +9,7 @@ Improvements 🙌:
|
|||
- Delete and react to stickers (#3250)
|
||||
- Compress video before sending (#442)
|
||||
- Improve file too big error detection (#3245)
|
||||
- User can now select video when selecting Gallery to send attachments to a room
|
||||
|
||||
Bugfix 🐛:
|
||||
- Message states cosmetic changes (#3007)
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.lib.multipicker
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.provider.MediaStore
|
||||
import im.vector.lib.multipicker.entity.MultiPickerBaseMediaType
|
||||
import im.vector.lib.multipicker.entity.MultiPickerImageType
|
||||
import im.vector.lib.multipicker.entity.MultiPickerVideoType
|
||||
import im.vector.lib.multipicker.utils.ImageUtils
|
||||
|
||||
/**
|
||||
* Image/Video Picker implementation
|
||||
*/
|
||||
class MediaPicker : Picker<MultiPickerBaseMediaType>() {
|
||||
|
||||
/**
|
||||
* Call this function from onActivityResult(int, int, Intent).
|
||||
* Returns selected image/video files or empty list if user did not select any files.
|
||||
*/
|
||||
override fun getSelectedFiles(context: Context, data: Intent?): List<MultiPickerBaseMediaType> {
|
||||
val mediaList = mutableListOf<MultiPickerBaseMediaType>()
|
||||
|
||||
getSelectedUriList(data).forEach { selectedUri ->
|
||||
val projection = arrayOf(
|
||||
MediaStore.Images.Media.DISPLAY_NAME,
|
||||
MediaStore.Images.Media.SIZE,
|
||||
MediaStore.Images.Media.MIME_TYPE
|
||||
)
|
||||
|
||||
context.contentResolver.query(
|
||||
selectedUri,
|
||||
projection,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)?.use { cursor ->
|
||||
val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
|
||||
val sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE)
|
||||
val mimeTypeColumn = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
|
||||
|
||||
if (cursor.moveToNext()) {
|
||||
val name = cursor.getString(nameColumn)
|
||||
val size = cursor.getLong(sizeColumn)
|
||||
val mimeType = cursor.getString(mimeTypeColumn)
|
||||
|
||||
if (mimeType.isMimeTypeVideo()) {
|
||||
var duration = 0L
|
||||
var width = 0
|
||||
var height = 0
|
||||
var orientation = 0
|
||||
|
||||
context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd ->
|
||||
val mediaMetadataRetriever = MediaMetadataRetriever()
|
||||
mediaMetadataRetriever.setDataSource(pfd.fileDescriptor)
|
||||
duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L
|
||||
width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0
|
||||
height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0
|
||||
orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0
|
||||
}
|
||||
|
||||
mediaList.add(
|
||||
MultiPickerVideoType(
|
||||
name,
|
||||
size,
|
||||
context.contentResolver.getType(selectedUri),
|
||||
selectedUri,
|
||||
width,
|
||||
height,
|
||||
orientation,
|
||||
duration
|
||||
)
|
||||
)
|
||||
} else {
|
||||
// Assume it's an image
|
||||
val bitmap = ImageUtils.getBitmap(context, selectedUri)
|
||||
val orientation = ImageUtils.getOrientation(context, selectedUri)
|
||||
|
||||
mediaList.add(
|
||||
MultiPickerImageType(
|
||||
name,
|
||||
size,
|
||||
context.contentResolver.getType(selectedUri),
|
||||
selectedUri,
|
||||
bitmap?.width ?: 0,
|
||||
bitmap?.height ?: 0,
|
||||
orientation
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mediaList
|
||||
}
|
||||
|
||||
override fun createIntent(): Intent {
|
||||
return Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, !single)
|
||||
type = "video/*, image/*"
|
||||
val mimeTypes = arrayOf("image/*", "video/*")
|
||||
putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String?.isMimeTypeVideo() = this?.startsWith("video/") == true
|
||||
}
|
|
@ -20,6 +20,7 @@ class MultiPicker<T> {
|
|||
|
||||
companion object Type {
|
||||
val IMAGE by lazy { MultiPicker<ImagePicker>() }
|
||||
val MEDIA by lazy { MultiPicker<MediaPicker>() }
|
||||
val FILE by lazy { MultiPicker<FilePicker>() }
|
||||
val VIDEO by lazy { MultiPicker<VideoPicker>() }
|
||||
val AUDIO by lazy { MultiPicker<AudioPicker>() }
|
||||
|
@ -31,6 +32,7 @@ class MultiPicker<T> {
|
|||
return when (type) {
|
||||
IMAGE -> ImagePicker() as T
|
||||
VIDEO -> VideoPicker() as T
|
||||
MEDIA -> MediaPicker() as T
|
||||
FILE -> FilePicker() as T
|
||||
AUDIO -> AudioPicker() as T
|
||||
CONTACT -> ContactPicker() as T
|
||||
|
|
|
@ -23,7 +23,7 @@ data class MultiPickerImageType(
|
|||
override val size: Long,
|
||||
override val mimeType: String?,
|
||||
override val contentUri: Uri,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val orientation: Int
|
||||
) : MultiPickerBaseType
|
||||
override val width: Int,
|
||||
override val height: Int,
|
||||
override val orientation: Int
|
||||
) : MultiPickerBaseMediaType
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.lib.multipicker.entity
|
||||
|
||||
interface MultiPickerBaseMediaType : MultiPickerBaseType {
|
||||
val width: Int
|
||||
val height: Int
|
||||
val orientation: Int
|
||||
}
|
|
@ -23,8 +23,8 @@ data class MultiPickerVideoType(
|
|||
override val size: Long,
|
||||
override val mimeType: String?,
|
||||
override val contentUri: Uri,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val orientation: Int,
|
||||
override val width: Int,
|
||||
override val height: Int,
|
||||
override val orientation: Int,
|
||||
val duration: Long
|
||||
) : MultiPickerBaseType
|
||||
) : MultiPickerBaseMediaType
|
||||
|
|
|
@ -77,10 +77,10 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
|
|||
}
|
||||
|
||||
/**
|
||||
* Starts the process for handling image picking
|
||||
* Starts the process for handling image/video picking
|
||||
*/
|
||||
fun selectGallery(activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||
MultiPicker.get(MultiPicker.IMAGE).startWith(activityResultLauncher)
|
||||
MultiPicker.get(MultiPicker.MEDIA).startWith(activityResultLauncher)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,9 +133,9 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
|
|||
}
|
||||
}
|
||||
|
||||
fun onImageResult(data: Intent?) {
|
||||
fun onMediaResult(data: Intent?) {
|
||||
callback.onContentAttachmentsReady(
|
||||
MultiPicker.get(MultiPicker.IMAGE)
|
||||
MultiPicker.get(MultiPicker.MEDIA)
|
||||
.getSelectedFiles(context, data)
|
||||
.map { it.toContentAttachmentData() }
|
||||
)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.app.features.attachments
|
||||
|
||||
import im.vector.lib.multipicker.entity.MultiPickerAudioType
|
||||
import im.vector.lib.multipicker.entity.MultiPickerBaseMediaType
|
||||
import im.vector.lib.multipicker.entity.MultiPickerBaseType
|
||||
import im.vector.lib.multipicker.entity.MultiPickerContactType
|
||||
import im.vector.lib.multipicker.entity.MultiPickerFileType
|
||||
|
@ -69,6 +70,14 @@ private fun MultiPickerBaseType.mapType(): ContentAttachmentData.Type {
|
|||
}
|
||||
}
|
||||
|
||||
fun MultiPickerBaseMediaType.toContentAttachmentData(): ContentAttachmentData {
|
||||
return when (this) {
|
||||
is MultiPickerImageType -> toContentAttachmentData()
|
||||
is MultiPickerVideoType -> toContentAttachmentData()
|
||||
else -> throw IllegalStateException("Unknown media type")
|
||||
}
|
||||
}
|
||||
|
||||
fun MultiPickerImageType.toContentAttachmentData(): ContentAttachmentData {
|
||||
if (mimeType == null) Timber.w("No mimeType")
|
||||
return ContentAttachmentData(
|
||||
|
|
|
@ -988,9 +988,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private val attachmentImageActivityResultLauncher = registerStartForActivityResult {
|
||||
private val attachmentMediaActivityResultLauncher = registerStartForActivityResult {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
attachmentsHelper.onImageResult(it.data)
|
||||
attachmentsHelper.onMediaResult(it.data)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1991,7 +1991,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
when (type) {
|
||||
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(requireContext(), attachmentPhotoActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentImageActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentMediaActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(attachmentContactActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment)
|
||||
|
|
Loading…
Reference in New Issue