Skip to content

Commit

Permalink
Merge branch 'develop' into feature/expose-text-formater-and-actions
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandar-apostolov authored Sep 23, 2024
2 parents 13e265b + 3e4b227 commit 8e9ff8a
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Added `actionsProvider` lambda parameter to `NotificationHandlerFactory::createN
- Add a default theme for `MediaPreviewActivity` and `MediaGalleryPreviewActivity`. [#5391](https://github.com/GetStream/stream-chat-android/pull/5391)
- Added typing indicator on `ChannelList`. [#5399](https://github.com/GetStream/stream-chat-android/pull/5399)
- Added support for Audio Recording feature. [#5404](https://github.com/GetStream/stream-chat-android/pull/5404)
- Added `ChatTheme#imageHeadersProvider` to allow adding custom headers to image requests. [#5414](https://github.com/GetStream/stream-chat-android/pull/5414)

### ⚠️ Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ package io.getstream.chat.android.client.api2.mapping

import io.getstream.chat.android.client.api2.model.dto.AttachmentDto
import io.getstream.chat.android.client.api2.model.dto.DownstreamMessageDto
import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto
import io.getstream.chat.android.client.api2.model.dto.UpstreamMessageDto
import io.getstream.chat.android.core.internal.StreamHandsOff
import io.getstream.chat.android.models.Attachment
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.Reaction
import io.getstream.chat.android.models.User
import io.getstream.chat.android.models.UserId
import java.util.Date
Expand Down Expand Up @@ -58,9 +61,9 @@ internal fun DownstreamMessageDto.toDomain(currentUserId: UserId?): Message =
html = html,
i18n = i18n,
id = id,
latestReactions = latest_reactions.mapTo(mutableListOf()) { it.toDomain(currentUserId) },
latestReactions = latest_reactions.toDomain(currentUserId, id),
mentionedUsers = mentioned_users.mapTo(mutableListOf()) { it.toDomain(currentUserId) },
ownReactions = own_reactions.mapTo(mutableListOf()) { it.toDomain(currentUserId) },
ownReactions = own_reactions.toDomain(currentUserId, id),
parentId = parent_id,
pinExpires = pin_expires,
pinned = pinned,
Expand All @@ -87,6 +90,24 @@ internal fun DownstreamMessageDto.toDomain(currentUserId: UserId?): Message =
extraData = extraData.toMutableMap(),
)

/**
* Map a list of [DownstreamReactionDto] to a list of [Reaction].
* They are filtered by [messageId] and mapped to domain model.
*
* @param currentUserId the current user id
* @param messageId the message id
*/
@StreamHandsOff(
reason = "Backend response is including wrong reactions for the message, so we need to filter them manually.",

)
private fun List<DownstreamReactionDto>.toDomain(
currentUserId: UserId?,
messageId: String,
): List<Reaction> =
filter { it.message_id == messageId }
.map { it.toDomain(currentUserId) }

private fun DownstreamMessageDto.lastUpdateTime(): Date = listOfNotNull(
updated_at,
poll?.updated_at,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,7 @@ public final class io/getstream/chat/android/compose/ui/theme/ChatTheme {
public final fun getSearchResultNameFormatter (Landroidx/compose/runtime/Composer;I)Lio/getstream/chat/android/compose/ui/util/SearchResultNameFormatter;
public final fun getShapes (Landroidx/compose/runtime/Composer;I)Lio/getstream/chat/android/compose/ui/theme/StreamShapes;
public final fun getStreamCdnImageResizing (Landroidx/compose/runtime/Composer;I)Lio/getstream/chat/android/ui/common/images/resizing/StreamCdnImageResizing;
public final fun getStreamImageHeadersProvider (Landroidx/compose/runtime/Composer;I)Lio/getstream/chat/android/ui/common/helper/ImageHeadersProvider;
public final fun getStreamMediaRecorder (Landroidx/compose/runtime/Composer;I)Lio/getstream/sdk/chat/audio/recording/StreamMediaRecorder;
public final fun getTimeProvider (Landroidx/compose/runtime/Composer;I)Lio/getstream/chat/android/ui/common/helper/TimeProvider;
public final fun getTypography (Landroidx/compose/runtime/Composer;I)Lio/getstream/chat/android/compose/ui/theme/StreamTypography;
Expand All @@ -1975,7 +1976,7 @@ public final class io/getstream/chat/android/compose/ui/theme/ChatTheme {
}

public final class io/getstream/chat/android/compose/ui/theme/ChatThemeKt {
public static final fun ChatTheme (ZZZZLio/getstream/chat/android/compose/ui/theme/StreamColors;Lio/getstream/chat/android/compose/ui/theme/StreamDimens;Lio/getstream/chat/android/compose/ui/theme/StreamTypography;Lio/getstream/chat/android/compose/ui/theme/StreamShapes;Landroidx/compose/material/ripple/RippleTheme;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lio/getstream/chat/android/compose/ui/util/ReactionIconFactory;Lio/getstream/chat/android/compose/ui/theme/ReactionOptionsTheme;Lio/getstream/chat/android/compose/ui/util/PollSwitchItemFactory;ZLio/getstream/chat/android/ui/common/helper/DateFormatter;Lio/getstream/chat/android/ui/common/helper/TimeProvider;Lio/getstream/chat/android/ui/common/utils/ChannelNameFormatter;Lio/getstream/chat/android/compose/ui/util/MessagePreviewFormatter;Lio/getstream/chat/android/compose/ui/util/SearchResultNameFormatter;Lio/getstream/chat/android/compose/ui/util/StreamCoilImageLoaderFactory;Lio/getstream/chat/android/compose/ui/util/MessageAlignmentProvider;Lio/getstream/chat/android/compose/ui/theme/MessageOptionsTheme;Lio/getstream/chat/android/ui/common/state/messages/list/MessageOptionsUserReactionAlignment;Ljava/util/List;ZLio/getstream/chat/android/ui/common/images/resizing/StreamCdnImageResizing;ZLio/getstream/chat/android/compose/ui/theme/MessageTheme;Lio/getstream/chat/android/compose/ui/theme/MessageTheme;Lio/getstream/chat/android/compose/ui/theme/MessageDateSeparatorTheme;Lio/getstream/chat/android/compose/ui/theme/MessageUnreadSeparatorTheme;Lio/getstream/chat/android/compose/ui/theme/MessageComposerTheme;Lio/getstream/chat/android/compose/ui/theme/AttachmentPickerTheme;Lio/getstream/chat/android/compose/ui/util/MessageTextFormatter;Lio/getstream/chat/android/compose/ui/util/QuotedMessageTextFormatter;Lio/getstream/sdk/chat/audio/recording/StreamMediaRecorder;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;IIIIII)V
public static final fun ChatTheme (ZZZZLio/getstream/chat/android/compose/ui/theme/StreamColors;Lio/getstream/chat/android/compose/ui/theme/StreamDimens;Lio/getstream/chat/android/compose/ui/theme/StreamTypography;Lio/getstream/chat/android/compose/ui/theme/StreamShapes;Landroidx/compose/material/ripple/RippleTheme;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lio/getstream/chat/android/compose/ui/util/ReactionIconFactory;Lio/getstream/chat/android/compose/ui/theme/ReactionOptionsTheme;Lio/getstream/chat/android/compose/ui/util/PollSwitchItemFactory;ZLio/getstream/chat/android/ui/common/helper/DateFormatter;Lio/getstream/chat/android/ui/common/helper/TimeProvider;Lio/getstream/chat/android/ui/common/utils/ChannelNameFormatter;Lio/getstream/chat/android/compose/ui/util/MessagePreviewFormatter;Lio/getstream/chat/android/compose/ui/util/SearchResultNameFormatter;Lio/getstream/chat/android/compose/ui/util/StreamCoilImageLoaderFactory;Lio/getstream/chat/android/ui/common/helper/ImageHeadersProvider;Lio/getstream/chat/android/compose/ui/util/MessageAlignmentProvider;Lio/getstream/chat/android/compose/ui/theme/MessageOptionsTheme;Lio/getstream/chat/android/ui/common/state/messages/list/MessageOptionsUserReactionAlignment;Ljava/util/List;ZLio/getstream/chat/android/ui/common/images/resizing/StreamCdnImageResizing;ZLio/getstream/chat/android/compose/ui/theme/MessageTheme;Lio/getstream/chat/android/compose/ui/theme/MessageTheme;Lio/getstream/chat/android/compose/ui/theme/MessageDateSeparatorTheme;Lio/getstream/chat/android/compose/ui/theme/MessageUnreadSeparatorTheme;Lio/getstream/chat/android/compose/ui/theme/MessageComposerTheme;Lio/getstream/chat/android/compose/ui/theme/AttachmentPickerTheme;Lio/getstream/chat/android/compose/ui/util/MessageTextFormatter;Lio/getstream/chat/android/compose/ui/util/QuotedMessageTextFormatter;Lio/getstream/sdk/chat/audio/recording/StreamMediaRecorder;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;IIIIII)V
}

public final class io/getstream/chat/android/compose/ui/theme/ComponentOffset {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import io.getstream.chat.android.compose.ui.util.ReactionIconFactory
import io.getstream.chat.android.compose.ui.util.SearchResultNameFormatter
import io.getstream.chat.android.compose.ui.util.StreamCoilImageLoaderFactory
import io.getstream.chat.android.ui.common.helper.DateFormatter
import io.getstream.chat.android.ui.common.helper.DefaultImageHeadersProvider
import io.getstream.chat.android.ui.common.helper.ImageHeadersProvider
import io.getstream.chat.android.ui.common.helper.TimeProvider
import io.getstream.chat.android.ui.common.images.resizing.StreamCdnImageResizing
import io.getstream.chat.android.ui.common.state.messages.list.MessageOptionsUserReactionAlignment
Expand Down Expand Up @@ -119,6 +121,9 @@ private val LocalQuotedMessageTextFormatter = compositionLocalOf<QuotedMessageTe
private val LocalSearchResultNameFormatter = compositionLocalOf<SearchResultNameFormatter> {
error("No SearchResultNameFormatter provided! Make sure to wrap all usages of Stream components in a ChatTheme.")
}
private val LocalStreamImageHeadersProvider = compositionLocalOf<ImageHeadersProvider> {
error("No ImageHeadersProvider provided! Make sure to wrap all usages of Stream components in a ChatTheme.")
}
private val LocalMessageAlignmentProvider = compositionLocalOf<MessageAlignmentProvider> {
error("No MessageAlignmentProvider provided! Make sure to wrap all usages of Stream components in a ChatTheme.")
}
Expand Down Expand Up @@ -212,6 +217,7 @@ private val LocalStreamMediaRecorder = compositionLocalOf<StreamMediaRecorder> {
* @param channelNameFormatter [ChannelNameFormatter] Used throughout the app for channel names.
* @param messagePreviewFormatter [MessagePreviewFormatter] Used to generate a string preview for the given message.
* @param imageLoaderFactory A factory that creates new Coil [ImageLoader] instances.
* @param imageHeadersProvider [ImageHeadersProvider] Used to provide headers for image requests.
* @param messageAlignmentProvider [MessageAlignmentProvider] Used to provide message alignment for the given message.
* @param messageOptionsTheme [MessageOptionsTheme] Theme for the message option list in the selected message menu.
* For theming the reaction option list in the same menu, use [reactionOptionsTheme].
Expand Down Expand Up @@ -260,6 +266,7 @@ public fun ChatTheme(
),
searchResultNameFormatter: SearchResultNameFormatter = SearchResultNameFormatter.defaultFormatter(),
imageLoaderFactory: StreamCoilImageLoaderFactory = StreamCoilImageLoaderFactory.defaultFactory(),
imageHeadersProvider: ImageHeadersProvider = DefaultImageHeadersProvider,
messageAlignmentProvider: MessageAlignmentProvider = MessageAlignmentProvider.defaultMessageAlignmentProvider(),
messageOptionsTheme: MessageOptionsTheme = MessageOptionsTheme.defaultTheme(),
messageOptionsUserReactionAlignment: MessageOptionsUserReactionAlignment = MessageOptionsUserReactionAlignment.END,
Expand Down Expand Up @@ -346,6 +353,7 @@ public fun ChatTheme(
LocalMessageComposerTheme provides messageComposerTheme,
LocalAttachmentPickerTheme provides attachmentPickerTheme,
LocalStreamImageLoader provides imageLoaderFactory.imageLoader(LocalContext.current.applicationContext),
LocalStreamImageHeadersProvider provides imageHeadersProvider,
LocalMessageAlignmentProvider provides messageAlignmentProvider,
LocalMessageOptionsTheme provides messageOptionsTheme,
LocalMessageOptionsUserReactionAlignment provides messageOptionsUserReactionAlignment,
Expand Down Expand Up @@ -617,6 +625,11 @@ public object ChatTheme {
@ReadOnlyComposable
get() = LocalAttachmentPickerTheme.current

public val streamImageHeadersProvider: ImageHeadersProvider
@Composable
@ReadOnlyComposable
get() = LocalStreamImageHeadersProvider.current

/**
* Retrieves the current [autoTranslationEnabled] value at the call site's position in the hierarchy.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.getstream.chat.android.compose.ui.util

import android.content.Context
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
Expand All @@ -40,6 +41,8 @@ import com.skydoves.landscapist.components.ImageComponent
import com.skydoves.landscapist.components.rememberImageComponent
import com.skydoves.landscapist.plugins.ImagePlugin
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.ui.common.helper.ImageHeadersProvider
import io.getstream.chat.android.uiutils.util.adjustColorBrightness
import kotlin.math.abs

Expand Down Expand Up @@ -113,12 +116,10 @@ public fun StreamImage(
)? = null,
failure: @Composable (BoxScope.(imageState: CoilImageState.Failure) -> Unit)? = null,
) {
CoilImage(
imageModel = data,
imageLoader = { LocalStreamImageLoader.current },
StreamImage(
imageRequest = data.asImageRequest(LocalContext.current) { listener(requestListener?.invoke()) },
modifier = modifier,
component = component,
requestListener = requestListener,
imageOptions = imageOptions,
onImageStateChanged = onImageStateChanged,
previewPlaceholder = previewPlaceholder,
Expand Down Expand Up @@ -160,7 +161,7 @@ public fun StreamImage(
failure: @Composable (BoxScope.(imageState: CoilImageState.Failure) -> Unit)? = null,
) {
CoilImage(
imageRequest = imageRequest,
imageRequest = imageRequest.provideHeaders(LocalContext.current, ChatTheme.streamImageHeadersProvider),
imageLoader = { LocalStreamImageLoader.current },
modifier = modifier,
component = component,
Expand Down Expand Up @@ -208,14 +209,11 @@ public fun rememberStreamImagePainter(
contentScale: ContentScale = ContentScale.Fit,
filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,
): AsyncImagePainter {
return rememberAsyncImagePainter(
model = ImageRequest.Builder(LocalContext.current)
.data(data)
.build(),
imageLoader = LocalStreamImageLoader.current,
placeholder = placeholderPainter,
error = errorPainter,
fallback = fallbackPainter,
return rememberStreamImagePainter(
model = data.toImageRequest(LocalContext.current),
placeholderPainter = placeholderPainter,
errorPainter = errorPainter,
fallbackPainter = fallbackPainter,
contentScale = contentScale,
onSuccess = onSuccess,
onError = onError,
Expand Down Expand Up @@ -260,7 +258,7 @@ public fun rememberStreamImagePainter(
filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,
): AsyncImagePainter {
return rememberAsyncImagePainter(
model = model,
model = model.provideHeaders(LocalContext.current, ChatTheme.streamImageHeadersProvider),
imageLoader = LocalStreamImageLoader.current,
placeholder = placeholderPainter,
error = errorPainter,
Expand All @@ -273,6 +271,67 @@ public fun rememberStreamImagePainter(
)
}

/**
* Converts the current lambda to another one that returns an [ImageRequest] that can be used to load the image.
*
* @param context The current context.
* @param block The block to apply to the [ImageRequest.Builder].
* @return The lambda that returns the [ImageRequest] that can be used to load the image.
*/
private fun (() -> Any?).asImageRequest(
context: Context,
block: ImageRequest.Builder.() -> Unit = { },
): () -> ImageRequest =
{ this().toImageRequest(context, block) }

/**
* Converts the current data to an [ImageRequest] that can be used to load the image.
*
* @param context The current context.
* @param block The block to apply to the [ImageRequest.Builder].
* @return The [ImageRequest] that can be used to load the image.
*/
private fun Any?.toImageRequest(
context: Context,
block: ImageRequest.Builder.() -> Unit = { },
): ImageRequest =
ImageRequest.Builder(context)
.data(this)
.apply(block)
.build()

/**
* Converts the current lambda to another one that provides headers to the [ImageRequest] based on
* the [ImageHeadersProvider] implementation.
*
* @param context The current context.
* @param imageHeaderProvider The [ImageHeadersProvider] implementation to use.
* @return The lambda that returns the [ImageRequest] with the headers applied.
*/
private fun (() -> ImageRequest).provideHeaders(
context: Context,
imageHeaderProvider: ImageHeadersProvider,
): () -> ImageRequest = { this().provideHeaders(context, imageHeaderProvider) }

/**
* Provides headers to the given [ImageRequest] based on the [ImageHeadersProvider] implementation.
*
* @param context The current context.
* @param imageHeaderProvider The [ImageHeadersProvider] implementation to use.
* @return The [ImageRequest] with the headers applied.
*/
private fun ImageRequest.provideHeaders(
context: Context,
imageHeaderProvider: ImageHeadersProvider,
): ImageRequest =
this.newBuilder(context)
.apply {
imageHeaderProvider.getImageRequestHeaders(this@provideHeaders.data.toString())
.entries
.forEach { addHeader(it.key, it.value) }
}
.build()

/**
* Used to change a parameter set on Coil requests in order
* to force Coil into retrying a request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ public final class io/getstream/chat/android/ui/common/helper/DateFormatter$Comp
public static synthetic fun from$default (Lio/getstream/chat/android/ui/common/helper/DateFormatter$Companion;Landroid/content/Context;Ljava/util/Locale;ILjava/lang/Object;)Lio/getstream/chat/android/ui/common/helper/DateFormatter;
}

public final class io/getstream/chat/android/ui/common/helper/DefaultImageHeadersProvider : io/getstream/chat/android/ui/common/helper/ImageHeadersProvider {
public static final field $stable I
public static final field INSTANCE Lio/getstream/chat/android/ui/common/helper/DefaultImageHeadersProvider;
public fun getImageRequestHeaders (Ljava/lang/String;)Ljava/util/Map;
}

public abstract interface class io/getstream/chat/android/ui/common/helper/ImageHeadersProvider {
public abstract fun getImageRequestHeaders (Ljava/lang/String;)Ljava/util/Map;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public interface ImageHeadersProvider {
public fun getImageRequestHeaders(url: String): Map<String, String>
}

internal object DefaultImageHeadersProvider : ImageHeadersProvider {
override fun getImageRequestHeaders(url: String): Map<String, String> = emptyMap<String, String>()
/**
* Default implementation of [ImageHeadersProvider] that doesn't provide any headers.
*/
public object DefaultImageHeadersProvider : ImageHeadersProvider {
override fun getImageRequestHeaders(url: String): Map<String, String> = emptyMap()
}

0 comments on commit 8e9ff8a

Please sign in to comment.