Skip to content

[AND-464] Provide custom ImageLoader to MediaGalleryPreviewActivity. #5736

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
### 🐞 Fixed
- Fix audio recording attachments not paused when the app goes to the background or the screen is covered with another one. [#5685](https://github.com/GetStream/stream-chat-android/pull/5685)
- Fix crash when multiple answers field is not a valid number when creating a poll. [#5733](https://github.com/GetStream/stream-chat-android/pull/5733)
- Ensure the `ImageLoader` created by a custom `StreamCoilImageLoaderFactory` is passed to the `MediaGalleryPreviewActivity`. [#5736](https://github.com/GetStream/stream-chat-android/pull/5736)

### ⬆️ Improved
- Improve the images loading. [#5724](https://github.com/GetStream/stream-chat-android/pull/5724)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
Expand All @@ -61,9 +62,11 @@ import io.getstream.chat.android.client.utils.attachment.isVideo
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.state.mediagallerypreview.MediaGalleryPreviewResult
import io.getstream.chat.android.compose.state.messages.attachments.AttachmentState
import io.getstream.chat.android.compose.ui.attachments.preview.MediaGalleryInjector
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.LocalStreamImageLoader
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 @@ -116,6 +119,12 @@ public fun MediaAttachmentContent(
val (message, _, onLongItemClick, onMediaGalleryPreviewResult) = attachmentState
val gridSpacing = ChatTheme.dimens.attachmentsContentMediaGridSpacing

// Prepare the image loader for the media gallery
val imageLoader = LocalStreamImageLoader.current
LaunchedEffect(imageLoader) {
MediaGalleryInjector.install(imageLoader)
}

Row(
modifier
.clip(ChatTheme.shapes.attachment)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2014-2025 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.chat.android.compose.ui.attachments.preview

import coil3.ImageLoader

/**
* Injector for non-configuration dependencies of the Media Gallery Activity.
* Serves a bridge the Activity/Fragment which hosts the `MessageList` and the `MediaGalleryPreviewActivity`,
* providing values passed in the `ChatTheme` holding the `MessageList` to the `MediaGalleryPreviewActivity`.
*/
internal object MediaGalleryInjector {

/**
* The [ImageLoader] instance.
*/
@Volatile
var imageLoader: ImageLoader? = null
internal set

/**
* Sets the [ImageLoader] instance.
*
* @param imageLoader The [ImageLoader] instance to set.
*/
fun install(imageLoader: ImageLoader) {
this.imageLoader = imageLoader
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
Expand All @@ -55,6 +56,7 @@ import io.getstream.chat.android.compose.state.mediagallerypreview.ShowInChat
import io.getstream.chat.android.compose.state.mediagallerypreview.toMediaGalleryPreviewActivityState
import io.getstream.chat.android.compose.state.mediagallerypreview.toMessage
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.util.LocalStreamImageLoader
import io.getstream.chat.android.compose.util.attachmentDownloadState
import io.getstream.chat.android.compose.util.onDownloadHandleRequest
import io.getstream.chat.android.compose.viewmodel.mediapreview.MediaGalleryPreviewViewModel
Expand Down Expand Up @@ -161,7 +163,6 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
SetupEdgeToEdge()

val message = mediaGalleryPreviewViewModel.message

if (message.isDeleted()) {
finish()
return@ChatTheme
Expand All @@ -171,24 +172,30 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
val downloadAttachmentUriGenerator = ChatTheme.streamDownloadAttachmentUriGenerator
val downloadRequestInterceptor = ChatTheme.streamDownloadRequestInterceptor

MediaGalleryPreviewScreen(
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
viewModel = mediaGalleryPreviewViewModel,
initialPage = attachmentPosition,
onHeaderLeadingContentClick = ::finish,
onOptionClick = { attachment, option ->
handleMediaAction(
attachment,
option.action,
writePermissionState,
downloadPayload,
downloadAttachmentUriGenerator::generateDownloadUri,
downloadRequestInterceptor::intercept,
)
},
onRequestShareAttachment = ::onRequestShareAttachment,
onConfirmShareAttachment = ::shareAttachment,
)
// Take the imageLoader from the injector, which is populated by the MediaAttachmentContent. This is a
// workaround for the fact that the MediaGalleryPreviewActivity is not a part of the composition tree of
// the MessageList, so the provided imageLoaderFactory from the MessageList ChatTheme cannot be used.
val imageLoader = MediaGalleryInjector.imageLoader ?: LocalStreamImageLoader.current
CompositionLocalProvider(LocalStreamImageLoader provides imageLoader) {
MediaGalleryPreviewScreen(
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
viewModel = mediaGalleryPreviewViewModel,
initialPage = attachmentPosition,
onHeaderLeadingContentClick = ::finish,
onOptionClick = { attachment, option ->
handleMediaAction(
attachment,
option.action,
writePermissionState,
downloadPayload,
downloadAttachmentUriGenerator::generateDownloadUri,
downloadRequestInterceptor::intercept,
)
},
onRequestShareAttachment = ::onRequestShareAttachment,
onConfirmShareAttachment = ::shareAttachment,
)
}
}
}
}
Expand Down
Loading