mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-16 03:08:58 +03:00
Merge pull request #2629 from vector-im/feature/ons/fix_show_sending_image
Sent image not displayed when opened immediately after sending
This commit is contained in:
commit
466f9bd532
9 changed files with 81 additions and 29 deletions
|
@ -15,7 +15,9 @@ Bugfix 🐛:
|
|||
- Room Topic not displayed correctly after visiting a link (#2551)
|
||||
- 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)
|
||||
- Initial sync is not retried correctly when there is some network error. (#2632)
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.core.files
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import java.io.InputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
class LocalFilesHelper @Inject constructor(private val context: Context) {
|
||||
fun isLocalFile(fileUri: String?): Boolean {
|
||||
return fileUri
|
||||
?.let { Uri.parse(it) }
|
||||
?.let { DocumentFile.fromSingleUri(context, it) }
|
||||
?.exists()
|
||||
.orFalse()
|
||||
}
|
||||
|
||||
fun openInputStream(fileUri: String?): InputStream? {
|
||||
return fileUri
|
||||
?.takeIf { isLocalFile(it) }
|
||||
?.let { Uri.parse(it) }
|
||||
?.let { context.contentResolver.openInputStream(it) }
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@ import com.bumptech.glide.GlideBuilder
|
|||
import com.bumptech.glide.Registry
|
||||
import com.bumptech.glide.annotation.GlideModule
|
||||
import com.bumptech.glide.module.AppGlideModule
|
||||
import im.vector.app.core.extensions.vectorComponent
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
import java.io.InputStream
|
||||
|
||||
|
@ -36,8 +35,10 @@ class MyAppGlideModule : AppGlideModule() {
|
|||
}
|
||||
|
||||
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
||||
registry.append(ImageContentRenderer.Data::class.java,
|
||||
registry.append(
|
||||
ImageContentRenderer.Data::class.java,
|
||||
InputStream::class.java,
|
||||
VectorGlideModelLoaderFactory(context.vectorComponent().activeSessionHolder()))
|
||||
VectorGlideModelLoaderFactory(context)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -24,7 +25,8 @@ import com.bumptech.glide.load.model.ModelLoader
|
|||
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.extensions.vectorComponent
|
||||
import im.vector.app.core.files.LocalFilesHelper
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
|
@ -33,11 +35,10 @@ import java.io.File
|
|||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessionHolder)
|
||||
: ModelLoaderFactory<ImageContentRenderer.Data, InputStream> {
|
||||
class VectorGlideModelLoaderFactory(private val context: Context) : ModelLoaderFactory<ImageContentRenderer.Data, InputStream> {
|
||||
|
||||
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<ImageContentRenderer.Data, InputStream> {
|
||||
return VectorGlideModelLoader(activeSessionHolder)
|
||||
return VectorGlideModelLoader(context)
|
||||
}
|
||||
|
||||
override fun teardown() {
|
||||
|
@ -45,7 +46,7 @@ class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessi
|
|||
}
|
||||
}
|
||||
|
||||
class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolder)
|
||||
class VectorGlideModelLoader(private val context: Context)
|
||||
: ModelLoader<ImageContentRenderer.Data, InputStream> {
|
||||
override fun handles(model: ImageContentRenderer.Data): Boolean {
|
||||
// Always handle
|
||||
|
@ -53,16 +54,19 @@ class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolde
|
|||
}
|
||||
|
||||
override fun buildLoadData(model: ImageContentRenderer.Data, width: Int, height: Int, options: Options): ModelLoader.LoadData<InputStream>? {
|
||||
return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(activeSessionHolder, model, width, height))
|
||||
return ModelLoader.LoadData(ObjectKey(model), VectorGlideDataFetcher(context, model, width, height))
|
||||
}
|
||||
}
|
||||
|
||||
class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolder,
|
||||
class VectorGlideDataFetcher(context: Context,
|
||||
private val data: ImageContentRenderer.Data,
|
||||
private val width: Int,
|
||||
private val height: Int)
|
||||
: DataFetcher<InputStream> {
|
||||
|
||||
private val localFilesHelper = LocalFilesHelper(context)
|
||||
private val activeSessionHolder = context.vectorComponent().activeSessionHolder()
|
||||
|
||||
private val client = activeSessionHolder.getSafeActiveSession()?.getOkHttpClient() ?: OkHttpClient()
|
||||
|
||||
override fun getDataClass(): Class<InputStream> {
|
||||
|
@ -97,9 +101,10 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde
|
|||
|
||||
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
|
||||
Timber.v("Load data: $data")
|
||||
if (data.isLocalFile && data.url != null) {
|
||||
val initialFile = File(data.url)
|
||||
callback.onDataReady(initialFile.inputStream())
|
||||
if (localFilesHelper.isLocalFile(data.url)) {
|
||||
localFilesHelper.openInputStream(data.url)?.use {
|
||||
callback.onDataReady(it)
|
||||
}
|
||||
return
|
||||
}
|
||||
// val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
|
||||
|
|
|
@ -24,8 +24,6 @@ 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()
|
||||
|
||||
/* ==========================================================================================
|
||||
* Delete
|
||||
* ========================================================================================== */
|
||||
|
|
|
@ -26,12 +26,12 @@ import android.view.View
|
|||
import dagger.Lazy
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.files.LocalFilesHelper
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.utils.DebouncedClickListener
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.core.utils.containsOnlyEmojis
|
||||
import im.vector.app.core.utils.isLocalFile
|
||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
|
||||
|
@ -94,6 +94,7 @@ import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
|
|||
import javax.inject.Inject
|
||||
|
||||
class MessageItemFactory @Inject constructor(
|
||||
private val localFilesHelper: LocalFilesHelper,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val dimensionConverter: DimensionConverter,
|
||||
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
|
||||
|
@ -205,7 +206,7 @@ class MessageItemFactory @Inject constructor(
|
|||
} ?: ""
|
||||
return MessageFileItem_()
|
||||
.attributes(attributes)
|
||||
.izLocalFile(fileUrl.isLocalFile())
|
||||
.izLocalFile(localFilesHelper.isLocalFile(fileUrl))
|
||||
.izDownloaded(session.fileService().isFileInCache(
|
||||
fileUrl,
|
||||
messageContent.getFileName(),
|
||||
|
@ -270,7 +271,7 @@ class MessageItemFactory @Inject constructor(
|
|||
return MessageFileItem_()
|
||||
.attributes(attributes)
|
||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||
.izLocalFile(messageContent.getFileUrl().isLocalFile())
|
||||
.izLocalFile(localFilesHelper.isLocalFile(messageContent.getFileUrl()))
|
||||
.izDownloaded(session.fileService().isFileInCache(messageContent))
|
||||
.mxcUrl(mxcUrl)
|
||||
.contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
|
||||
|
@ -305,7 +306,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 +345,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(
|
||||
|
|
|
@ -25,6 +25,7 @@ import androidx.core.view.isVisible
|
|||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.files.LocalFilesHelper
|
||||
import im.vector.app.core.glide.GlideApp
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
|
@ -55,7 +56,7 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
|
|||
super.bind(holder)
|
||||
imageContentRenderer.render(mediaData, mode, holder.imageView)
|
||||
if (!attributes.informationData.sendState.hasFailed()) {
|
||||
contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, mediaData.isLocalFile, holder.progressLayout)
|
||||
contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, LocalFilesHelper(holder.view.context).isLocalFile(mediaData.url), holder.progressLayout)
|
||||
} else {
|
||||
holder.progressLayout.isVisible = false
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.ORIENTATION
|
|||
import com.github.piasy.biv.view.BigImageView
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.files.LocalFilesHelper
|
||||
import im.vector.app.core.glide.GlideApp
|
||||
import im.vector.app.core.glide.GlideRequest
|
||||
import im.vector.app.core.glide.GlideRequests
|
||||
import im.vector.app.core.ui.model.Size
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.core.utils.isLocalFile
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
|
||||
|
@ -59,7 +59,8 @@ interface AttachmentData : Parcelable {
|
|||
val allowNonMxcUrls: Boolean
|
||||
}
|
||||
|
||||
class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
||||
class ImageContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper,
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val dimensionConverter: DimensionConverter) {
|
||||
|
||||
@Parcelize
|
||||
|
@ -73,7 +74,6 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||
val maxHeight: Int,
|
||||
val width: Int?,
|
||||
val maxWidth: Int,
|
||||
val isLocalFile: Boolean = url.isLocalFile(),
|
||||
// If true will load non mxc url, be careful to set it only for images sent by you
|
||||
override val allowNonMxcUrls: Boolean = false
|
||||
) : AttachmentData
|
||||
|
@ -291,7 +291,7 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||
|
||||
private fun resolveUrl(data: Data) =
|
||||
(activeSessionHolder.getActiveSession().contentUrlResolver().resolveFullSize(data.url)
|
||||
?: data.url?.takeIf { data.isLocalFile && data.allowNonMxcUrls })
|
||||
?: data.url?.takeIf { localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls })
|
||||
|
||||
private fun processSize(data: Data, mode: Mode): Size {
|
||||
val maxImageWidth = data.maxWidth
|
||||
|
|
|
@ -24,7 +24,7 @@ import androidx.core.view.isVisible
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.utils.isLocalFile
|
||||
import im.vector.app.core.files.LocalFilesHelper
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
|
||||
|
@ -33,7 +33,8 @@ import java.io.File
|
|||
import java.net.URLEncoder
|
||||
import javax.inject.Inject
|
||||
|
||||
class VideoContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
||||
class VideoContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper,
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val errorFormatter: ErrorFormatter) {
|
||||
|
||||
@Parcelize
|
||||
|
@ -63,7 +64,7 @@ class VideoContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||
loadingView.isVisible = false
|
||||
errorView.isVisible = true
|
||||
errorView.setText(R.string.unknown_error)
|
||||
} else if (data.url.isLocalFile() && data.allowNonMxcUrls) {
|
||||
} else if (localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls) {
|
||||
thumbnailView.isVisible = false
|
||||
loadingView.isVisible = false
|
||||
videoView.isVisible = true
|
||||
|
@ -98,7 +99,7 @@ class VideoContentRenderer @Inject constructor(private val activeSessionHolder:
|
|||
}
|
||||
} else {
|
||||
val resolvedUrl = contentUrlResolver.resolveFullSize(data.url)
|
||||
?: data.url?.takeIf { data.url.isLocalFile() && data.allowNonMxcUrls }
|
||||
?: data.url?.takeIf { localFilesHelper.isLocalFile(data.url) && data.allowNonMxcUrls }
|
||||
|
||||
if (resolvedUrl == null) {
|
||||
thumbnailView.isVisible = false
|
||||
|
|
Loading…
Add table
Reference in a new issue