forked from GitHub-Mirror/riotX-android
128 lines
4.4 KiB
Kotlin
128 lines
4.4 KiB
Kotlin
/*
|
|
* Copyright 2019 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.riotx.core.glide
|
|
|
|
import com.bumptech.glide.Priority
|
|
import com.bumptech.glide.load.DataSource
|
|
import com.bumptech.glide.load.Options
|
|
import com.bumptech.glide.load.data.DataFetcher
|
|
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.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
|
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
|
import im.vector.riotx.features.media.ImageContentRenderer
|
|
import okhttp3.OkHttpClient
|
|
import okhttp3.Request
|
|
import timber.log.Timber
|
|
import java.io.File
|
|
import java.io.FileInputStream
|
|
import java.io.IOException
|
|
import java.io.InputStream
|
|
import com.bumptech.glide.load.engine.Resource as Resource1
|
|
|
|
|
|
class VectorGlideModelLoaderFactory(private val activeSessionHolder: ActiveSessionHolder)
|
|
: ModelLoaderFactory<ImageContentRenderer.Data, InputStream> {
|
|
|
|
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<ImageContentRenderer.Data, InputStream> {
|
|
return VectorGlideModelLoader(activeSessionHolder)
|
|
}
|
|
|
|
override fun teardown() {
|
|
// Is there something to do here?
|
|
}
|
|
|
|
}
|
|
|
|
class VectorGlideModelLoader(private val activeSessionHolder: ActiveSessionHolder)
|
|
: ModelLoader<ImageContentRenderer.Data, InputStream> {
|
|
override fun handles(model: ImageContentRenderer.Data): Boolean {
|
|
// Always handle
|
|
return true
|
|
}
|
|
|
|
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))
|
|
}
|
|
}
|
|
|
|
class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolder,
|
|
private val data: ImageContentRenderer.Data,
|
|
private val width: Int,
|
|
private val height: Int)
|
|
: DataFetcher<InputStream> {
|
|
|
|
val client = OkHttpClient()
|
|
|
|
override fun getDataClass(): Class<InputStream> {
|
|
return InputStream::class.java
|
|
}
|
|
|
|
private var stream: InputStream? = null
|
|
|
|
override fun cleanup() {
|
|
cancel()
|
|
}
|
|
|
|
override fun getDataSource(): DataSource {
|
|
// ?
|
|
return DataSource.REMOTE
|
|
}
|
|
|
|
override fun cancel() {
|
|
if (stream != null) {
|
|
try {
|
|
stream?.close() // interrupts decode if any
|
|
stream = null
|
|
} catch (ignore: IOException) {
|
|
Timber.e(ignore)
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
|
|
Timber.v("Load data: $data")
|
|
if (data.isLocalFile()) {
|
|
val initialFile = File(data.url)
|
|
callback.onDataReady(FileInputStream(initialFile))
|
|
return
|
|
}
|
|
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
|
|
val url = contentUrlResolver.resolveFullSize(data.url)
|
|
?: return
|
|
|
|
val request = Request.Builder()
|
|
.url(url)
|
|
.build()
|
|
|
|
val response = client.newCall(request).execute()
|
|
val inputStream = response.body()?.byteStream()
|
|
Timber.v("Response size ${response.body()?.contentLength()} - Stream available: ${inputStream?.available()}")
|
|
if (!response.isSuccessful) {
|
|
callback.onLoadFailed(IOException("Unexpected code $response"))
|
|
return
|
|
}
|
|
stream = if (data.elementToDecrypt != null && data.elementToDecrypt.k.isNotBlank()) {
|
|
MXEncryptedAttachments.decryptAttachment(inputStream, data.elementToDecrypt)
|
|
} else {
|
|
inputStream
|
|
}
|
|
callback.onDataReady(stream)
|
|
}
|
|
} |