diff --git a/app/build.gradle b/app/build.gradle index 94a7096..dd21fc8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -89,5 +89,5 @@ dependencies { implementation Dependencies.mavenCentral.matrixOlm implementation Dependencies.mavenCentral.kotlinSerializationJson - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' } diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/DecryptingFetcher.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/DecryptingFetcher.kt index 3e3226c..0907592 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/DecryptingFetcher.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/DecryptingFetcher.kt @@ -11,6 +11,7 @@ import coil.fetch.SourceResult import coil.size.Size import okhttp3.OkHttpClient import okhttp3.Request +import okhttp3.Response import okio.Buffer import java.security.MessageDigest import javax.crypto.Cipher @@ -28,9 +29,15 @@ class DecryptingFetcher : Fetcher { override suspend fun fetch(pool: BitmapPool, data: RoomEvent.Image, size: Size, options: Options): FetchResult { val response = http.newCall(Request.Builder().url(data.imageMeta.url).build()).execute() - val outputStream = Buffer() + val outputStream = when { + data.imageMeta.keys != null -> handleEncrypted(response, data.imageMeta.keys!!) + else -> response.body()?.source() ?: throw IllegalArgumentException("No bitmap response found") + } - val keys = data.imageMeta.keys!! + return SourceResult(outputStream, null, DataSource.NETWORK) + } + + private fun handleEncrypted(response: Response, keys: RoomEvent.Image.ImageMeta.Keys): Buffer { val key = Base64.decode(keys.k.replace('-', '+').replace('_', '/'), Base64.DEFAULT) val initVectorBytes = Base64.decode(keys.iv, Base64.DEFAULT) @@ -45,6 +52,7 @@ class DecryptingFetcher : Fetcher { val d = ByteArray(CRYPTO_BUFFER_SIZE) var decodedBytes: ByteArray + val outputStream = Buffer() response.body()?.let { it.byteStream().use { read = it.read(d) @@ -56,7 +64,7 @@ class DecryptingFetcher : Fetcher { } } } - return SourceResult(outputStream, null, DataSource.NETWORK) + return outputStream } override fun key(data: RoomEvent.Image) = data.imageMeta.url diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerScreen.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerScreen.kt index cdcac28..7fe8bdf 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerScreen.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerScreen.kt @@ -1,5 +1,6 @@ package app.dapk.st.messenger +import android.content.res.Configuration import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -20,11 +21,10 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.IntSize -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp +import androidx.compose.ui.unit.* import app.dapk.st.core.Lce import app.dapk.st.core.LifecycleEffect import app.dapk.st.core.StartObserving @@ -212,6 +212,8 @@ private fun LazyItemScope.AlignedBubble( } } +private val decryptingFetcher = DecryptingFetcher() + @Composable private fun MessageImage(content: BubbleContent) { Box(modifier = Modifier.padding(start = 6.dp)) { @@ -237,14 +239,12 @@ private fun MessageImage(content: BubbleContent) { ) } - val width = with(LocalDensity.current) { content.message.imageMeta.width.toDp() } - val height = with(LocalDensity.current) { content.message.imageMeta.height.toDp() } Spacer(modifier = Modifier.height(4.dp)) Image( - modifier = Modifier.size(width, height), + modifier = Modifier.size(content.message.imageMeta.scaleMeta(LocalDensity.current, LocalConfiguration.current)), painter = rememberImagePainter( data = content.message, - builder = { fetcher(DecryptingFetcher()) } + builder = { fetcher(decryptingFetcher) } ), contentDescription = null, ) @@ -264,8 +264,25 @@ private fun MessageImage(content: BubbleContent) { } } } +} + +private fun RoomEvent.Image.ImageMeta.scaleMeta(density: Density, configuration: Configuration): DpSize { + return with(density) { + val scaler = minOf( + this@scaleMeta.height.scalerFor(configuration.screenHeightDp.dp.toPx() * 0.5f), + this@scaleMeta.width.scalerFor(configuration.screenWidthDp.dp.toPx() * 0.6f) + ) + + DpSize( + width = (this@scaleMeta.width * scaler).toDp(), + height = (this@scaleMeta.height * scaler).toDp(), + ) + } +} +private fun Int.scalerFor(max: Float): Float { + return max / this } private val selfBackgroundShape = RoundedCornerShape(12.dp, 0.dp, 12.dp, 12.dp)