updating to coil 2
This commit is contained in:
parent
e445458009
commit
165241f412
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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) {
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue