From d165b04307703dc09c31ce9eb22e7ff210a57d6a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 1 Apr 2021 16:47:54 +0200 Subject: [PATCH] Changes to prepare for VFS --- .../chat_bubble/ChatBubbleActivity.kt | 50 +++---------------- .../chat/adapters/ChatMessagesListAdapter.kt | 9 ++-- .../chat/fragments/DetailChatRoomFragment.kt | 47 ++++++++++++----- .../viewmodels/ChatMessageContentViewModel.kt | 4 +- .../files/fragments/ImageViewerFragment.kt | 6 ++- .../main/files/fragments/PdfViewerFragment.kt | 6 ++- .../files/fragments/TextViewerFragment.kt | 6 ++- .../main/files/fragments/TopBarFragment.kt | 42 ++++++++++------ .../files/fragments/VideoViewerFragment.kt | 6 ++- .../main/viewmodels/SharedMainViewModel.kt | 2 +- .../java/org/linphone/core/CorePreferences.kt | 6 +++ .../main/java/org/linphone/utils/FileUtils.kt | 9 +++- app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 14 files changed, 110 insertions(+), 85 deletions(-) diff --git a/app/src/main/java/org/linphone/activities/chat_bubble/ChatBubbleActivity.kt b/app/src/main/java/org/linphone/activities/chat_bubble/ChatBubbleActivity.kt index fca5cac5f..6603f4119 100644 --- a/app/src/main/java/org/linphone/activities/chat_bubble/ChatBubbleActivity.kt +++ b/app/src/main/java/org/linphone/activities/chat_bubble/ChatBubbleActivity.kt @@ -19,11 +19,9 @@ */ package org.linphone.activities.chat_bubble -import android.content.ActivityNotFoundException import android.content.Intent -import android.net.Uri import android.os.Bundle -import android.webkit.MimeTypeMap +import android.widget.Toast import androidx.databinding.DataBindingUtil import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope @@ -31,7 +29,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.linphone.LinphoneApplication import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.activities.GenericActivity @@ -113,8 +110,12 @@ class ChatBubbleActivity : GenericActivity() { adapter.disableContextMenu() adapter.openContentEvent.observe(this, { - it.consume { path -> - openFile(path) + it.consume { content -> + if (content.isFileEncrypted) { + Toast.makeText(this, R.string.chat_bubble_cant_open_enrypted_file, Toast.LENGTH_LONG).show() + } else { + FileUtils.openFileInThirdPartyApp(this, content.filePath.orEmpty(), true) + } } }) @@ -174,41 +175,4 @@ class ChatBubbleActivity : GenericActivity() { binding.chatMessagesList.scrollToPosition(adapter.itemCount - 1) } } - - private fun openFile(contentFilePath: String) { - val intent = Intent(Intent.ACTION_VIEW) - val contentUri: Uri = FileUtils.getPublicFilePath(this, contentFilePath) - val filePath: String = contentUri.toString() - Log.i("[Chat Bubble] Trying to open file: $filePath") - var type: String? = null - val extension = FileUtils.getExtensionFromFileName(filePath) - - if (extension.isNotEmpty()) { - Log.i("[Chat Bubble] Found extension $extension") - type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) - } else { - Log.e("[Chat Bubble] Couldn't find extension") - } - - if (type != null) { - Log.i("[Chat Bubble] Found matching MIME type $type") - } else { - type = "file/$extension" - Log.e("[Chat Bubble] Can't get MIME type from extension: $extension, will use $type") - } - - intent.setDataAndType(contentUri, type) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - - try { - startActivity(intent) - - if (LinphoneApplication.corePreferences.enableAnimations) { - overridePendingTransition(R.anim.enter_right, R.anim.exit_left) - } - } catch (anfe: ActivityNotFoundException) { - Log.e("[Chat Bubble] Couldn't find an activity to handle MIME type: $type") - } - } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt index d7c0638f2..87a75e65f 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt @@ -40,6 +40,7 @@ import org.linphone.activities.main.chat.viewmodels.OnContentClickedListener import org.linphone.activities.main.viewmodels.ListTopBarViewModel import org.linphone.core.ChatMessage import org.linphone.core.ChatRoomCapabilities +import org.linphone.core.Content import org.linphone.core.EventLog import org.linphone.databinding.ChatEventListCellBinding import org.linphone.databinding.ChatMessageListCellBinding @@ -73,13 +74,13 @@ class ChatMessagesListAdapter( MutableLiveData>() } - val openContentEvent: MutableLiveData> by lazy { - MutableLiveData>() + val openContentEvent: MutableLiveData> by lazy { + MutableLiveData>() } private val contentClickedListener = object : OnContentClickedListener { - override fun onContentClicked(path: String) { - openContentEvent.value = Event(path) + override fun onContentClicked(content: Content) { + openContentEvent.value = Event(content) } } 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 0bed56ddb..a74d6f37a 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 @@ -222,24 +222,47 @@ class DetailChatRoomFragment : MasterFragment + it.consume { content -> + val path = content.filePath.orEmpty() + if (!File(path).exists()) { (requireActivity() as MainActivity).showSnackBar(R.string.chat_room_file_not_found) } else { Log.i("[Chat Message] Opening file: $path") - sharedViewModel.fileToOpen.value = path - val preventScreenshots = viewModel.chatRoom.currentParams.encryptionEnabled() - when { - FileUtils.isExtensionImage(path) -> navigateToImageFileViewer(preventScreenshots) - FileUtils.isExtensionVideo(path) -> navigateToVideoFileViewer(preventScreenshots) - FileUtils.isExtensionAudio(path) -> navigateToAudioFileViewer(preventScreenshots) - FileUtils.isExtensionPdf(path) -> navigateToPdfFileViewer(preventScreenshots) - FileUtils.isPlainTextFile(path) -> navigateToTextFileViewer(preventScreenshots) - else -> { - if (!FileUtils.openFileInThirdPartyApp(requireActivity(), path)) { - showDialogToSuggestOpeningFileAsText() + sharedViewModel.contentToOpen.value = content + + if (corePreferences.useInAppFileViewerForNonEncryptedFiles || content.isFileEncrypted) { + val preventScreenshots = + viewModel.chatRoom.currentParams.encryptionEnabled() + when { + FileUtils.isExtensionImage(path) -> navigateToImageFileViewer( + preventScreenshots + ) + FileUtils.isExtensionVideo(path) -> navigateToVideoFileViewer( + preventScreenshots + ) + FileUtils.isExtensionAudio(path) -> navigateToAudioFileViewer( + preventScreenshots + ) + FileUtils.isExtensionPdf(path) -> navigateToPdfFileViewer( + preventScreenshots + ) + FileUtils.isPlainTextFile(path) -> navigateToTextFileViewer( + preventScreenshots + ) + else -> { + if (content.isFileEncrypted) { + Log.w("[Chat Message] File is encrypted and can't be opened in one of our viewers...") + // TODO: show dialog to ask user for consent before trying to export the file first + } else if (!FileUtils.openFileInThirdPartyApp(requireActivity(), path)) { + showDialogToSuggestOpeningFileAsText() + } } } + } else { + if (!FileUtils.openFileInThirdPartyApp(requireActivity(), path)) { + showDialogToSuggestOpeningFileAsText() + } } } } 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 92940ad98..c237265f1 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 @@ -146,10 +146,10 @@ class ChatMessageContentViewModel( } fun openFile() { - listener?.onContentClicked(content.filePath.orEmpty()) + listener?.onContentClicked(content) } } interface OnContentClickedListener { - fun onContentClicked(path: String) + fun onContentClicked(content: Content) } diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/ImageViewerFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/ImageViewerFragment.kt index a6277eac3..b257e8755 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/ImageViewerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/ImageViewerFragment.kt @@ -45,11 +45,13 @@ class ImageViewerFragment : SecureFragment() { ViewModelProvider(this).get(SharedMainViewModel::class.java) } - val filePath = sharedViewModel.fileToOpen.value + val content = sharedViewModel.contentToOpen.value + content ?: return + val filePath = content.filePath filePath ?: return (childFragmentManager.findFragmentById(R.id.top_bar_fragment) as? TopBarFragment) - ?.setFilePath(filePath) + ?.setContent(content) viewModel = ViewModelProvider( this, diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/PdfViewerFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/PdfViewerFragment.kt index a6e4e7943..fd8139b89 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/PdfViewerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/PdfViewerFragment.kt @@ -45,11 +45,13 @@ class PdfViewerFragment : SecureFragment() { ViewModelProvider(this).get(SharedMainViewModel::class.java) } - val filePath = sharedViewModel.fileToOpen.value + val content = sharedViewModel.contentToOpen.value + content ?: return + val filePath = content.filePath filePath ?: return (childFragmentManager.findFragmentById(R.id.top_bar_fragment) as? TopBarFragment) - ?.setFilePath(filePath) + ?.setContent(content) viewModel = ViewModelProvider( this, diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/TextViewerFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/TextViewerFragment.kt index 5ced40461..486e54d90 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/TextViewerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/TextViewerFragment.kt @@ -43,11 +43,13 @@ class TextViewerFragment : SecureFragment() { ViewModelProvider(this).get(SharedMainViewModel::class.java) } - val filePath = sharedViewModel.fileToOpen.value + val content = sharedViewModel.contentToOpen.value + content ?: return + val filePath = content.filePath filePath ?: return (childFragmentManager.findFragmentById(R.id.top_bar_fragment) as? TopBarFragment) - ?.setFilePath(filePath) + ?.setContent(content) viewModel = ViewModelProvider( this, diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt index 92dabf6cc..b377e4a5c 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/TopBarFragment.kt @@ -24,12 +24,14 @@ import androidx.navigation.fragment.findNavController import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.SnackBarActivity +import org.linphone.core.Content import org.linphone.core.tools.Log import org.linphone.databinding.FileViewerTopBarFragmentBinding import org.linphone.utils.FileUtils class TopBarFragment : GenericFragment() { - private var filePath: String = "" + private var content: Content? = null + private var plainFilePath: String = "" override fun getLayoutId(): Int = R.layout.file_viewer_top_bar_fragment @@ -43,24 +45,36 @@ class TopBarFragment : GenericFragment() { } binding.setExportClickListener { - if (!FileUtils.openFileInThirdPartyApp(requireActivity(), filePath)) { - (requireActivity() as SnackBarActivity).showSnackBar(R.string.chat_message_no_app_found_to_handle_file_mime_type) + if (content != null) { + val filePath = content?.plainFilePath.orEmpty() + plainFilePath = if (filePath.isEmpty()) content?.filePath.orEmpty() else filePath + Log.i("[File Viewer] Plain file path is: $filePath") + if (plainFilePath.isNotEmpty()) { + if (!FileUtils.openFileInThirdPartyApp(requireActivity(), plainFilePath)) { + (requireActivity() as SnackBarActivity).showSnackBar(R.string.chat_message_no_app_found_to_handle_file_mime_type) + if (plainFilePath != content?.filePath.orEmpty()) { + Log.i("[File Viewer] No app to open plain file path: $plainFilePath, destroying it") + FileUtils.deleteFile(plainFilePath) + } + plainFilePath = "" + } + } + } else { + Log.e("[File Viewer] No Content set!") } } } - fun setFilePath(newFilePath: String) { - Log.i("[File Viewer] File path is: $newFilePath") - filePath = newFilePath + override fun onDestroyView() { + if (plainFilePath.isNotEmpty() && plainFilePath != content?.filePath.orEmpty()) { + Log.i("[File Viewer] Destroying plain file path: $plainFilePath") + FileUtils.deleteFile(plainFilePath) + } + super.onDestroyView() } - override fun onSaveInstanceState(outState: Bundle) { - outState.putString("FilePath", filePath) - super.onSaveInstanceState(outState) - } - - override fun onViewStateRestored(savedInstanceState: Bundle?) { - super.onViewStateRestored(savedInstanceState) - filePath = savedInstanceState?.getString("FilePath") ?: filePath + fun setContent(c: Content) { + Log.i("[File Viewer] Content file path is: ${c.filePath}") + content = c } } diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt index 162c41109..1a29a48ec 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt @@ -47,11 +47,13 @@ class VideoViewerFragment : SecureFragment() { ViewModelProvider(this).get(SharedMainViewModel::class.java) } - val filePath = sharedViewModel.fileToOpen.value + val content = sharedViewModel.contentToOpen.value + content ?: return + val filePath = content.filePath filePath ?: return (childFragmentManager.findFragmentById(R.id.top_bar_fragment) as? TopBarFragment) - ?.setFilePath(filePath) + ?.setContent(content) viewModel = ViewModelProvider( this, diff --git a/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt b/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt index abbb9a8b4..fa0f1ed09 100644 --- a/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt @@ -48,7 +48,7 @@ class SharedMainViewModel : ViewModel() { MutableLiveData>() } - val fileToOpen = MutableLiveData() + val contentToOpen = MutableLiveData() var createEncryptedChatRoom: Boolean = false diff --git a/app/src/main/java/org/linphone/core/CorePreferences.kt b/app/src/main/java/org/linphone/core/CorePreferences.kt index dd3065e71..5f387c6c7 100644 --- a/app/src/main/java/org/linphone/core/CorePreferences.kt +++ b/app/src/main/java/org/linphone/core/CorePreferences.kt @@ -128,6 +128,12 @@ class CorePreferences constructor(private val context: Context) { config.setBool("app", "make_downloaded_images_public_in_gallery", value) } + var useInAppFileViewerForNonEncryptedFiles: Boolean + get() = config.getBool("app", "use_in_app_file_viewer_for_non_encrypted_files", true) + set(value) { + config.setBool("app", "use_in_app_file_viewer_for_non_encrypted_files", value) + } + var hideChatMessageContentInNotification: Boolean get() = config.getBool("app", "hide_chat_message_content_in_notification", false) set(value) { diff --git a/app/src/main/java/org/linphone/utils/FileUtils.kt b/app/src/main/java/org/linphone/utils/FileUtils.kt index 7d47afba1..50438a2fc 100644 --- a/app/src/main/java/org/linphone/utils/FileUtils.kt +++ b/app/src/main/java/org/linphone/utils/FileUtils.kt @@ -297,7 +297,11 @@ class FileUtils { return contentUri } - fun openFileInThirdPartyApp(activity: Activity, contentFilePath: String): Boolean { + fun openFileInThirdPartyApp( + activity: Activity, + contentFilePath: String, + newTask: Boolean = false + ): Boolean { val intent = Intent(Intent.ACTION_VIEW) val contentUri: Uri = getPublicFilePath(activity, contentFilePath) val filePath: String = contentUri.toString() @@ -321,6 +325,9 @@ class FileUtils { intent.setDataAndType(contentUri, type) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + if (newTask) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } try { activity.startActivity(intent) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8232bbf82..3eb9950a5 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -568,4 +568,5 @@ Ouvrir les conversations dans l\'application au lieu de la bulle Ouvrir le fichier dans une application tierce Aucune application n\'est disponible pour ouvrir ce type de fichier + Impossible d\'ouvrir un fichier chiffré dans la bulle de conversation \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 72c5dd7be..4672b04e4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -201,6 +201,7 @@ <Redacted> No app available for this kind of file + Can\'t open encrypted file in chat bubble No recordings