From 7ca36938df8f09ebdce1457e42db277068ef8040 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 11 Jun 2020 14:54:21 +0200 Subject: [PATCH] Improved videos shared by chat preview --- .../chat/fragments/DetailChatRoomFragment.kt | 6 ++-- .../ChatMessageAttachmentViewModel.kt | 21 ++++++++++++- .../viewmodels/ChatMessageContentViewModel.kt | 19 ++++++++++++ .../viewmodels/ChatMessageSendingViewModel.kt | 2 +- .../org/linphone/utils/DataBindingUtils.kt | 6 ++++ .../main/java/org/linphone/utils/FileUtils.kt | 24 +++++++-------- .../java/org/linphone/utils/ImageUtils.kt | 5 ++++ .../layout/chat_message_attachment_cell.xml | 30 +++++++++++++++++-- .../res/layout/chat_message_content_cell.xml | 22 ++++++++++++-- 9 files changed, 111 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt index 3dfd75f38..1b9785567 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt @@ -39,7 +39,6 @@ import androidx.navigation.Navigation import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.tabs_fragment.* import kotlinx.coroutines.launch import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences @@ -518,8 +517,7 @@ class DetailChatRoomFragment : MasterFragment() { private fun openFile(contentFilePath: String) { val intent = Intent(Intent.ACTION_VIEW) - val path = contentFilePath - val contentUri: Uri = FileUtils.getPublicFilePath(requireContext(), path) + val contentUri: Uri = FileUtils.getPublicFilePath(requireContext(), contentFilePath) val filePath: String = contentUri.toString() Log.i("[Chat Message] Trying to open file: $filePath") var type: String? = null @@ -535,7 +533,7 @@ class DetailChatRoomFragment : MasterFragment() { if (type != null) { Log.i("[Chat Message] Found matching MIME type $type") } else { - type = FileUtils.getMimeFromFile(filePath) + type = "file/$extension" Log.e("[Chat Message] Can't get MIME type from extension: $extension, will use $type") } diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageAttachmentViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageAttachmentViewModel.kt index ad597cf48..070491746 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageAttachmentViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageAttachmentViewModel.kt @@ -19,15 +19,34 @@ */ package org.linphone.activities.main.chat.viewmodels +import android.graphics.Bitmap +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.linphone.utils.FileUtils +import org.linphone.utils.ImageUtils class ChatMessageAttachmentViewModel( val path: String, - val isImage: Boolean, private val deleteCallback: (attachment: ChatMessageAttachmentViewModel) -> Unit ) : ViewModel() { val fileName: String = FileUtils.getNameFromFilePath(path) + val isImage: Boolean = FileUtils.isExtensionImage(path) + val isVideo: Boolean = FileUtils.isExtensionVideo(path) + val videoPreview = MutableLiveData() + + init { + if (isVideo) { + viewModelScope.launch { + withContext(Dispatchers.IO) { + videoPreview.postValue(ImageUtils.getVideoPreview(path)) + } + } + } + } fun delete() { deleteCallback(this) diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageContentViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageContentViewModel.kt index 523856702..20a0c0c25 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageContentViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageContentViewModel.kt @@ -19,12 +19,18 @@ */ package org.linphone.activities.main.chat.viewmodels +import android.graphics.Bitmap import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.linphone.core.ChatMessage import org.linphone.core.Content import org.linphone.core.tools.Log import org.linphone.utils.FileUtils +import org.linphone.utils.ImageUtils class ChatMessageContentViewModel( val content: Content, @@ -32,6 +38,8 @@ class ChatMessageContentViewModel( private val listener: OnContentClickedListener? ) : ViewModel() { val isImage = MutableLiveData() + val isVideo = MutableLiveData() + val videoPreview = MutableLiveData() val downloadable = MutableLiveData() @@ -55,14 +63,25 @@ class ChatMessageContentViewModel( if (content.filePath.isNotEmpty()) { Log.i("[Content] Found displayable content: ${content.filePath}") isImage.value = FileUtils.isExtensionImage(content.filePath) + isVideo.value = FileUtils.isExtensionVideo(content.filePath) + + if (isVideo.value == true) { + viewModelScope.launch { + withContext(Dispatchers.IO) { + videoPreview.postValue(ImageUtils.getVideoPreview(content.filePath)) + } + } + } } else { Log.w("[Content] Found content with empty path...") isImage.value = false + isVideo.value = false } } else { Log.i("[Content] Found downloadable content: ${content.name}") downloadable.value = true isImage.value = false + isVideo.value = false } downloadEnabled.value = downloadable.value diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt index 3cafc7e8c..5e6639e6b 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt @@ -74,7 +74,7 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() fun addAttachment(path: String) { val list = arrayListOf() list.addAll(attachments.value.orEmpty()) - list.add(ChatMessageAttachmentViewModel(path, FileUtils.isExtensionImage(path)) { + list.add(ChatMessageAttachmentViewModel(path) { removeAttachment(it) }) attachments.value = list diff --git a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt index 7d7e6112e..63306bc35 100644 --- a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt +++ b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt @@ -20,6 +20,7 @@ package org.linphone.utils import android.content.Context +import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.net.Uri import android.text.Editable @@ -54,6 +55,11 @@ fun ImageView.setSourceImageResource(resource: Int) { this.setImageResource(resource) } +@BindingAdapter("android:src") +fun ImageView.setSourceImageBitmap(bitmap: Bitmap?) { + if (bitmap != null) this.setImageBitmap(bitmap) +} + @BindingAdapter("android:contentDescription") fun ImageView.setContentDescription(resource: Int) { if (resource == 0) { diff --git a/app/src/main/java/org/linphone/utils/FileUtils.kt b/app/src/main/java/org/linphone/utils/FileUtils.kt index b9d58b750..e1f73b42a 100644 --- a/app/src/main/java/org/linphone/utils/FileUtils.kt +++ b/app/src/main/java/org/linphone/utils/FileUtils.kt @@ -23,6 +23,7 @@ import android.content.Context import android.net.Uri import android.os.Environment import android.provider.OpenableColumns +import android.webkit.MimeTypeMap import androidx.core.content.FileProvider import java.io.* import java.text.SimpleDateFormat @@ -37,13 +38,6 @@ import org.linphone.core.tools.Log class FileUtils { companion object { - fun getMimeFromFile(path: String?): String? { - val filePath = path ?: "" - return if (isExtensionImage(filePath)) { - "image/" + getExtensionFromFileName(filePath) - } else "file/" + getExtensionFromFileName(filePath) - } - fun getNameFromFilePath(filePath: String): String { var name = filePath val i = filePath.lastIndexOf('/') @@ -54,17 +48,19 @@ class FileUtils { } fun getExtensionFromFileName(fileName: String): String { - var extension = "" - val i = fileName.lastIndexOf('.') - if (i > 0) { - extension = fileName.substring(i + 1) - } - return extension + return MimeTypeMap.getFileExtensionFromUrl(fileName) } fun isExtensionImage(path: String): Boolean { val extension = getExtensionFromFileName(path).toLowerCase(Locale.getDefault()) - return extension.matches(Regex("(png|jpg|jpeg|bmp|gif)")) + val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) + return type?.startsWith("image/") ?: false + } + + fun isExtensionVideo(path: String): Boolean { + val extension = getExtensionFromFileName(path).toLowerCase(Locale.getDefault()) + val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) + return type?.startsWith("video/") ?: false } fun getFileStorageDir(isPicture: Boolean = false): File { diff --git a/app/src/main/java/org/linphone/utils/ImageUtils.kt b/app/src/main/java/org/linphone/utils/ImageUtils.kt index 563c71f62..d277f15de 100644 --- a/app/src/main/java/org/linphone/utils/ImageUtils.kt +++ b/app/src/main/java/org/linphone/utils/ImageUtils.kt @@ -21,6 +21,7 @@ package org.linphone.utils import android.content.Context import android.graphics.* +import android.media.ThumbnailUtils import android.net.Uri import android.provider.MediaStore @@ -62,6 +63,10 @@ class ImageUtils { return rotatedBitmap } + fun getVideoPreview(path: String): Bitmap? { + return ThumbnailUtils.createVideoThumbnail(path, MediaStore.Images.Thumbnails.MINI_KIND) + } + private fun getRoundBitmap(bitmap: Bitmap): Bitmap? { val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888) diff --git a/app/src/main/res/layout/chat_message_attachment_cell.xml b/app/src/main/res/layout/chat_message_attachment_cell.xml index 420fcd181..5ff0171ab 100644 --- a/app/src/main/res/layout/chat_message_attachment_cell.xml +++ b/app/src/main/res/layout/chat_message_attachment_cell.xml @@ -34,9 +34,35 @@ android:layout_alignRight="@id/pendingImageForUpload" android:src="@drawable/clean_field" /> + + + + + + + + + +