updating to coil 2

This commit is contained in:
Adam Brown 2022-05-21 12:38:28 +01:00
parent e445458009
commit 165241f412
4 changed files with 63 additions and 46 deletions

View File

@ -10,12 +10,14 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.ExperimentalUnitApi import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import coil.compose.rememberImagePainter import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest
import coil.transform.CircleCropTransformation import coil.transform.CircleCropTransformation
@OptIn(ExperimentalUnitApi::class) @OptIn(ExperimentalUnitApi::class)
@ -25,7 +27,8 @@ fun BoxScope.CircleishAvatar(avatarUrl: String?, fallbackLabel: String, size: Dp
null -> { null -> {
val colors = SmallTalkTheme.extendedColors.getMissingImageColor(fallbackLabel) val colors = SmallTalkTheme.extendedColors.getMissingImageColor(fallbackLabel)
Box( Box(
Modifier.align(Alignment.Center) Modifier
.align(Alignment.Center)
.background(color = colors.first, shape = CircleShape) .background(color = colors.first, shape = CircleShape)
.size(size), .size(size),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
@ -40,14 +43,16 @@ fun BoxScope.CircleishAvatar(avatarUrl: String?, fallbackLabel: String, size: Dp
} }
else -> { else -> {
Image( Image(
painter = rememberImagePainter( painter = rememberAsyncImagePainter(
data = avatarUrl, model = ImageRequest.Builder(LocalContext.current)
builder = { .data(avatarUrl)
transformations(CircleCropTransformation()) .transformations(CircleCropTransformation())
} .build()
), ),
contentDescription = null, contentDescription = null,
modifier = Modifier.size(size).align(Alignment.Center) modifier = Modifier
.size(size)
.align(Alignment.Center)
) )
} }
} }
@ -56,7 +61,11 @@ fun BoxScope.CircleishAvatar(avatarUrl: String?, fallbackLabel: String, size: Dp
@Composable @Composable
fun MissingAvatarIcon(displayName: String, displayImageSize: Dp) { fun MissingAvatarIcon(displayName: String, displayImageSize: Dp) {
val colors = SmallTalkTheme.extendedColors.getMissingImageColor(displayName) val colors = SmallTalkTheme.extendedColors.getMissingImageColor(displayName)
Box(Modifier.background(color = colors.first, shape = CircleShape).size(displayImageSize), contentAlignment = Alignment.Center) { Box(
Modifier
.background(color = colors.first, shape = CircleShape)
.size(displayImageSize), contentAlignment = Alignment.Center
) {
Text( Text(
text = (displayName).first().toString().uppercase(), text = (displayName).first().toString().uppercase(),
color = colors.second color = colors.second
@ -67,11 +76,11 @@ fun MissingAvatarIcon(displayName: String, displayImageSize: Dp) {
@Composable @Composable
fun MessengerUrlIcon(avatarUrl: String, displayImageSize: Dp) { fun MessengerUrlIcon(avatarUrl: String, displayImageSize: Dp) {
Image( Image(
painter = rememberImagePainter( painter = rememberAsyncImagePainter(
data = avatarUrl, model = ImageRequest.Builder(LocalContext.current)
builder = { .data(avatarUrl)
transformations(CircleCropTransformation()) .transformations(CircleCropTransformation())
} .build()
), ),
contentDescription = null, contentDescription = null,
modifier = Modifier.size(displayImageSize) modifier = Modifier.size(displayImageSize)

View File

@ -1,14 +1,15 @@
package app.dapk.st.messenger package app.dapk.st.messenger
import android.content.Context
import android.util.Base64 import android.util.Base64
import app.dapk.st.matrix.sync.RoomEvent import app.dapk.st.matrix.sync.RoomEvent
import coil.bitmap.BitmapPool import coil.ImageLoader
import coil.decode.DataSource import coil.decode.DataSource
import coil.decode.Options import coil.decode.ImageSource
import coil.fetch.FetchResult import coil.fetch.FetchResult
import coil.fetch.Fetcher import coil.fetch.Fetcher
import coil.fetch.SourceResult import coil.fetch.SourceResult
import coil.size.Size import coil.request.Options
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -23,18 +24,23 @@ private const val CIPHER_ALGORITHM = "AES/CTR/NoPadding"
private const val SECRET_KEY_SPEC_ALGORITHM = "AES" private const val SECRET_KEY_SPEC_ALGORITHM = "AES"
private const val MESSAGE_DIGEST_ALGORITHM = "SHA-256" private const val MESSAGE_DIGEST_ALGORITHM = "SHA-256"
class DecryptingFetcher : Fetcher<RoomEvent.Image> { class DecryptingFetcherFactory(private val context: Context) : Fetcher.Factory<RoomEvent.Image> {
override fun create(data: RoomEvent.Image, options: Options, imageLoader: ImageLoader): Fetcher {
return DecryptingFetcher(data, context)
}
}
private val http = OkHttpClient() private val http = OkHttpClient()
override suspend fun fetch(pool: BitmapPool, data: RoomEvent.Image, size: Size, options: Options): FetchResult { class DecryptingFetcher(private val data: RoomEvent.Image, private val context: Context) : Fetcher {
override suspend fun fetch(): FetchResult {
val response = http.newCall(Request.Builder().url(data.imageMeta.url).build()).execute() val response = http.newCall(Request.Builder().url(data.imageMeta.url).build()).execute()
val outputStream = when { val outputStream = when {
data.imageMeta.keys != null -> handleEncrypted(response, data.imageMeta.keys!!) data.imageMeta.keys != null -> handleEncrypted(response, data.imageMeta.keys!!)
else -> response.body()?.source() ?: throw IllegalArgumentException("No bitmap response found") else -> response.body?.source() ?: throw IllegalArgumentException("No bitmap response found")
} }
return SourceResult(ImageSource(outputStream, context), null, DataSource.NETWORK)
return SourceResult(outputStream, null, DataSource.NETWORK)
} }
private fun handleEncrypted(response: Response, keys: RoomEvent.Image.ImageMeta.Keys): Buffer { private fun handleEncrypted(response: Response, keys: RoomEvent.Image.ImageMeta.Keys): Buffer {
@ -53,7 +59,7 @@ class DecryptingFetcher : Fetcher<RoomEvent.Image> {
var decodedBytes: ByteArray var decodedBytes: ByteArray
val outputStream = Buffer() val outputStream = Buffer()
response.body()?.let { response.body?.let {
it.byteStream().use { it.byteStream().use {
read = it.read(d) read = it.read(d)
while (read != -1) { while (read != -1) {
@ -66,7 +72,4 @@ class DecryptingFetcher : Fetcher<RoomEvent.Image> {
} }
return outputStream return outputStream
} }
override fun key(data: RoomEvent.Image) = data.imageMeta.url
} }

View File

@ -22,6 +22,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.*
@ -37,7 +38,8 @@ import app.dapk.st.matrix.sync.RoomEvent
import app.dapk.st.matrix.sync.RoomEvent.Message import app.dapk.st.matrix.sync.RoomEvent.Message
import app.dapk.st.matrix.sync.RoomState import app.dapk.st.matrix.sync.RoomState
import app.dapk.st.navigator.Navigator import app.dapk.st.navigator.Navigator
import coil.compose.rememberImagePainter import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
@ -212,8 +214,6 @@ private fun <T : RoomEvent> LazyItemScope.AlignedBubble(
} }
} }
private val decryptingFetcher = DecryptingFetcher()
@Composable @Composable
private fun MessageImage(content: BubbleContent<RoomEvent.Image>) { private fun MessageImage(content: BubbleContent<RoomEvent.Image>) {
Box(modifier = Modifier.padding(start = 6.dp)) { Box(modifier = Modifier.padding(start = 6.dp)) {
@ -242,9 +242,11 @@ private fun MessageImage(content: BubbleContent<RoomEvent.Image>) {
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Image( Image(
modifier = Modifier.size(content.message.imageMeta.scale(LocalDensity.current, LocalConfiguration.current)), modifier = Modifier.size(content.message.imageMeta.scale(LocalDensity.current, LocalConfiguration.current)),
painter = rememberImagePainter( painter = rememberAsyncImagePainter(
data = content.message, model = ImageRequest.Builder(LocalContext.current)
builder = { fetcher(decryptingFetcher) } .fetcherFactory(DecryptingFetcherFactory(LocalContext.current))
.data(content.message)
.build()
), ),
contentDescription = null, contentDescription = null,
) )
@ -410,9 +412,11 @@ private fun ReplyBubbleContent(content: BubbleContent<RoomEvent.Reply>) {
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Image( Image(
modifier = Modifier.size(replyingTo.imageMeta.scale(LocalDensity.current, LocalConfiguration.current)), modifier = Modifier.size(replyingTo.imageMeta.scale(LocalDensity.current, LocalConfiguration.current)),
painter = rememberImagePainter( painter = rememberAsyncImagePainter(
data = replyingTo, model = ImageRequest.Builder(LocalContext.current)
builder = { fetcher(DecryptingFetcher()) } .fetcherFactory(DecryptingFetcherFactory(LocalContext.current))
.data(replyingTo)
.build()
), ),
contentDescription = null, contentDescription = null,
) )
@ -445,9 +449,11 @@ private fun ReplyBubbleContent(content: BubbleContent<RoomEvent.Reply>) {
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Image( Image(
modifier = Modifier.size(message.imageMeta.scale(LocalDensity.current, LocalConfiguration.current)), modifier = Modifier.size(message.imageMeta.scale(LocalDensity.current, LocalConfiguration.current)),
painter = rememberImagePainter( painter = rememberAsyncImagePainter(
data = content.message, model = ImageRequest.Builder(LocalContext.current)
builder = { fetcher(DecryptingFetcher()) } .data(content.message)
.fetcherFactory(DecryptingFetcherFactory(LocalContext.current))
.build()
), ),
contentDescription = null, contentDescription = null,
) )

View File

@ -154,11 +154,10 @@ private fun RoomInvite.inviterName() = this.from.displayName?.let { "$it (${this
@Composable @Composable
private fun ProfileViewModel.ObserveEvents() { private fun ProfileViewModel.ObserveEvents() {
val context = LocalContext.current // StartObserving {
StartObserving { // this@ObserveEvents.events.launch {
this@ObserveEvents.events.launch { // when (it) {
when (it) { // }
} // }
} // }
}
} }