Skip to content

Commit

Permalink
[AND-330] Migrate to Coil3 (#5645)
Browse files Browse the repository at this point in the history
* Migrate to Coil3

* Update CHANGELOG.md

* Add max fetch retries

* Remove unused method
  • Loading branch information
JcMinarro authored Feb 25, 2025
1 parent a7b00c2 commit 4c399df
Show file tree
Hide file tree
Showing 23 changed files with 173 additions and 237 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
- Add `MessageListViewModel::scrollToFirstUnreadMessage` method. [#5635](https://github.com/GetStream/stream-chat-android/pull/5635)

### ⚠️ Changed
- Upgrade to Coil 3. If you use Coil internally in your app and want to upgrade it, you can follow [their migration guide](https://coil-kt.github.io/coil/upgrading_to_coil3/). [#5645](https://github.com/GetStream/stream-chat-android/pull/5645)

### ❌ Removed

Expand All @@ -82,6 +83,7 @@

### ⚠️ Changed
- 🚨Breaking change: Change the `AttachmentPickerPollCreation` event to hold a prepared `PollConfig` to simplify the poll creation handling. [#5634](https://github.com/GetStream/stream-chat-android/pull/5634)
- Upgrade to Coil 3. If you use Coil internally in your app and want to upgrade it, you can follow [their migration guide](https://coil-kt.github.io/coil/upgrading_to_coil3/). [#5645](https://github.com/GetStream/stream-chat-android/pull/5645)

### ❌ Removed

Expand Down
15 changes: 8 additions & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ androidxUiAutomator = "2.4.0-alpha01"
androidxViewPager2 = "1.1.0"
androidxTest = "1.5.2"
baseProfile = "1.3.1"
coil = "2.7.0"
coil = "3.1.0"
composeAccompanist = "0.36.0"
composeMarkdown = "0.5.4"
composeStableMarker = "1.0.5"
Expand Down Expand Up @@ -57,7 +57,7 @@ kotest = "5.9.1"
kotlin = "2.0.21"
kotlinBinaryValidator = "0.16.3"
ksp = "2.0.21-1.0.28"
landscapist = "2.3.6"
landscapist = "2.4.7"
leakCanary = "2.4"
macroBenchmark = "1.2.3"
markwon = "4.6.2"
Expand Down Expand Up @@ -149,10 +149,11 @@ androidx-test-junit-ktx = { module = "androidx.test.ext:junit-ktx", version.ref
androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "androidxViewPager2"}
androidx-work = { module = "androidx.work:work-runtime-ktx", version.ref = "work"}
androidx-work-testing = { module = "androidx.work:work-testing", version.ref = "work"}
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-video = { module = "io.coil-kt:coil-video", 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-video = { module = "io.coil-kt.coil3:coil-video", version.ref = "coil"}
compose-markdown = { module = "com.github.jeziellago:compose-markdown", version.ref = "composeMarkdown"}
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detektPlugin"}
firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx", version.ref = "firebaseAnalytics"}
Expand Down Expand Up @@ -202,7 +203,7 @@ robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectr
shimmer = { module = "com.facebook.shimmer:shimmer", version.ref = "shimmer"}
shimmer-compose = { module = "com.valentinilk.shimmer:compose-shimmer", version.ref = "shimmerCompose"}
skydoves-compose-stable-marker = { module = "com.github.skydoves:compose-stable-marker", version.ref = "composeStableMarker"}
skydoves-landscapist-coil = { module = "com.github.skydoves:landscapist-coil", version.ref = "landscapist"}
skydoves-landscapist-coil = { module = "com.github.skydoves:landscapist-coil3", version.ref = "landscapist"}
skydoves-landscapist-placeholder = { module = "com.github.skydoves:landscapist-placeholder", version.ref = "landscapist"}
skydoves-landscapist-animation = { module = "com.github.skydoves:landscapist-animation", version.ref = "landscapist"}
stream-android-push = { module = "io.getstream:stream-android-push", version.ref = "streamPush"}
Expand Down
10 changes: 5 additions & 5 deletions stream-chat-android-compose/api/stream-chat-android-compose.api
Original file line number Diff line number Diff line change
Expand Up @@ -3612,8 +3612,8 @@ public final class io/getstream/chat/android/compose/ui/util/ImageUtilsKt {
public static final fun StreamImage (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;Lcom/skydoves/landscapist/components/ImageComponent;Lcom/skydoves/landscapist/ImageOptions;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V
public static final fun StreamImage (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;Lcom/skydoves/landscapist/components/ImageComponent;Lkotlin/jvm/functions/Function0;Lcom/skydoves/landscapist/ImageOptions;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V
public static final fun mirrorRtl (Landroidx/compose/ui/Modifier;Landroidx/compose/ui/unit/LayoutDirection;)Landroidx/compose/ui/Modifier;
public static final fun rememberStreamImagePainter-MqR-F_0 (Lcoil/request/ImageRequest;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/layout/ContentScale;ILandroidx/compose/runtime/Composer;II)Lcoil/compose/AsyncImagePainter;
public static final fun rememberStreamImagePainter-MqR-F_0 (Ljava/lang/Object;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/layout/ContentScale;ILandroidx/compose/runtime/Composer;II)Lcoil/compose/AsyncImagePainter;
public static final fun rememberStreamImagePainter-MqR-F_0 (Lcoil3/request/ImageRequest;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/layout/ContentScale;ILandroidx/compose/runtime/Composer;II)Lcoil3/compose/AsyncImagePainter;
public static final fun rememberStreamImagePainter-MqR-F_0 (Ljava/lang/Object;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/graphics/painter/Painter;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/layout/ContentScale;ILandroidx/compose/runtime/Composer;II)Lcoil3/compose/AsyncImagePainter;
}

public final class io/getstream/chat/android/compose/ui/util/LocalStreamImageLoaderKt {
Expand Down Expand Up @@ -3745,7 +3745,7 @@ public final class io/getstream/chat/android/compose/ui/util/StorageHelperWrappe

public abstract interface class io/getstream/chat/android/compose/ui/util/StreamCoilImageLoaderFactory {
public static final field Companion Lio/getstream/chat/android/compose/ui/util/StreamCoilImageLoaderFactory$Companion;
public abstract fun imageLoader (Landroid/content/Context;)Lcoil/ImageLoader;
public abstract fun imageLoader (Landroid/content/Context;)Lcoil3/ImageLoader;
}

public final class io/getstream/chat/android/compose/ui/util/StreamCoilImageLoaderFactory$Companion {
Expand All @@ -3758,10 +3758,10 @@ public final class io/getstream/chat/android/compose/ui/util/StreamImageLoaderPr
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Landroidx/compose/runtime/ProvidableCompositionLocal;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Landroidx/compose/runtime/ProvidableCompositionLocal;Landroidx/compose/runtime/ProvidableCompositionLocal;)Z
public static final fun getCurrent (Landroidx/compose/runtime/ProvidableCompositionLocal;Landroidx/compose/runtime/Composer;I)Lcoil/ImageLoader;
public static final fun getCurrent (Landroidx/compose/runtime/ProvidableCompositionLocal;Landroidx/compose/runtime/Composer;I)Lcoil3/ImageLoader;
public fun hashCode ()I
public static fun hashCode-impl (Landroidx/compose/runtime/ProvidableCompositionLocal;)I
public static final fun provides-impl (Landroidx/compose/runtime/ProvidableCompositionLocal;Lcoil/ImageLoader;)Landroidx/compose/runtime/ProvidedValue;
public static final fun provides-impl (Landroidx/compose/runtime/ProvidableCompositionLocal;Lcoil3/ImageLoader;)Landroidx/compose/runtime/ProvidedValue;
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Landroidx/compose/runtime/ProvidableCompositionLocal;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Landroidx/compose/runtime/ProvidableCompositionLocal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImagePainter
import io.getstream.chat.android.client.utils.attachment.isGiphy
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.state.messages.attachments.AttachmentState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
Expand All @@ -58,9 +56,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import coil.compose.AsyncImagePainter
import coil.request.ImageRequest
import io.getstream.chat.android.client.ChatClient
import coil3.compose.AsyncImagePainter
import coil3.request.ImageRequest
import io.getstream.chat.android.client.utils.attachment.isImage
import io.getstream.chat.android.client.utils.attachment.isVideo
import io.getstream.chat.android.compose.R
Expand All @@ -69,8 +66,6 @@ import io.getstream.chat.android.compose.state.messages.attachments.AttachmentSt
import io.getstream.chat.android.compose.ui.attachments.preview.MediaGalleryPreviewContract
import io.getstream.chat.android.compose.ui.components.ShimmerProgressIndicator
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.util.ImageRequestTimeoutHandler
import io.getstream.chat.android.compose.ui.util.RetryHash
import io.getstream.chat.android.compose.ui.util.StreamAsyncImage
import io.getstream.chat.android.models.Attachment
import io.getstream.chat.android.models.AttachmentType
Expand Down Expand Up @@ -404,14 +399,9 @@ internal fun MediaAttachmentContentItem(
) -> Unit,
overlayContent: @Composable (attachmentType: String?) -> Unit,
) {
val connectionState by ChatClient.instance().clientState.connectionState.collectAsState()
val isImage = attachment.isImage()
val isVideo = attachment.isVideo()

// Used as a workaround for Coil's lack of a retry policy.
// See: https://github.com/coil-kt/coil/issues/884#issuecomment-975932886
var retryHash by remember { mutableIntStateOf(0) }

val data =
if (isImage || (isVideo && ChatTheme.videoThumbnailsEnabled)) {
when (message.syncStatus) {
Expand All @@ -425,10 +415,9 @@ internal fun MediaAttachmentContentItem(
}

val context = LocalContext.current
val imageRequest = remember(retryHash) {
val imageRequest = remember {
ImageRequest.Builder(context)
.data(data)
.setParameter(key = RetryHash, value = retryHash)
.build()
}

Expand All @@ -439,15 +428,6 @@ internal fun MediaAttachmentContentItem(
onResult = { result -> onMediaGalleryPreviewResult(result) },
)

// Used to refresh the request for the current page if it has previously failed.
ImageRequestTimeoutHandler(
data = data,
connectionState = connectionState,
imageState = imageState,
) {
retryHash++
}

val areVideosEnabled = ChatTheme.videoThumbnailsEnabled
val streamCdnImageResizing = ChatTheme.streamCdnImageResizing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
Expand All @@ -116,8 +115,8 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import coil.compose.AsyncImagePainter
import coil.request.ImageRequest
import coil3.compose.AsyncImagePainter
import coil3.request.ImageRequest
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState
Expand Down Expand Up @@ -147,8 +146,6 @@ import io.getstream.chat.android.compose.ui.components.SimpleDialog
import io.getstream.chat.android.compose.ui.components.Timestamp
import io.getstream.chat.android.compose.ui.components.avatar.Avatar
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.util.ImageRequestTimeoutHandler
import io.getstream.chat.android.compose.ui.util.RetryHash
import io.getstream.chat.android.compose.ui.util.StreamAsyncImage
import io.getstream.chat.android.compose.ui.util.StreamImage
import io.getstream.chat.android.compose.ui.util.isCompleted
Expand Down Expand Up @@ -801,16 +798,11 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
// Used as a workaround for Coil's lack of a retry policy.
// See: https://github.com/coil-kt/coil/issues/884#issuecomment-975932886
var retryHash by remember { mutableIntStateOf(0) }

val data = attachment.imagePreviewUrl
val context = LocalContext.current
val imageRequest = remember(retryHash) {
val imageRequest = remember {
ImageRequest.Builder(context)
.data(data)
.setParameter(key = RetryHash, value = retryHash)
.build()
}

Expand All @@ -825,20 +817,11 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {

val scale by animateFloatAsState(targetValue = currentScale, label = "")

// Used to refresh the request if it has previously failed.
ImageRequestTimeoutHandler(
data = data,
connectionState = mediaGalleryPreviewViewModel.connectionState,
imageState = imageState,
) {
retryHash++
}

val transformModifier = if (imageState is AsyncImagePainter.State.Success) {
val state = imageState as AsyncImagePainter.State.Success
val size = Size(
width = state.result.drawable.intrinsicWidth.toFloat(),
height = state.result.drawable.intrinsicHeight.toFloat(),
width = state.result.image.width.toFloat(),
height = state.result.image.height.toFloat(),
)
Modifier
.aspectRatio(size.width / size.height, true)
Expand Down Expand Up @@ -1579,11 +1562,6 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
) {
val isImage = attachment.isImage()
val isVideo = attachment.isVideo()

// Used as a workaround for Coil's lack of a retry policy.
// See: https://github.com/coil-kt/coil/issues/884#issuecomment-975932886
var retryHash by remember { mutableIntStateOf(0) }

val coroutineScope = rememberCoroutineScope()

Box(
Expand All @@ -1610,24 +1588,14 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
}

val context = LocalContext.current
val imageRequest = remember(retryHash) {
val imageRequest = remember {
ImageRequest.Builder(context)
.data(data)
.setParameter(RetryHash, retryHash.toString())
.build()
}

var imageState by remember { mutableStateOf<AsyncImagePainter.State>(AsyncImagePainter.State.Empty) }

// Used to refresh the request if it has previously failed.
ImageRequestTimeoutHandler(
data = data,
connectionState = mediaGalleryPreviewViewModel.connectionState,
imageState = imageState,
) {
retryHash++
}

val backgroundColor = if (isImage) {
ChatTheme.colors.imageBackgroundMediaGalleryPicker
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import coil.decode.VideoFrameDecoder
import coil.request.ImageRequest
import coil.request.videoFrameMillis
import coil3.request.ImageRequest
import coil3.video.VideoFrameDecoder
import coil3.video.videoFrameMillis
import com.skydoves.landscapist.ImageOptions
import com.skydoves.landscapist.coil.CoilImage
import com.skydoves.landscapist.coil3.CoilImage
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.state.messages.attachments.AttachmentPickerItemState
import io.getstream.chat.android.compose.ui.theme.ChatTheme
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImagePainter
import coil3.compose.AsyncImagePainter
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.util.StreamAsyncImage
import io.getstream.chat.android.ui.common.images.resizing.applyStreamCdnImageResizingIfEnabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import coil.ImageLoader
import coil3.ImageLoader
import com.valentinilk.shimmer.LocalShimmerTheme
import io.getstream.chat.android.client.ChatClient
import io.getstream.chat.android.client.header.VersionPrefixHeader
Expand Down
Loading

0 comments on commit 4c399df

Please sign in to comment.