Skip to content

Commit ead6bf8

Browse files
authored
Merge pull request #4347 from element-hq/feature/bma/coil3
Migrate to coil3
2 parents 491bb1d + 299f2fb commit ead6bf8

File tree

44 files changed

+172
-127
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+172
-127
lines changed

appnav/src/main/kotlin/io/element/android/appnav/LoggedInAppScopeFlowNode.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
* Please see LICENSE files in the repository root for full details.
66
*/
77

8+
@file:OptIn(DelicateCoilApi::class)
9+
810
package io.element.android.appnav
911

1012
import android.os.Parcelable
1113
import androidx.compose.runtime.Composable
1214
import androidx.compose.ui.Modifier
13-
import coil.Coil
15+
import coil3.SingletonImageLoader
16+
import coil3.annotation.DelicateCoilApi
1417
import com.bumble.appyx.core.composable.Children
1518
import com.bumble.appyx.core.lifecycle.subscribe
1619
import com.bumble.appyx.core.modality.BuildContext
@@ -69,7 +72,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
6972
super.onBuilt()
7073
lifecycle.subscribe(
7174
onCreate = {
72-
Coil.setImageLoader(imageLoaderHolder.get(inputs.matrixClient))
75+
SingletonImageLoader.setUnsafe(imageLoaderHolder.get(inputs.matrixClient))
7376
},
7477
)
7578
}

appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
* Please see LICENSE files in the repository root for full details.
66
*/
77

8+
@file:OptIn(DelicateCoilApi::class)
9+
810
package io.element.android.appnav
911

1012
import android.os.Parcelable
1113
import androidx.compose.runtime.Composable
1214
import androidx.compose.ui.Modifier
13-
import coil.Coil
15+
import coil3.SingletonImageLoader
16+
import coil3.annotation.DelicateCoilApi
1417
import com.bumble.appyx.core.lifecycle.subscribe
1518
import com.bumble.appyx.core.modality.BuildContext
1619
import com.bumble.appyx.core.node.Node
@@ -55,7 +58,7 @@ class NotLoggedInFlowNode @AssistedInject constructor(
5558
super.onBuilt()
5659
lifecycle.subscribe(
5760
onCreate = {
58-
Coil.setImageLoader(notLoggedInImageLoaderFactory)
61+
SingletonImageLoader.setUnsafe(notLoggedInImageLoaderFactory.newImageLoader())
5962
},
6063
)
6164
}

features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package io.element.android.features.call.notifications
99

1010
import androidx.core.graphics.drawable.IconCompat
1111
import androidx.test.platform.app.InstrumentationRegistry
12-
import coil.ImageLoader
12+
import coil3.ImageLoader
1313
import com.google.common.truth.Truth.assertThat
1414
import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator
1515
import io.element.android.libraries.matrix.test.AN_EVENT_ID

features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt

+16-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import androidx.compose.foundation.Image
1111
import androidx.compose.foundation.layout.BoxWithConstraints
1212
import androidx.compose.foundation.layout.size
1313
import androidx.compose.runtime.Composable
14+
import androidx.compose.runtime.collectAsState
1415
import androidx.compose.runtime.getValue
1516
import androidx.compose.runtime.mutableIntStateOf
1617
import androidx.compose.runtime.remember
@@ -22,9 +23,10 @@ import androidx.compose.ui.layout.ContentScale
2223
import androidx.compose.ui.platform.LocalContext
2324
import androidx.compose.ui.platform.LocalDensity
2425
import androidx.compose.ui.unit.dp
25-
import coil.compose.AsyncImagePainter
26-
import coil.compose.rememberAsyncImagePainter
27-
import coil.request.ImageRequest
26+
import coil3.Extras
27+
import coil3.compose.AsyncImagePainter
28+
import coil3.compose.rememberAsyncImagePainter
29+
import coil3.request.ImageRequest
2830
import io.element.android.compound.theme.ElementTheme
2931
import io.element.android.features.location.api.internal.StaticMapPlaceholder
3032
import io.element.android.features.location.api.internal.StaticMapUrlBuilder
@@ -33,7 +35,6 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
3335
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
3436
import io.element.android.libraries.designsystem.theme.components.Icon
3537
import io.element.android.libraries.designsystem.utils.CommonDrawables
36-
import timber.log.Timber
3738

