From 55f5f90c45b060cbf25565b0b9969a91c3ed7324 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Thu, 7 Jan 2021 19:32:04 +0300 Subject: [PATCH] Use ContentResolver and DocumentFile instead of legacy File. Fixes #409. --- CHANGES.md | 1 + .../vector/app/core/glide/MyAppGlideModule.kt | 2 +- .../app/core/glide/VectorGlideModelLoader.kt | 24 ++++++++++++------- .../im/vector/app/core/utils/FileUtils.kt | 16 ++++++++++++- .../timeline/factory/MessageItemFactory.kt | 12 ++++++---- .../timeline/item/MessageImageVideoItem.kt | 3 ++- .../features/media/ImageContentRenderer.kt | 7 +++--- .../features/media/VideoContentRenderer.kt | 8 ++++--- 8 files changed, 51 insertions(+), 22 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7d4678fe40..a92a0e6d09 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Bugfix 🐛: - Url previews sometimes attached to wrong message (#2561) - Hiding membership events works the exact opposite (#2603) - Tapping drawer having more than 1 room in notifications gives "malformed link" error (#2605) + - Sent image not displayed when opened immediately after sending (#409) Translations 🗣: - diff --git a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt index a51410165b..d73c64b087 100644 --- a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt +++ b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt @@ -38,6 +38,6 @@ class MyAppGlideModule : AppGlideModule() { override fun registerComponents(context: Context, glide: Glide, registry: Registry) { registry.append(ImageContentRenderer.Data::class.java, InputStream::class.java, - VectorGlideModelLoaderFactory(context.vectorComponent().activeSessionHolder())) + VectorGlideModelLoaderFactory(context, context.vectorComponent().activeSessionHolder())) } } diff --git a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt index 9a7cf1eb76..600ed0317e 100644 --- a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt +++ b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt @@ -16,6 +16,7 @@ package im.vector.app.core.glide +import android.content.Context import com.bumptech.glide.Priority import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.Options @@ -25,6 +26,8 @@ import com.bumptech.glide.load.model.ModelLoaderFactory import com.bumptech.glide.load.model.MultiModelLoaderFactory import com.bumptech.glide.signature.ObjectKey import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.utils.isLocalFile +import im.vector.app.core.utils.openInputStream import im.vector.app.features.media.ImageContentRenderer import okhttp3.OkHttpClient import org.matrix.android.sdk.api.MatrixCallback @@ -33,11 +36,12 @@ import java.io.File import java.io.IOException import java.io.InputStream -class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessionHolder) - : ModelLoaderFactory { +class VectorGlideModelLoaderFactory(private val context: Context, + private val activeSessionHolder: ActiveSessionHolder +) : ModelLoaderFactory { override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { - return VectorGlideModelLoader(activeSessionHolder) + return VectorGlideModelLoader(context, activeSessionHolder) } override fun teardown() { @@ -45,7 +49,7 @@ class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessi } } -class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolder) +class VectorGlideModelLoader(private val context: Context, private val activeSessionHolder: ActiveSessionHolder) : ModelLoader { override fun handles(model: ImageContentRenderer.Data): Boolean { // Always handle @@ -53,11 +57,12 @@ class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolde } override fun buildLoadData(model: ImageContentRenderer.Data, width: Int, height: Int, options: Options): ModelLoader.LoadData? { - return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(activeSessionHolder, model, width, height)) + return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(context, activeSessionHolder, model, width, height)) } } -class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolder, +class VectorGlideDataFetcher(private val context: Context, + private val activeSessionHolder: ActiveSessionHolder, private val data: ImageContentRenderer.Data, private val width: Int, private val height: Int) @@ -97,9 +102,10 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde override fun loadData(priority: Priority, callback: DataFetcher.DataCallback) { Timber.v("Load data: $data") - if (data.isLocalFile && data.url != null) { - val initialFile = File(data.url) - callback.onDataReady(initialFile.inputStream()) + if (data.url.isLocalFile(context)) { + data.url.openInputStream(context)?.use { + callback.onDataReady(it) + } return } // val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() diff --git a/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt b/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt index aa36dd0959..2be06c09a5 100644 --- a/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/FileUtils.kt @@ -17,14 +17,28 @@ package im.vector.app.core.utils import android.content.Context +import android.net.Uri +import androidx.documentfile.provider.DocumentFile +import org.matrix.android.sdk.api.extensions.orFalse import timber.log.Timber import java.io.File +import java.io.InputStream import java.util.Locale // Implementation should return true in case of success typealias ActionOnFile = (file: File) -> Boolean -internal fun String?.isLocalFile() = this != null && File(this).exists() +internal fun String?.isLocalFile(context: Context): Boolean { + return this?.let { + DocumentFile.fromSingleUri(context, Uri.parse(it))?.exists() + }.orFalse() +} + +internal fun String?.openInputStream(context: Context): InputStream? { + return if (isLocalFile(context)) { + context.contentResolver.openInputStream(Uri.parse(this)) + } else null +} /* ========================================================================================== * Delete diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index a1e041b98f..3dea83032c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.detail.timeline.factory +import android.content.Context import android.text.SpannableStringBuilder import android.text.Spanned import android.text.TextPaint @@ -94,6 +95,7 @@ import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent import javax.inject.Inject class MessageItemFactory @Inject constructor( + private val context: Context, private val colorProvider: ColorProvider, private val dimensionConverter: DimensionConverter, private val timelineMediaSizeProvider: TimelineMediaSizeProvider, @@ -205,7 +207,7 @@ class MessageItemFactory @Inject constructor( } ?: "" return MessageFileItem_() .attributes(attributes) - .izLocalFile(fileUrl.isLocalFile()) + .izLocalFile(fileUrl.isLocalFile(context)) .izDownloaded(session.fileService().isFileInCache( fileUrl, messageContent.getFileName(), @@ -270,7 +272,7 @@ class MessageItemFactory @Inject constructor( return MessageFileItem_() .attributes(attributes) .leftGuideline(avatarSizeProvider.leftGuideline) - .izLocalFile(messageContent.getFileUrl().isLocalFile()) + .izLocalFile(messageContent.getFileUrl().isLocalFile(context)) .izDownloaded(session.fileService().isFileInCache(messageContent)) .mxcUrl(mxcUrl) .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) @@ -305,7 +307,8 @@ class MessageItemFactory @Inject constructor( height = messageContent.info?.height, maxHeight = maxHeight, width = messageContent.info?.width, - maxWidth = maxWidth + maxWidth = maxWidth, + allowNonMxcUrls = informationData.sendState.isSending() ) return MessageImageVideoItem_() .attributes(attributes) @@ -343,7 +346,8 @@ class MessageItemFactory @Inject constructor( height = messageContent.videoInfo?.height, maxHeight = maxHeight, width = messageContent.videoInfo?.width, - maxWidth = maxWidth + maxWidth = maxWidth, + allowNonMxcUrls = informationData.sendState.isSending() ) val videoData = VideoContentRenderer.Data( diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt index 98db0bc9b9..a8d5ed1631 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt @@ -26,6 +26,7 @@ import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.glide.GlideApp +import im.vector.app.core.utils.isLocalFile import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.session.room.send.SendState @@ -55,7 +56,7 @@ abstract class MessageImageVideoItem : AbsMessageItem