Reworked a bit the code handling the file type depending on it's extension + added error logs when Coil fails to load an image

This commit is contained in:
Sylvain Berfini 2023-01-10 15:51:51 +01:00
parent 752ea34328
commit 4f7e4c9cd8
7 changed files with 91 additions and 44 deletions

View file

@ -19,6 +19,7 @@
*/
package org.linphone.activities.main.chat.data
import android.webkit.MimeTypeMap
import org.linphone.utils.FileUtils
class ChatMessageAttachmentData(
@ -26,10 +27,19 @@ class ChatMessageAttachmentData(
private val deleteCallback: (attachment: ChatMessageAttachmentData) -> Unit
) {
val fileName: String = FileUtils.getNameFromFilePath(path)
val isImage: Boolean = FileUtils.isExtensionImage(path)
val isVideo: Boolean = FileUtils.isExtensionVideo(path)
val isAudio: Boolean = FileUtils.isExtensionAudio(path)
val isPdf: Boolean = FileUtils.isExtensionPdf(path)
val isImage: Boolean
val isVideo: Boolean
val isAudio: Boolean
val isPdf: Boolean
init {
val extension = FileUtils.getExtensionFromFileName(path)
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
isImage = FileUtils.isMimeImage(mime)
isVideo = FileUtils.isMimeVideo(mime)
isAudio = FileUtils.isMimeAudio(mime)
isPdf = FileUtils.isMimePdf(mime)
}
fun delete() {
deleteCallback(this)

View file

@ -23,6 +23,7 @@ import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
import android.text.style.UnderlineSpan
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.media.AudioFocusRequestCompat
@ -259,12 +260,23 @@ class ChatMessageContentData(
isConferenceSchedule.value = isConferenceIcs
if (path.isNotEmpty()) {
Log.i("[Content] Found displayable content: $path")
filePath.value = path
isImage.value = FileUtils.isExtensionImage(path)
isVideo.value = FileUtils.isExtensionVideo(path) && !isVoiceRecord
isAudio.value = FileUtils.isExtensionAudio(path) && !isVoiceRecord
isPdf.value = FileUtils.isExtensionPdf(path)
val extension = FileUtils.getExtensionFromFileName(path)
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
isImage.value = FileUtils.isMimeImage(mime)
isVideo.value = FileUtils.isMimeVideo(mime) && !isVoiceRecord
isAudio.value = FileUtils.isMimeAudio(mime) && !isVoiceRecord
isPdf.value = FileUtils.isMimePdf(mime)
val type = when {
isImage.value == true -> "image"
isVideo.value == true -> "video"
isAudio.value == true -> "audio"
isPdf.value == true -> "pdf"
isVoiceRecord -> "voice recording"
isConferenceIcs -> "conference invitation"
else -> "unknown"
}
Log.i("[Content] Extension for file [$path] is [$extension], deduced type from MIME is [$type]")
if (isVoiceRecord) {
val duration = content.fileDuration // duration is in ms
@ -288,10 +300,12 @@ class ChatMessageContentData(
}
} else if (content.isFileTransfer) {
downloadable.value = true
isImage.value = FileUtils.isExtensionImage(fileName.value!!)
isVideo.value = FileUtils.isExtensionVideo(fileName.value!!)
isAudio.value = FileUtils.isExtensionAudio(fileName.value!!)
isPdf.value = FileUtils.isExtensionPdf(fileName.value!!)
val extension = FileUtils.getExtensionFromFileName(fileName.value!!)
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
isImage.value = FileUtils.isMimeImage(mime)
isVideo.value = FileUtils.isMimeVideo(mime)
isAudio.value = FileUtils.isMimeAudio(mime)
isPdf.value = FileUtils.isMimePdf(mime)
isVoiceRecording.value = false
isConferenceSchedule.value = false
} else if (content.isIcalendar) {

View file

@ -29,6 +29,7 @@ import android.os.Parcelable
import android.provider.MediaStore
import android.view.*
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.webkit.MimeTypeMap
import android.widget.PopupWindow
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
@ -457,20 +458,23 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
if (corePreferences.useInAppFileViewerForNonEncryptedFiles || content.isFileEncrypted) {
val preventScreenshots =
viewModel.chatRoom.currentParams.isEncryptionEnabled
val extension = FileUtils.getExtensionFromFileName(path)
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
when {
FileUtils.isExtensionImage(path) -> navigateToImageFileViewer(
FileUtils.isMimeImage(mime) -> navigateToImageFileViewer(
preventScreenshots
)
FileUtils.isExtensionVideo(path) -> navigateToVideoFileViewer(
FileUtils.isMimeVideo(mime) -> navigateToVideoFileViewer(
preventScreenshots
)
FileUtils.isExtensionAudio(path) -> navigateToAudioFileViewer(
FileUtils.isMimeAudio(mime) -> navigateToAudioFileViewer(
preventScreenshots
)
FileUtils.isExtensionPdf(path) -> navigateToPdfFileViewer(
FileUtils.isMimePdf(mime) -> navigateToPdfFileViewer(
preventScreenshots
)
FileUtils.isPlainTextFile(path) -> navigateToTextFileViewer(
FileUtils.isMimePlainText(mime) -> navigateToTextFileViewer(
preventScreenshots
)
else -> {

View file

@ -21,6 +21,7 @@ package org.linphone.activities.main.files.fragments
import android.os.Bundle
import android.view.View
import android.webkit.MimeTypeMap
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@ -89,8 +90,10 @@ class TopBarFragment : GenericFragment<FileViewerTopBarFragmentBinding>() {
val filePath = content.filePath.orEmpty()
Log.i("[File Viewer] Trying to export file [$filePath] through Media Store API")
val extension = FileUtils.getExtensionFromFileName(filePath)
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
when {
FileUtils.isExtensionImage(filePath) -> {
FileUtils.isMimeImage(mime) -> {
val export = lifecycleScope.async {
Compatibility.addImageToMediaStore(requireContext(), content)
}
@ -101,7 +104,7 @@ class TopBarFragment : GenericFragment<FileViewerTopBarFragmentBinding>() {
Log.e("[File Viewer] Something went wrong while copying file to Media Store...")
}
}
FileUtils.isExtensionVideo(filePath) -> {
FileUtils.isMimeVideo(mime) -> {
val export = lifecycleScope.async {
Compatibility.addVideoToMediaStore(requireContext(), content)
}
@ -112,7 +115,7 @@ class TopBarFragment : GenericFragment<FileViewerTopBarFragmentBinding>() {
Log.e("[File Viewer] Something went wrong while copying file to Media Store...")
}
}
FileUtils.isExtensionAudio(filePath) -> {
FileUtils.isMimeAudio(mime) -> {
val export = lifecycleScope.async {
Compatibility.addAudioToMediaStore(requireContext(), content)
}

View file

@ -31,6 +31,7 @@ import android.telephony.TelephonyManager
import android.util.Base64
import android.util.Pair
import android.view.*
import android.webkit.MimeTypeMap
import androidx.emoji.bundled.BundledEmojiCompatConfig
import androidx.emoji.text.EmojiCompat
import androidx.lifecycle.*
@ -894,22 +895,24 @@ class CoreContext(
val filePath = content.filePath.orEmpty()
Log.i("[Context] Trying to export file [$filePath] through Media Store API")
val extension = FileUtils.getExtensionFromFileName(filePath)
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
when {
FileUtils.isExtensionImage(filePath) -> {
FileUtils.isMimeImage(mime) -> {
if (Compatibility.addImageToMediaStore(context, content)) {
Log.i("[Context] Successfully exported image [${content.name}] to Media Store")
} else {
Log.e("[Context] Something went wrong while copying file to Media Store...")
}
}
FileUtils.isExtensionVideo(filePath) -> {
FileUtils.isMimeVideo(mime) -> {
if (Compatibility.addVideoToMediaStore(context, content)) {
Log.i("[Context] Successfully exported video [${content.name}] to Media Store")
} else {
Log.e("[Context] Something went wrong while copying file to Media Store...")
}
}
FileUtils.isExtensionAudio(filePath) -> {
FileUtils.isMimeAudio(mime) -> {
if (Compatibility.addAudioToMediaStore(context, content)) {
Log.i("[Context] Successfully exported audio [${content.name}] to Media Store")
} else {

View file

@ -326,11 +326,22 @@ fun loadImageWithCoil(imageView: ImageView, path: String?) {
if (corePreferences.vfsEnabled && path.endsWith(FileUtils.VFS_PLAIN_FILE_EXTENSION)) {
imageView.load(path) {
diskCachePolicy(CachePolicy.DISABLED)
listener(
onError = { _, result ->
Log.e("[Data Binding] [Coil] Error loading [$path]: ${result.throwable}")
}
)
}
} else {
imageView.load(path)
imageView.load(path) {
listener(
onError = { _, result ->
Log.e("[Data Binding] [Coil] Error loading [$path]: ${result.throwable}")
}
)
}
}
} else {
} else if (path != null) {
Log.w("[Data Binding] [Coil] Can't load $path")
}
}
@ -466,8 +477,8 @@ fun loadAvatarWithCoil(imageView: ImageView, path: String?) {
imageView.load(path) {
transformations(CircleCropTransformation())
listener(
onError = { _, _ ->
Log.w("[Data Binding] [Coil] Can't load $path")
onError = { _, result ->
Log.e("[Data Binding] [Coil] Error loading [$path]: ${result.throwable}")
imageView.visibility = View.GONE
},
onSuccess = { _, _ ->

View file

@ -66,39 +66,41 @@ class FileUtils {
}
}
return extension
return extension.lowercase(Locale.getDefault())
}
fun isPlainTextFile(path: String): Boolean {
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
fun isMimePlainText(type: String?): Boolean {
return type?.startsWith("text/plain") ?: false
}
fun isExtensionPdf(path: String): Boolean {
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
fun isMimePdf(type: String?): Boolean {
return type?.startsWith("application/pdf") ?: false
}
fun isExtensionImage(path: String): Boolean {
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
fun isMimeImage(type: String?): Boolean {
return type?.startsWith("image/") ?: false
}
fun isExtensionVideo(path: String): Boolean {
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
fun isMimeVideo(type: String?): Boolean {
return type?.startsWith("video/") ?: false
}
fun isExtensionAudio(path: String): Boolean {
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
fun isMimeAudio(type: String?): Boolean {
return type?.startsWith("audio/") ?: false
}
fun isExtensionImage(path: String): Boolean {
val extension = getExtensionFromFileName(path)
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
return isMimeImage(type)
}
fun isExtensionVideo(path: String): Boolean {
val extension = getExtensionFromFileName(path)
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
return isMimeVideo(type)
}
fun clearExistingPlainFiles() {
for (file in coreContext.context.filesDir.listFiles().orEmpty()) {
if (file.path.endsWith(VFS_PLAIN_FILE_EXTENSION)) {