3839
/**
3940
* Shows a static map image downloaded via a third party service's static maps API.
@@ -75,14 +76,15 @@ fun StaticMapView(
7576
)
7677
)
7778
.size(width = constraints.maxWidth, height = constraints.maxHeight)
78-
.setParameter("retry_hash", retryHash, memoryCacheKey = null)
79+
.apply {
80+
extras.set(Extras.Key("retry_hash"), retryHash).build()
81+
}
7982
.build()
80-
}.apply {
81-
Timber.d("Static map image request: ${this?.data}")
8283
}
8384
)
8485

85-
if (painter.state is AsyncImagePainter.State.Success) {
86+
val collectedState = painter.state.collectAsState()
87+
if (collectedState.value is AsyncImagePainter.State.Success) {
8688
Image(
8789
painter = painter,
8890
contentDescription = contentDescription,
@@ -100,7 +102,7 @@ fun StaticMapView(
100102
)
101103
} else {
102104
StaticMapPlaceholder(
103-
showProgress = painter.state is AsyncImagePainter.State.Loading,
105+
showProgress = collectedState.value.isLoading(),
104106
contentDescription = contentDescription,
105107
width = maxWidth,
106108
height = maxHeight,
@@ -110,6 +112,11 @@ fun StaticMapView(
110112
}
111113
}
112114

115+
private fun AsyncImagePainter.State.isLoading(): Boolean {
116+
return this is AsyncImagePainter.State.Empty ||
117+
this is AsyncImagePainter.State.Loading
118+
}
119+
113120
@PreviewsDayNight
114121
@Composable
115122
internal fun StaticMapViewPreview() = ElementPreview {

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import androidx.compose.ui.res.stringResource
3333
import androidx.compose.ui.tooling.preview.PreviewParameter
3434
import androidx.compose.ui.unit.dp
3535
import androidx.compose.ui.unit.sp
36-
import coil.compose.AsyncImage
36+
import coil3.compose.AsyncImage
3737
import io.element.android.compound.theme.ElementTheme
3838
import io.element.android.features.messages.impl.R
3939
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ import androidx.compose.ui.semantics.contentDescription
3737
import androidx.compose.ui.semantics.semantics
3838
import androidx.compose.ui.tooling.preview.PreviewParameter
3939
import androidx.compose.ui.unit.dp
40-
import coil.compose.AsyncImage
41-
import coil.compose.AsyncImagePainter
40+
import coil3.compose.AsyncImage
41+
import coil3.compose.AsyncImagePainter
4242
import io.element.android.compound.theme.ElementTheme
4343
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
4444
import io.element.android.features.messages.impl.timeline.components.ATimelineItemEventRow

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import androidx.compose.ui.res.stringResource
2525
import androidx.compose.ui.semantics.contentDescription
2626
import androidx.compose.ui.semantics.semantics
2727
import androidx.compose.ui.tooling.preview.PreviewParameter
28-
import coil.compose.AsyncImage
29-
import coil.compose.AsyncImagePainter
28+
import coil3.compose.AsyncImage
29+
import coil3.compose.AsyncImagePainter
3030
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
3131
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContentProvider
3232
import io.element.android.features.messages.impl.timeline.protection.ProtectedView

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ import androidx.compose.ui.semantics.contentDescription
4040
import androidx.compose.ui.semantics.semantics
4141
import androidx.compose.ui.tooling.preview.PreviewParameter
4242
import androidx.compose.ui.unit.dp
43-
import coil.compose.AsyncImage
44-
import coil.compose.AsyncImagePainter
43+
import coil3.compose.AsyncImage
44+
import coil3.compose.AsyncImagePainter
4545
import io.element.android.compound.theme.ElementTheme
4646
import io.element.android.compound.tokens.generated.CompoundIcons
4747
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import androidx.compose.ui.text.style.TextOverflow
5050
import androidx.compose.ui.tooling.preview.PreviewParameter
5151
import androidx.compose.ui.unit.dp
5252
import androidx.compose.ui.unit.sp
53-
import coil.compose.AsyncImage
53+
import coil3.compose.AsyncImage
5454
import io.element.android.compound.theme.ElementTheme
5555
import io.element.android.features.messages.impl.timeline.components.REACTION_IMAGE_ASPECT_RATIO
5656
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction

features/preferences/impl/build.gradle.kts

+3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ dependencies {
6363
implementation(libs.androidx.datastore.preferences)
6464
api(projects.features.preferences.api)
6565

66+
implementation(platform(libs.network.okhttp.bom))
67+
implementation(libs.network.okhttp)
68+
6669
testImplementation(libs.test.junit)
6770
testImplementation(libs.coroutines.test)
6871
testImplementation(libs.molecule.runtime)

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt

+2-5
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
* Please see LICENSE files in the repository root for full details.
66
*/
77

8-
@file:OptIn(ExperimentalCoilApi::class)
9-
108
package io.element.android.features.preferences.impl.tasks
119

1210
import android.content.Context
13-
import coil.Coil
14-
import coil.annotation.ExperimentalCoilApi
11+
import coil3.SingletonImageLoader
1512
import com.squareup.anvil.annotations.ContributesBinding
1613
import io.element.android.features.ftue.api.state.FtueService
1714
import io.element.android.features.preferences.impl.DefaultCacheService
@@ -43,7 +40,7 @@ class DefaultClearCacheUseCase @Inject constructor(
4340
// Clear Matrix cache
4441
matrixClient.clearCache()
4542
// Clear Coil cache
46-
Coil.imageLoader(context).let {
43+
SingletonImageLoader.get(context).let {
4744
it.diskCache?.clear()
4845
it.memoryCache?.clear()
4946
}

features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
2828
import androidx.compose.ui.text.input.KeyboardType
2929
import androidx.compose.ui.tooling.preview.PreviewParameter
3030
import androidx.compose.ui.unit.dp
31-
import coil.compose.AsyncImage
32-
import coil.request.ImageRequest
31+
import coil3.compose.AsyncImage
32+
import coil3.request.ImageRequest
3333
import io.element.android.features.rageshake.impl.R
3434
import io.element.android.libraries.architecture.AsyncAction
3535
import io.element.android.libraries.designsystem.components.async.AsyncActionView

gradle/libs.versions.toml

+6-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ datetime = "0.6.2"
4242
serialization_json = "1.8.0"
4343

4444
#other
45-
coil = "2.7.0"
45+
coil = "3.1.0"
4646
showkase = "1.0.3"
4747
appyx = "1.6.0"
4848
sqldelight = "2.0.2"
@@ -159,10 +159,11 @@ test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "
159159
test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.5.1"
160160

161161
# Others
162-
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
163-
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
164-
coil_gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
165-
coil_test = { module = "io.coil-kt:coil-test", version.ref = "coil" }
162+
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
163+
coil_network_okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" }
164+
coil_compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
165+
coil_gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" }
166+
coil_test = { module = "io.coil-kt.coil3:coil-test", version.ref = "coil" }
166167
compound = { module = "io.element.android:compound-android", version = "25.2.26" }
167168
datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
168169
serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" }

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt

+10-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package io.element.android.libraries.designsystem.components
99

1010
import android.graphics.Bitmap
1111
import android.graphics.Typeface
12-
import android.graphics.drawable.BitmapDrawable
1312
import android.os.Build
1413
import android.text.TextPaint
1514
import androidx.annotation.FloatRange
@@ -85,9 +84,10 @@ import androidx.compose.ui.unit.dp
8584
import androidx.compose.ui.unit.isSpecified
8685
import androidx.compose.ui.unit.toOffset
8786
import androidx.compose.ui.unit.toSize
88-
import coil.imageLoader
89-
import coil.request.DefaultRequestOptions
90-
import coil.request.ImageRequest
87+
import coil3.SingletonImageLoader
88+
import coil3.request.ImageRequest
89+
import coil3.request.allowHardware
90+
import coil3.toBitmap
9191
import com.airbnb.android.showkase.annotation.ShowkaseComposable
9292
import com.vanniktech.blurhash.BlurHash
9393
import io.element.android.compound.theme.ElementTheme
@@ -328,7 +328,7 @@ fun Modifier.avatarBloom(
328328
ImageRequest.Builder(context)
329329
.data(avatarData)
330330
// Allow cache and default dispatchers
331-
.defaults(DefaultRequestOptions())
331+
.defaults(ImageRequest.Defaults())
332332
// Needed to be able to read pixels from the Bitmap for the hash
333333
.allowHardware(false)
334334
// Reduce size so it loads faster for large avatars
@@ -340,9 +340,11 @@ fun Modifier.avatarBloom(
340340
var blurHash by rememberSaveable(avatarData) { mutableStateOf<String?>(null) }
341341
LaunchedEffect(avatarData) {
342342
withContext(Dispatchers.IO) {
343-
val drawable =
344-
context.imageLoader.execute(painterRequest).drawable ?: return@withContext
345-
val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return@withContext
343+
val bitmap = SingletonImageLoader.get(context)
344+
.execute(painterRequest)
345+
.image
346+
?.toBitmap()
347+
?: return@withContext
346348
blurHash = BlurHash.encode(
347349
bitmap = bitmap,
348350
componentX = BloomDefaults.HASH_COMPONENTS,

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt

+8-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.size
1515
import androidx.compose.foundation.shape.CircleShape
1616
import androidx.compose.runtime.Composable
1717
import androidx.compose.runtime.SideEffect
18+
import androidx.compose.runtime.collectAsState
19+
import androidx.compose.runtime.getValue
1820
import androidx.compose.ui.Alignment
1921
import androidx.compose.ui.Modifier
2022
import androidx.compose.ui.draw.clip
@@ -26,10 +28,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
2628
import androidx.compose.ui.unit.Dp
2729
import androidx.compose.ui.unit.dp
2830
import androidx.compose.ui.unit.sp
29-
import coil.compose.AsyncImage
30-
import coil.compose.AsyncImagePainter
31-
import coil.compose.SubcomposeAsyncImage
32-
import coil.compose.SubcomposeAsyncImageContent
31+
import coil3.compose.AsyncImage
32+
import coil3.compose.AsyncImagePainter
33+
import coil3.compose.SubcomposeAsyncImage
34+
import coil3.compose.SubcomposeAsyncImageContent
3335
import io.element.android.compound.theme.ElementTheme
3436
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
3537
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
@@ -89,7 +91,8 @@ private fun ImageAvatar(
8991
contentScale = ContentScale.Crop,
9092
modifier = modifier
9193
) {
92-
when (val state = painter.state) {
94+
val collectedState by painter.state.collectAsState()
95+
when (val state = collectedState) {
9396
is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()
9497
is AsyncImagePainter.State.Error -> {
9598
SideEffect {

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/blurhash/BlurHashAsyncImage.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue
2020
import androidx.compose.ui.Alignment
2121
import androidx.compose.ui.Modifier
2222
import androidx.compose.ui.layout.ContentScale
23-
import coil.compose.AsyncImage
23+
import coil3.compose.AsyncImage
2424

2525
@Composable
2626
fun BlurHashAsyncImage(

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt

+13-6
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,29 @@ package io.element.android.libraries.designsystem.preview
99

1010
import androidx.compose.foundation.isSystemInDarkTheme
1111
import androidx.compose.runtime.Composable
12+
import androidx.compose.runtime.CompositionLocalProvider
13+
import coil3.annotation.ExperimentalCoilApi
14+
import coil3.compose.AsyncImagePreviewHandler
15+
import coil3.compose.LocalAsyncImagePreviewHandler
1216
import io.element.android.compound.theme.ElementTheme
1317
import io.element.android.libraries.designsystem.theme.components.Surface
1418

19+
@OptIn(ExperimentalCoilApi::class)
1520
@Composable
1621
@Suppress("ModifierMissing")
1722
fun ElementPreview(
1823
darkTheme: Boolean = isSystemInDarkTheme(),
1924
showBackground: Boolean = true,
2025
content: @Composable () -> Unit
2126
) {
22-
ElementTheme(darkTheme = darkTheme) {
23-
if (showBackground) {
24-
// If we have a proper contentColor applied we need a Surface instead of a Box
25-
Surface(content = content)
26-
} else {
27-
content()
27+
CompositionLocalProvider(LocalAsyncImagePreviewHandler provides AsyncImagePreviewHandler { null }) {
28+
ElementTheme(darkTheme = darkTheme) {
29+
if (showBackground) {
30+
// If we have a proper contentColor applied we need a Surface instead of a Box
31+
Surface(content = content)
32+
} else {
33+
content()
34+
}
2835
}
2936
}
3037
}

libraries/matrixui/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434
implementation(projects.libraries.testtags)
3535
implementation(libs.coil.compose)
3636
implementation(libs.coil.gif)
37+
implementation(libs.coil.network.okhttp)
3738
implementation(libs.jsoup)
3839

3940
testImplementation(libs.coroutines.test)

libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnsavedAvatar.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import androidx.compose.ui.graphics.painter.ColorPainter
2424
import androidx.compose.ui.layout.ContentScale
2525
import androidx.compose.ui.platform.LocalContext
2626
import androidx.compose.ui.unit.dp
27-
import coil.compose.AsyncImage
28-
import coil.request.ImageRequest
27+
import coil3.compose.AsyncImage
28+
import coil3.request.ImageRequest
2929
import io.element.android.compound.theme.ElementTheme
3030
import io.element.android.libraries.designsystem.preview.ElementPreview
3131
import io.element.android.libraries.designsystem.preview.PreviewsDayNight

0 commit comments

Comments
 (0)