Add MediaSource.withCleanUrl method that removes invalid fragment data from MXC urls
We've seen some MXC urls in the wild having some `mxc://foo/bar#auto` fragment suffix, which is invalid, but the URL before that fragment part is valid and can be displayed
This commit is contained in:
parent
992a1133c9
commit
7fe0cc4d45
3 changed files with 36 additions and 7 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
package io.element.android.libraries.matrix.api.media
|
package io.element.android.libraries.matrix.api.media
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import androidx.core.net.toUri
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
|
@ -22,3 +23,25 @@ data class MediaSource(
|
||||||
*/
|
*/
|
||||||
val json: String? = null,
|
val json: String? = null,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new [MediaSource] with a valid URL.
|
||||||
|
*/
|
||||||
|
fun MediaSource.withCleanUrl(): MediaSource {
|
||||||
|
val uri = this.url.toUri()
|
||||||
|
if (uri.scheme != "mxc") return this
|
||||||
|
|
||||||
|
// We've seen some MXC urls in the wild having some `mxc://foo/bar#auto` fragment suffix, which is invalid
|
||||||
|
val cleanedUrl = buildString {
|
||||||
|
append(uri.scheme)
|
||||||
|
if (!this.endsWith("://")) {
|
||||||
|
append("://")
|
||||||
|
}
|
||||||
|
append(uri.host)
|
||||||
|
if (uri.path != null) {
|
||||||
|
append(uri.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.copy(url = cleanedUrl)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes
|
||||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||||
import io.element.android.libraries.matrix.api.media.MediaFile
|
import io.element.android.libraries.matrix.api.media.MediaFile
|
||||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||||
|
import io.element.android.libraries.matrix.api.media.withCleanUrl
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.rustcomponents.sdk.Client
|
import org.matrix.rustcomponents.sdk.Client
|
||||||
import org.matrix.rustcomponents.sdk.use
|
import org.matrix.rustcomponents.sdk.use
|
||||||
|
|
@ -91,7 +92,7 @@ class RustMediaLoader(
|
||||||
return if (json != null) {
|
return if (json != null) {
|
||||||
RustMediaSource.fromJson(json)
|
RustMediaSource.fromJson(json)
|
||||||
} else {
|
} else {
|
||||||
RustMediaSource.fromUrl(url)
|
RustMediaSource.fromUrl(withCleanUrl().url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import coil3.fetch.SourceFetchResult
|
||||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||||
import io.element.android.libraries.matrix.api.media.toFile
|
import io.element.android.libraries.matrix.api.media.toFile
|
||||||
|
import io.element.android.libraries.matrix.api.media.withCleanUrl
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
import okio.FileSystem
|
import okio.FileSystem
|
||||||
import okio.Path.Companion.toOkioPath
|
import okio.Path.Companion.toOkioPath
|
||||||
|
|
@ -28,14 +29,18 @@ internal class CoilMediaFetcher(
|
||||||
) : Fetcher {
|
) : Fetcher {
|
||||||
override suspend fun fetch(): FetchResult? {
|
override suspend fun fetch(): FetchResult? {
|
||||||
val source = mediaData.source
|
val source = mediaData.source
|
||||||
if (source == null) {
|
val mediaSource = when {
|
||||||
Timber.e("MediaData source is null")
|
source == null -> {
|
||||||
return null
|
Timber.e("MediaData source is null")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
source.url.startsWith("mxc:") -> source.withCleanUrl()
|
||||||
|
else -> source
|
||||||
}
|
}
|
||||||
return when (val kind = mediaData.kind) {
|
return when (val kind = mediaData.kind) {
|
||||||
is MediaRequestData.Kind.Content -> fetchContent(source)
|
is MediaRequestData.Kind.Content -> fetchContent(mediaSource)
|
||||||
is MediaRequestData.Kind.Thumbnail -> fetchThumbnail(source, kind)
|
is MediaRequestData.Kind.Thumbnail -> fetchThumbnail(mediaSource, kind)
|
||||||
is MediaRequestData.Kind.File -> fetchFile(source, kind)
|
is MediaRequestData.Kind.File -> fetchFile(mediaSource, kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue