mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-19 16:08:29 +00:00
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:
parent
752ea34328
commit
4f7e4c9cd8
7 changed files with 91 additions and 44 deletions
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.main.chat.data
|
package org.linphone.activities.main.chat.data
|
||||||
|
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import org.linphone.utils.FileUtils
|
import org.linphone.utils.FileUtils
|
||||||
|
|
||||||
class ChatMessageAttachmentData(
|
class ChatMessageAttachmentData(
|
||||||
|
|
@ -26,10 +27,19 @@ class ChatMessageAttachmentData(
|
||||||
private val deleteCallback: (attachment: ChatMessageAttachmentData) -> Unit
|
private val deleteCallback: (attachment: ChatMessageAttachmentData) -> Unit
|
||||||
) {
|
) {
|
||||||
val fileName: String = FileUtils.getNameFromFilePath(path)
|
val fileName: String = FileUtils.getNameFromFilePath(path)
|
||||||
val isImage: Boolean = FileUtils.isExtensionImage(path)
|
val isImage: Boolean
|
||||||
val isVideo: Boolean = FileUtils.isExtensionVideo(path)
|
val isVideo: Boolean
|
||||||
val isAudio: Boolean = FileUtils.isExtensionAudio(path)
|
val isAudio: Boolean
|
||||||
val isPdf: Boolean = FileUtils.isExtensionPdf(path)
|
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() {
|
fun delete() {
|
||||||
deleteCallback(this)
|
deleteCallback(this)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import android.text.Spannable
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.text.style.UnderlineSpan
|
import android.text.style.UnderlineSpan
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.media.AudioFocusRequestCompat
|
import androidx.media.AudioFocusRequestCompat
|
||||||
|
|
@ -259,12 +260,23 @@ class ChatMessageContentData(
|
||||||
isConferenceSchedule.value = isConferenceIcs
|
isConferenceSchedule.value = isConferenceIcs
|
||||||
|
|
||||||
if (path.isNotEmpty()) {
|
if (path.isNotEmpty()) {
|
||||||
Log.i("[Content] Found displayable content: $path")
|
|
||||||
filePath.value = path
|
filePath.value = path
|
||||||
isImage.value = FileUtils.isExtensionImage(path)
|
val extension = FileUtils.getExtensionFromFileName(path)
|
||||||
isVideo.value = FileUtils.isExtensionVideo(path) && !isVoiceRecord
|
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
isAudio.value = FileUtils.isExtensionAudio(path) && !isVoiceRecord
|
isImage.value = FileUtils.isMimeImage(mime)
|
||||||
isPdf.value = FileUtils.isExtensionPdf(path)
|
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) {
|
if (isVoiceRecord) {
|
||||||
val duration = content.fileDuration // duration is in ms
|
val duration = content.fileDuration // duration is in ms
|
||||||
|
|
@ -288,10 +300,12 @@ class ChatMessageContentData(
|
||||||
}
|
}
|
||||||
} else if (content.isFileTransfer) {
|
} else if (content.isFileTransfer) {
|
||||||
downloadable.value = true
|
downloadable.value = true
|
||||||
isImage.value = FileUtils.isExtensionImage(fileName.value!!)
|
val extension = FileUtils.getExtensionFromFileName(fileName.value!!)
|
||||||
isVideo.value = FileUtils.isExtensionVideo(fileName.value!!)
|
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
isAudio.value = FileUtils.isExtensionAudio(fileName.value!!)
|
isImage.value = FileUtils.isMimeImage(mime)
|
||||||
isPdf.value = FileUtils.isExtensionPdf(fileName.value!!)
|
isVideo.value = FileUtils.isMimeVideo(mime)
|
||||||
|
isAudio.value = FileUtils.isMimeAudio(mime)
|
||||||
|
isPdf.value = FileUtils.isMimePdf(mime)
|
||||||
isVoiceRecording.value = false
|
isVoiceRecording.value = false
|
||||||
isConferenceSchedule.value = false
|
isConferenceSchedule.value = false
|
||||||
} else if (content.isIcalendar) {
|
} else if (content.isIcalendar) {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import android.os.Parcelable
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener
|
import android.view.ViewTreeObserver.OnGlobalLayoutListener
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
|
|
@ -457,20 +458,23 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
||||||
if (corePreferences.useInAppFileViewerForNonEncryptedFiles || content.isFileEncrypted) {
|
if (corePreferences.useInAppFileViewerForNonEncryptedFiles || content.isFileEncrypted) {
|
||||||
val preventScreenshots =
|
val preventScreenshots =
|
||||||
viewModel.chatRoom.currentParams.isEncryptionEnabled
|
viewModel.chatRoom.currentParams.isEncryptionEnabled
|
||||||
|
|
||||||
|
val extension = FileUtils.getExtensionFromFileName(path)
|
||||||
|
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
when {
|
when {
|
||||||
FileUtils.isExtensionImage(path) -> navigateToImageFileViewer(
|
FileUtils.isMimeImage(mime) -> navigateToImageFileViewer(
|
||||||
preventScreenshots
|
preventScreenshots
|
||||||
)
|
)
|
||||||
FileUtils.isExtensionVideo(path) -> navigateToVideoFileViewer(
|
FileUtils.isMimeVideo(mime) -> navigateToVideoFileViewer(
|
||||||
preventScreenshots
|
preventScreenshots
|
||||||
)
|
)
|
||||||
FileUtils.isExtensionAudio(path) -> navigateToAudioFileViewer(
|
FileUtils.isMimeAudio(mime) -> navigateToAudioFileViewer(
|
||||||
preventScreenshots
|
preventScreenshots
|
||||||
)
|
)
|
||||||
FileUtils.isExtensionPdf(path) -> navigateToPdfFileViewer(
|
FileUtils.isMimePdf(mime) -> navigateToPdfFileViewer(
|
||||||
preventScreenshots
|
preventScreenshots
|
||||||
)
|
)
|
||||||
FileUtils.isPlainTextFile(path) -> navigateToTextFileViewer(
|
FileUtils.isMimePlainText(mime) -> navigateToTextFileViewer(
|
||||||
preventScreenshots
|
preventScreenshots
|
||||||
)
|
)
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package org.linphone.activities.main.files.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
|
@ -89,8 +90,10 @@ class TopBarFragment : GenericFragment<FileViewerTopBarFragmentBinding>() {
|
||||||
val filePath = content.filePath.orEmpty()
|
val filePath = content.filePath.orEmpty()
|
||||||
Log.i("[File Viewer] Trying to export file [$filePath] through Media Store API")
|
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 {
|
when {
|
||||||
FileUtils.isExtensionImage(filePath) -> {
|
FileUtils.isMimeImage(mime) -> {
|
||||||
val export = lifecycleScope.async {
|
val export = lifecycleScope.async {
|
||||||
Compatibility.addImageToMediaStore(requireContext(), content)
|
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...")
|
Log.e("[File Viewer] Something went wrong while copying file to Media Store...")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.isExtensionVideo(filePath) -> {
|
FileUtils.isMimeVideo(mime) -> {
|
||||||
val export = lifecycleScope.async {
|
val export = lifecycleScope.async {
|
||||||
Compatibility.addVideoToMediaStore(requireContext(), content)
|
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...")
|
Log.e("[File Viewer] Something went wrong while copying file to Media Store...")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.isExtensionAudio(filePath) -> {
|
FileUtils.isMimeAudio(mime) -> {
|
||||||
val export = lifecycleScope.async {
|
val export = lifecycleScope.async {
|
||||||
Compatibility.addAudioToMediaStore(requireContext(), content)
|
Compatibility.addAudioToMediaStore(requireContext(), content)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import android.telephony.TelephonyManager
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
import android.view.*
|
import android.view.*
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.emoji.bundled.BundledEmojiCompatConfig
|
import androidx.emoji.bundled.BundledEmojiCompatConfig
|
||||||
import androidx.emoji.text.EmojiCompat
|
import androidx.emoji.text.EmojiCompat
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
|
|
@ -894,22 +895,24 @@ class CoreContext(
|
||||||
val filePath = content.filePath.orEmpty()
|
val filePath = content.filePath.orEmpty()
|
||||||
Log.i("[Context] Trying to export file [$filePath] through Media Store API")
|
Log.i("[Context] Trying to export file [$filePath] through Media Store API")
|
||||||
|
|
||||||
|
val extension = FileUtils.getExtensionFromFileName(filePath)
|
||||||
|
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||||
when {
|
when {
|
||||||
FileUtils.isExtensionImage(filePath) -> {
|
FileUtils.isMimeImage(mime) -> {
|
||||||
if (Compatibility.addImageToMediaStore(context, content)) {
|
if (Compatibility.addImageToMediaStore(context, content)) {
|
||||||
Log.i("[Context] Successfully exported image [${content.name}] to Media Store")
|
Log.i("[Context] Successfully exported image [${content.name}] to Media Store")
|
||||||
} else {
|
} else {
|
||||||
Log.e("[Context] Something went wrong while copying file to Media Store...")
|
Log.e("[Context] Something went wrong while copying file to Media Store...")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.isExtensionVideo(filePath) -> {
|
FileUtils.isMimeVideo(mime) -> {
|
||||||
if (Compatibility.addVideoToMediaStore(context, content)) {
|
if (Compatibility.addVideoToMediaStore(context, content)) {
|
||||||
Log.i("[Context] Successfully exported video [${content.name}] to Media Store")
|
Log.i("[Context] Successfully exported video [${content.name}] to Media Store")
|
||||||
} else {
|
} else {
|
||||||
Log.e("[Context] Something went wrong while copying file to Media Store...")
|
Log.e("[Context] Something went wrong while copying file to Media Store...")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.isExtensionAudio(filePath) -> {
|
FileUtils.isMimeAudio(mime) -> {
|
||||||
if (Compatibility.addAudioToMediaStore(context, content)) {
|
if (Compatibility.addAudioToMediaStore(context, content)) {
|
||||||
Log.i("[Context] Successfully exported audio [${content.name}] to Media Store")
|
Log.i("[Context] Successfully exported audio [${content.name}] to Media Store")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -326,11 +326,22 @@ fun loadImageWithCoil(imageView: ImageView, path: String?) {
|
||||||
if (corePreferences.vfsEnabled && path.endsWith(FileUtils.VFS_PLAIN_FILE_EXTENSION)) {
|
if (corePreferences.vfsEnabled && path.endsWith(FileUtils.VFS_PLAIN_FILE_EXTENSION)) {
|
||||||
imageView.load(path) {
|
imageView.load(path) {
|
||||||
diskCachePolicy(CachePolicy.DISABLED)
|
diskCachePolicy(CachePolicy.DISABLED)
|
||||||
|
listener(
|
||||||
|
onError = { _, result ->
|
||||||
|
Log.e("[Data Binding] [Coil] Error loading [$path]: ${result.throwable}")
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} 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")
|
Log.w("[Data Binding] [Coil] Can't load $path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -466,8 +477,8 @@ fun loadAvatarWithCoil(imageView: ImageView, path: String?) {
|
||||||
imageView.load(path) {
|
imageView.load(path) {
|
||||||
transformations(CircleCropTransformation())
|
transformations(CircleCropTransformation())
|
||||||
listener(
|
listener(
|
||||||
onError = { _, _ ->
|
onError = { _, result ->
|
||||||
Log.w("[Data Binding] [Coil] Can't load $path")
|
Log.e("[Data Binding] [Coil] Error loading [$path]: ${result.throwable}")
|
||||||
imageView.visibility = View.GONE
|
imageView.visibility = View.GONE
|
||||||
},
|
},
|
||||||
onSuccess = { _, _ ->
|
onSuccess = { _, _ ->
|
||||||
|
|
|
||||||
|
|
@ -66,39 +66,41 @@ class FileUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return extension
|
return extension.lowercase(Locale.getDefault())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPlainTextFile(path: String): Boolean {
|
fun isMimePlainText(type: String?): Boolean {
|
||||||
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
|
|
||||||
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
|
||||||
return type?.startsWith("text/plain") ?: false
|
return type?.startsWith("text/plain") ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isExtensionPdf(path: String): Boolean {
|
fun isMimePdf(type: String?): Boolean {
|
||||||
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
|
|
||||||
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
|
||||||
return type?.startsWith("application/pdf") ?: false
|
return type?.startsWith("application/pdf") ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isExtensionImage(path: String): Boolean {
|
fun isMimeImage(type: String?): Boolean {
|
||||||
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
|
|
||||||
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
|
||||||
return type?.startsWith("image/") ?: false
|
return type?.startsWith("image/") ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isExtensionVideo(path: String): Boolean {
|
fun isMimeVideo(type: String?): Boolean {
|
||||||
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
|
|
||||||
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
|
||||||
return type?.startsWith("video/") ?: false
|
return type?.startsWith("video/") ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isExtensionAudio(path: String): Boolean {
|
fun isMimeAudio(type: String?): Boolean {
|
||||||
val extension = getExtensionFromFileName(path).lowercase(Locale.getDefault())
|
|
||||||
val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
|
||||||
return type?.startsWith("audio/") ?: false
|
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() {
|
fun clearExistingPlainFiles() {
|
||||||
for (file in coreContext.context.filesDir.listFiles().orEmpty()) {
|
for (file in coreContext.context.filesDir.listFiles().orEmpty()) {
|
||||||
if (file.path.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
if (file.path.endsWith(VFS_PLAIN_FILE_EXTENSION)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue