Migrate to coil3

This commit is contained in:
Benoit Marty 2025-03-03 12:30:17 +01:00
parent 491bb1d8fe
commit a70249769d
43 changed files with 148 additions and 117 deletions

View file

@ -5,12 +5,15 @@
* Please see LICENSE files in the repository root for full details.
*/
@file:OptIn(DelicateCoilApi::class)
package io.element.android.appnav
import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import coil.Coil
import coil3.SingletonImageLoader
import coil3.annotation.DelicateCoilApi
import com.bumble.appyx.core.composable.Children
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
@ -69,7 +72,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
super.onBuilt()
lifecycle.subscribe(
onCreate = {
Coil.setImageLoader(imageLoaderHolder.get(inputs.matrixClient))
SingletonImageLoader.setUnsafe(imageLoaderHolder.get(inputs.matrixClient))
},
)
}

View file

@ -5,12 +5,15 @@
* Please see LICENSE files in the repository root for full details.
*/
@file:OptIn(DelicateCoilApi::class)
package io.element.android.appnav
import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import coil.Coil
import coil3.SingletonImageLoader
import coil3.annotation.DelicateCoilApi
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
@ -55,7 +58,7 @@ class NotLoggedInFlowNode @AssistedInject constructor(
super.onBuilt()
lifecycle.subscribe(
onCreate = {
Coil.setImageLoader(notLoggedInImageLoaderFactory)
SingletonImageLoader.setUnsafe(notLoggedInImageLoaderFactory.newImageLoader())
},
)
}

View file

@ -9,7 +9,7 @@ package io.element.android.features.call.notifications
import androidx.core.graphics.drawable.IconCompat
import androidx.test.platform.app.InstrumentationRegistry
import coil.ImageLoader
import coil3.ImageLoader
import com.google.common.truth.Truth.assertThat
import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator
import io.element.android.libraries.matrix.test.AN_EVENT_ID

View file

@ -11,6 +11,7 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
@ -22,9 +23,10 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImagePainter
import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest
import coil3.Extras
import coil3.compose.AsyncImagePainter
import coil3.compose.rememberAsyncImagePainter
import coil3.request.ImageRequest
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.location.api.internal.StaticMapPlaceholder
import io.element.android.features.location.api.internal.StaticMapUrlBuilder
@ -33,7 +35,6 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.utils.CommonDrawables
import timber.log.Timber
/**
* Shows a static map image downloaded via a third party service's static maps API.
@ -75,14 +76,15 @@ fun StaticMapView(
)
)
.size(width = constraints.maxWidth, height = constraints.maxHeight)
.setParameter("retry_hash", retryHash, memoryCacheKey = null)
.apply {
extras.set(Extras.Key("retry_hash"), retryHash).build()
}
.build()
}.apply {
Timber.d("Static map image request: ${this?.data}")
}
)
if (painter.state is AsyncImagePainter.State.Success) {
val collectedState = painter.state.collectAsState()
if (collectedState.value is AsyncImagePainter.State.Success) {
Image(
painter = painter,
contentDescription = contentDescription,
@ -100,7 +102,7 @@ fun StaticMapView(
)
} else {
StaticMapPlaceholder(
showProgress = painter.state is AsyncImagePainter.State.Loading,
showProgress = collectedState.value is AsyncImagePainter.State.Loading,
contentDescription = contentDescription,
width = maxWidth,
height = maxHeight,

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import coil3.compose.AsyncImage
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.R
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction

View file

@ -37,8 +37,8 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.components.ATimelineItemEventRow

View file

@ -25,8 +25,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.PreviewParameter
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContentProvider
import io.element.android.features.messages.impl.timeline.protection.ProtectedView

View file

@ -40,8 +40,8 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent

View file

@ -50,7 +50,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import coil3.compose.AsyncImage
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.timeline.components.REACTION_IMAGE_ASPECT_RATIO
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction

View file

@ -63,6 +63,9 @@ dependencies {
implementation(libs.androidx.datastore.preferences)
api(projects.features.preferences.api)
implementation(platform(libs.network.okhttp.bom))
implementation(libs.network.okhttp)
testImplementation(libs.test.junit)
testImplementation(libs.coroutines.test)
testImplementation(libs.molecule.runtime)

View file

@ -5,13 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
@file:OptIn(ExperimentalCoilApi::class)
package io.element.android.features.preferences.impl.tasks
import android.content.Context
import coil.Coil
import coil.annotation.ExperimentalCoilApi
import coil3.SingletonImageLoader
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.ftue.api.state.FtueService
import io.element.android.features.preferences.impl.DefaultCacheService
@ -43,7 +40,7 @@ class DefaultClearCacheUseCase @Inject constructor(
// Clear Matrix cache
matrixClient.clearCache()
// Clear Coil cache
Coil.imageLoader(context).let {
SingletonImageLoader.get(context).let {
it.diskCache?.clear()
it.memoryCache?.clear()
}

View file

@ -28,8 +28,8 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import io.element.android.features.rageshake.impl.R
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.async.AsyncActionView

View file

@ -42,7 +42,7 @@ datetime = "0.6.2"
serialization_json = "1.8.0"
#other
coil = "2.7.0"
coil = "3.1.0"
showkase = "1.0.3"
appyx = "1.6.0"
sqldelight = "2.0.2"
@ -159,10 +159,11 @@ test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "
test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.5.1"
# Others
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
coil_gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
coil_test = { module = "io.coil-kt:coil-test", version.ref = "coil" }
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
coil_network_okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" }
coil_compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
coil_gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" }
coil_test = { module = "io.coil-kt.coil3:coil-test", version.ref = "coil" }
compound = { module = "io.element.android:compound-android", version = "25.2.26" }
datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" }

View file

@ -9,7 +9,6 @@ package io.element.android.libraries.designsystem.components
import android.graphics.Bitmap
import android.graphics.Typeface
import android.graphics.drawable.BitmapDrawable
import android.os.Build
import android.text.TextPaint
import androidx.annotation.FloatRange
@ -85,9 +84,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.isSpecified
import androidx.compose.ui.unit.toOffset
import androidx.compose.ui.unit.toSize
import coil.imageLoader
import coil.request.DefaultRequestOptions
import coil.request.ImageRequest
import coil3.SingletonImageLoader
import coil3.request.ImageRequest
import coil3.request.allowHardware
import coil3.toBitmap
import com.airbnb.android.showkase.annotation.ShowkaseComposable
import com.vanniktech.blurhash.BlurHash
import io.element.android.compound.theme.ElementTheme
@ -328,7 +328,7 @@ fun Modifier.avatarBloom(
ImageRequest.Builder(context)
.data(avatarData)
// Allow cache and default dispatchers
.defaults(DefaultRequestOptions())
.defaults(ImageRequest.Defaults())
// Needed to be able to read pixels from the Bitmap for the hash
.allowHardware(false)
// Reduce size so it loads faster for large avatars
@ -340,9 +340,9 @@ fun Modifier.avatarBloom(
var blurHash by rememberSaveable(avatarData) { mutableStateOf<String?>(null) }
LaunchedEffect(avatarData) {
withContext(Dispatchers.IO) {
val drawable =
context.imageLoader.execute(painterRequest).drawable ?: return@withContext
val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return@withContext
val bitmap = SingletonImageLoader.get(context)
.execute(painterRequest)
.image?.toBitmap() ?: return@withContext
blurHash = BlurHash.encode(
bitmap = bitmap,
componentX = BloomDefaults.HASH_COMPONENTS,

View file

@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -26,10 +28,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil.compose.SubcomposeAsyncImage
import coil.compose.SubcomposeAsyncImageContent
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import coil3.compose.SubcomposeAsyncImage
import coil3.compose.SubcomposeAsyncImageContent
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
@ -89,7 +91,8 @@ private fun ImageAvatar(
contentScale = ContentScale.Crop,
modifier = modifier
) {
when (val state = painter.state) {
val collectedState by painter.state.collectAsState()
when (val state = collectedState) {
is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()
is AsyncImagePainter.State.Error -> {
SideEffect {

View file

@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import coil.compose.AsyncImage
import coil3.compose.AsyncImage
@Composable
fun BlurHashAsyncImage(

View file

@ -34,6 +34,7 @@ dependencies {
implementation(projects.libraries.testtags)
implementation(libs.coil.compose)
implementation(libs.coil.gif)
implementation(libs.coil.network.okhttp)
implementation(libs.jsoup)
testImplementation(libs.coroutines.test)

View file

@ -24,8 +24,8 @@ import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight

View file

@ -7,9 +7,9 @@
package io.element.android.libraries.matrix.ui.media
import coil.ImageLoader
import coil.fetch.Fetcher
import coil.request.Options
import coil3.ImageLoader
import coil3.fetch.Fetcher
import coil3.request.Options
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.matrix.api.MatrixClient
@ -24,7 +24,6 @@ internal class AvatarDataFetcherFactory(
return CoilMediaFetcher(
mediaLoader = client.mediaLoader,
mediaData = data.toMediaRequestData(),
options = options
)
}
}

View file

@ -7,16 +7,16 @@
package io.element.android.libraries.matrix.ui.media
import coil.decode.DataSource
import coil.decode.ImageSource
import coil.fetch.FetchResult
import coil.fetch.Fetcher
import coil.fetch.SourceResult
import coil.request.Options
import coil3.decode.DataSource
import coil3.decode.ImageSource
import coil3.fetch.FetchResult
import coil3.fetch.Fetcher
import coil3.fetch.SourceFetchResult
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.toFile
import okio.Buffer
import okio.FileSystem
import okio.Path.Companion.toOkioPath
import timber.log.Timber
import java.nio.ByteBuffer
@ -24,7 +24,6 @@ import java.nio.ByteBuffer
internal class CoilMediaFetcher(
private val mediaLoader: MatrixMediaLoader,
private val mediaData: MediaRequestData,
private val options: Options
) : Fetcher {
override suspend fun fetch(): FetchResult? {
if (mediaData.source == null) {
@ -32,8 +31,8 @@ internal class CoilMediaFetcher(
return null
}
return when (mediaData.kind) {
is MediaRequestData.Kind.Content -> fetchContent(mediaData.source, options)
is MediaRequestData.Kind.Thumbnail -> fetchThumbnail(mediaData.source, mediaData.kind, options)
is MediaRequestData.Kind.Content -> fetchContent(mediaData.source)
is MediaRequestData.Kind.Thumbnail -> fetchThumbnail(mediaData.source, mediaData.kind)
is MediaRequestData.Kind.File -> fetchFile(mediaData.source, mediaData.kind)
}
}
@ -47,8 +46,12 @@ internal class CoilMediaFetcher(
return mediaLoader.downloadMediaFile(mediaSource, kind.mimeType, kind.fileName)
.map { mediaFile ->
val file = mediaFile.toFile()
SourceResult(
source = ImageSource(file = file.toOkioPath(), closeable = mediaFile),
SourceFetchResult(
source = ImageSource(
file = file.toOkioPath(),
fileSystem = FileSystem.SYSTEM,
closeable = mediaFile,
),
mimeType = null,
dataSource = DataSource.DISK
)
@ -59,37 +62,40 @@ internal class CoilMediaFetcher(
.getOrNull()
}
private suspend fun fetchContent(mediaSource: MediaSource, options: Options): FetchResult? {
private suspend fun fetchContent(mediaSource: MediaSource): FetchResult? {
return mediaLoader.loadMediaContent(
source = mediaSource,
).map { byteArray ->
byteArray.asSourceResult(options)
byteArray.asSourceResult()
}.onFailure {
Timber.e(it)
}.getOrNull()
}
private suspend fun fetchThumbnail(mediaSource: MediaSource, kind: MediaRequestData.Kind.Thumbnail, options: Options): FetchResult? {
private suspend fun fetchThumbnail(mediaSource: MediaSource, kind: MediaRequestData.Kind.Thumbnail): FetchResult? {
return mediaLoader.loadMediaThumbnail(
source = mediaSource,
width = kind.width,
height = kind.height,
).map { byteArray ->
byteArray.asSourceResult(options)
byteArray.asSourceResult()
}.onFailure {
Timber.e(it)
}.getOrNull()
}
private fun ByteArray.asSourceResult(options: Options): SourceResult {
private fun ByteArray.asSourceResult(): SourceFetchResult {
val byteBuffer = ByteBuffer.wrap(this)
val bufferedSource = try {
Buffer().apply { write(byteBuffer) }
} finally {
byteBuffer.position(0)
}
return SourceResult(
source = ImageSource(bufferedSource, options.context),
return SourceFetchResult(
source = ImageSource(
source = bufferedSource,
fileSystem = FileSystem.SYSTEM,
),
mimeType = null,
dataSource = DataSource.MEMORY
)

View file

@ -9,10 +9,10 @@ package io.element.android.libraries.matrix.ui.media
import android.content.Context
import android.os.Build
import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil3.ImageLoader
import coil3.gif.AnimatedImageDecoder
import coil3.gif.GifDecoder
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
@ -33,11 +33,17 @@ class DefaultLoggedInImageLoaderFactory @Inject constructor(
override fun newImageLoader(matrixClient: MatrixClient): ImageLoader {
return ImageLoader
.Builder(context)
.okHttpClient { okHttpClient.get() }
.components {
add(
OkHttpNetworkFetcherFactory(
callFactory = {
okHttpClient.get()
}
)
)
// Add gif support
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
add(ImageDecoderDecoder.Factory())
add(AnimatedImageDecoder.Factory())
} else {
add(GifDecoder.Factory())
}
@ -53,11 +59,19 @@ class DefaultLoggedInImageLoaderFactory @Inject constructor(
class NotLoggedInImageLoaderFactory @Inject constructor(
@ApplicationContext private val context: Context,
private val okHttpClient: Provider<OkHttpClient>,
) : ImageLoaderFactory {
override fun newImageLoader(): ImageLoader {
) {
fun newImageLoader(): ImageLoader {
return ImageLoader
.Builder(context)
.okHttpClient { okHttpClient.get() }
.components {
add(
OkHttpNetworkFetcherFactory(
callFactory = {
okHttpClient.get()
}
)
)
}
.build()
}
}

View file

@ -7,7 +7,7 @@
package io.element.android.libraries.matrix.ui.media
import coil.ImageLoader
import coil3.ImageLoader
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn

View file

@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.ui.media
import io.element.android.libraries.matrix.api.media.MediaSource
/**
* Can be use with [coil.compose.AsyncImage] to load a [MediaSource].
* Can be use with [coil3.compose.AsyncImage] to load a [MediaSource].
* This will go internally through our [CoilMediaFetcher].
*
* Example of usage:

View file

@ -7,9 +7,9 @@
package io.element.android.libraries.matrix.ui.media
import coil.ImageLoader
import coil.fetch.Fetcher
import coil.request.Options
import coil3.ImageLoader
import coil3.fetch.Fetcher
import coil3.request.Options
import io.element.android.libraries.matrix.api.MatrixClient
internal class MediaRequestDataFetcherFactory(
@ -23,7 +23,6 @@ internal class MediaRequestDataFetcherFactory(
return CoilMediaFetcher(
mediaLoader = client.mediaLoader,
mediaData = data,
options = options
)
}
}

View file

@ -7,8 +7,8 @@
package io.element.android.libraries.matrix.ui.media
import coil.key.Keyer
import coil.request.Options
import coil3.key.Keyer
import coil3.request.Options
import io.element.android.libraries.designsystem.components.avatar.AvatarData
internal class AvatarDataKeyer : Keyer<AvatarData> {

View file

@ -8,7 +8,7 @@
package io.element.android.libraries.matrix.ui.media
import androidx.test.platform.app.InstrumentationRegistry
import coil.ImageLoader
import coil3.ImageLoader
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.test.A_SESSION_ID

View file

@ -7,7 +7,7 @@
package io.element.android.libraries.matrix.ui.media
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.matrix.api.MatrixClient
class FakeLoggedInImageLoaderFactory(

View file

@ -25,7 +25,7 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil3.compose.AsyncImage
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.components.BigIcon

View file

@ -23,8 +23,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalInspectionMode
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight

View file

@ -30,8 +30,8 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.preview.ElementPreview

View file

@ -46,7 +46,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil3.compose.AsyncImage
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.architecture.AsyncData

View file

@ -9,7 +9,7 @@ package io.element.android.libraries.push.api.notifications
import android.graphics.Bitmap
import androidx.core.graphics.drawable.IconCompat
import coil.ImageLoader
import coil3.ImageLoader
interface NotificationBitmapLoader {
/**

View file

@ -11,10 +11,11 @@ import android.content.Context
import android.graphics.Bitmap
import android.os.Build
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap
import coil.ImageLoader
import coil.request.ImageRequest
import coil.transform.CircleCropTransformation
import coil3.ImageLoader
import coil3.request.ImageRequest
import coil3.request.transformations
import coil3.toBitmap
import coil3.transform.CircleCropTransformation
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
@ -50,7 +51,7 @@ class DefaultNotificationBitmapLoader @Inject constructor(
.transformations(CircleCropTransformation())
.build()
val result = imageLoader.execute(imageRequest)
result.drawable?.toBitmap()
result.image?.toBitmap()
} catch (e: Throwable) {
Timber.e(e, "Unable to load room bitmap")
null
@ -78,7 +79,7 @@ class DefaultNotificationBitmapLoader @Inject constructor(
.transformations(CircleCropTransformation())
.build()
val result = imageLoader.execute(imageRequest)
val bitmap = result.drawable?.toBitmap()
val bitmap = result.image?.toBitmap()
return bitmap?.let { IconCompat.createWithBitmap(it) }
} catch (e: Throwable) {
Timber.e(e, "Unable to load user bitmap")

View file

@ -12,7 +12,7 @@ import android.graphics.Typeface
import android.text.style.StyleSpan
import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans
import coil.ImageLoader
import coil3.ImageLoader
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.core.RoomId

View file

@ -7,7 +7,7 @@
package io.element.android.libraries.push.impl.notifications
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.api.notifications.NotificationIdProvider

View file

@ -9,7 +9,7 @@ package io.element.android.libraries.push.impl.notifications
import android.app.Notification
import android.graphics.Bitmap
import coil.ImageLoader
import coil3.ImageLoader
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.core.RoomId

View file

@ -16,7 +16,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.MessagingStyle
import androidx.core.app.Person
import androidx.core.content.res.ResourcesCompat
import coil.ImageLoader
import coil3.ImageLoader
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.core.meta.BuildMeta

View file

@ -9,7 +9,7 @@ package io.element.android.libraries.push.impl.notifications.fake
import android.app.Notification
import android.graphics.Bitmap
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.RoomEventGroupInfo

View file

@ -7,7 +7,7 @@
package io.element.android.libraries.push.impl.notifications.fake
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.NotificationDataFactory
import io.element.android.libraries.push.impl.notifications.OneShotNotification

View file

@ -8,7 +8,7 @@
package io.element.android.libraries.push.impl.notifications.fake
import android.app.Notification
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.RoomGroupMessageCreator

View file

@ -9,12 +9,11 @@ package io.element.android.libraries.push.test.notifications
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import coil.ImageLoader
import coil.annotation.ExperimentalCoilApi
import coil.test.FakeImageLoaderEngine
import coil3.ImageLoader
import coil3.test.FakeImageLoaderEngine
import coil3.test.intercept
import org.robolectric.RuntimeEnvironment
@OptIn(ExperimentalCoilApi::class)
class FakeImageLoader {
private val coilRequests = mutableListOf<Any>()

View file

@ -7,7 +7,7 @@
package io.element.android.libraries.push.test.notifications
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder

View file

@ -9,7 +9,7 @@ package io.element.android.libraries.push.test.notifications.push
import android.graphics.Bitmap
import androidx.core.graphics.drawable.IconCompat
import coil.ImageLoader
import coil3.ImageLoader
import io.element.android.libraries.push.api.notifications.NotificationBitmapLoader
class FakeNotificationBitmapLoader(