Skip to content
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

[i269] Add theming for reaction and message options in ChatTheme #5226

Merged
merged 10 commits into from
Jun 18, 2024
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,12 @@
### ⬆️ Improved

### ✅ Added
- Added `MessageOptionItemVisibility` class that controls menu item visibility in the selected message options menu.
- Added new `ChatTheme.messageOptionItemVisibility` property of type `MessageOptionItemVisibility`.
- Added docs sections that describe these changes.

### ⚠️ Changed
- Used the new `ChatTheme.messageOptionItemVisibility` property in `defaultMessageOptionsState()` in combination with own capabilities to control menu option item visibility.

### ❌ Removed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ The `ChatTheme` component is a wrapper that **you should use as the root** of al
* `attachmentPreviewHandlers`: Used to provide previews for all supported attachment types. If you do not wish to use the default previews, you can customize this.
* `quotedAttachmentFactories`: Used to process messages and show different types of attachment UI, when quoting a message that contains an attachment.
* `reactionIconFactory`: Used to create a reaction icon for the given reaction type. You can use the default factory that supports a predefined set of reactions, or provide a custom one.
* `reactionOptionsTheme`: Used to define the appearance of the reaction option list in the selected message menu. For theming the message option list in the same menu, see `messageOptionsTheme` below.
* `dateFormatter`: Used to define the timestamp formatting in the app. You can use the default formatting, or customize it to your needs.
* `channelNameFormatter`: Used to define the channel name formatting in the app. You can use the default implementation, or customize it according to your needs.
* `messagePreviewFormatter`: Used to define the message preview formatting in the app. You can use the default implementation, or customize the display of message previews according to your needs.
* `imageLoaderFactory`: Used to create Coil image loader instances. You can use the default image loader factory, or provide a custom one.
* `messageAlignmentProvider`: Used to provide an alignment for a particular message. You can use the default implementation which aligns the messages of the current user to end, or customize it according to your needs.
* `messageOptionsTheme`: Used to define the appearance of the message option list in the selected message menu. For theming the reaction option list in the same menu, see `reactionOptionsTheme` above.
* `messageOptionsUserReactionAlignment`: Used to define how message reactions are aligned when browsing all reactions for a given message.
* `permissionHandlers`: Used to handle permissions inside the app. Default implementation of the download permission handler automatically downloads files after the permission has been granted.
* `attachmentsPickerTabFactories`: Used to display different tabs in the attachments picker dialog.
Expand Down Expand Up @@ -170,6 +172,12 @@ You can find their definitions in the [class documentation](https://github.com/G

Reactions are easily customizable by passing in your own `ReactionIconFactory` which contains reactions and overriding `ChatTheme.reactionIconFactory` with it.

### ReactionOptionsTheme

Defines the appearance of the reaction option list in the selected message menu. Allows you to show/hide options through the `areReactionOptionsVisible` parameter.

See the [class documentation](https://github.com/GetStream/stream-chat-android/blob/0817af6b82cd72d541ed5e816fef8a3a27441e69/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ReactionOptionsTheme.kt) for more details.

### DateFormatter

Used for formatting various times and dates such as the timestamp you see when a message is displayed. The default date formatter in `ChatTheme` is Stream's `DefaultDateFormatter`.
Expand Down Expand Up @@ -303,6 +311,12 @@ You can find out more about it by reading the [class documentation](https://gith

As with all of the other `ChatTheme` properties, you can easily customize how the messages are aligned by overriding `ChatTheme.messageAlignmentProvider` with your own implementation of `MessageAlignmentProvider`.

### MessageOptionsTheme

Defines the appearance of the message option list in the selected message menu. Allows you to show/hide options through the `optionVisibility` parameter.

See the [class documentation](https://github.com/GetStream/stream-chat-android/blob/e01d636f66fb0986ab71288f4ddee92afe550fd0/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/MessageOptionsTheme.kt) for more details.

### MessageOptionsUserReactionAlignment

Determines the alignment of the reaction icon inside user reactions. By default, they are aligned to the end.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public fun defaultMessageOptionsState(
): List<MessageOptionItemState>
```

This function uses `ownCapabilities` to produce the correct list of `MessageOptionItemState`.
This function uses the [`ChatTheme.messageOptionsTheme.optionVisibility`](../general-customization/chat-theme.mdx#messageoptionstheme) property and `ownCapabilities` to produce the correct list of `MessageOptionItemState`. Read more about customizing what options `SelectedMessageMenu` shows [here](../message-components/selected-message-menu.mdx#customizing-the-menu-option-list).

`defaultMessageOptionsState` regulates the following capabilities:

Expand Down Expand Up @@ -182,7 +182,7 @@ Additionally, the capability '**send-typing-events ***' is implemented in our `M
our `MessageComposerViewModel`.
Please keep this in mind should you wish to not use our `ViewModel`s.

# How capabilities affect the UI
## How capabilities affect the UI

Let's take `MessageComposer` into consideration.
If we left it with the default, empty set of own capabilities we would get the following result:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Selecting Messages
---
toc_max_heading_level: 4
---

# Selected Message Menu

The `SelectedMessageMenu` component allows you to show different message options to the user when they select a message in the `MessageList`. This is usually done by long tapping on a message item.

Expand Down Expand Up @@ -99,7 +103,7 @@ Next, let's see how to customize the menu.

## Customization

You can customize the reactions you show, as well as the message options in this component:
You can customize the `SelectedMessageMenu` component by using the following parameters:

```kotlin
@Composable
Expand All @@ -114,15 +118,44 @@ fun SelectedMessageMenu(
)
```

* `messageOptions`: Allows you to customize which message options are shown in the overlay. You can use `defaultMessageOptionsState()` to get the default actions that we expose in our SDK.
* `messageOptions`: Allows you to customize which message options are shown in the overlay. See [below](#customizing-the-menu-option-list).
* `modifier`: Modifier for the dialog component.
* `overlayColor`: Allows you to customize the color of the overlay.
* `shape`: Allows you to customize the shape of the dialog.
* `reactionTypes`: Allows you to customize which reactions show in the overlay. By default it uses `ChatTheme.reactionIconFactory` which is exposed by the [`ChatTheme`](../general-customization/chat-theme.mdx) component.
* `reactionTypes`: Allows you to customize which reactions show in the overlay. See [below](#customizing-reactions).

#### Customizing the Menu Option List

You can pass `defaultMessageOptionsState()` to the `messageOptions` parameter to get the default actions that we expose in our SDK. This function uses the [`ChatTheme.messageOptionsTheme.optionVisibility`](../general-customization/chat-theme.mdx#messageoptionstheme) property and [own capabilities](../guides/implementing-own-capabilities.mdx) under the hood to control which action is visible to the user.

The values that `defaultMessageOptionsState()` gets from `ChatTheme.messageOptionsTheme.optionVisibility` take precedence over own capabilities, so you can pass your own implementation of [`MessageOptionTheme`](https://github.com/GetStream/stream-chat-android/blob/e01d636f66fb0986ab71288f4ddee92afe550fd0/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/MessageOptionsTheme.kt) to `ChatTheme.messageOptionsTheme` to control which options to show. This is useful when you are using `MessagesScreen`, for example, which sets up `SelectedMessageMenu` automatically.

```kotlin
ChatTheme(
// ...
messageOptionsTheme = MessageOptionsTheme.defaultTheme(
optionVisibility = MessageOptionItemVisibility(
isMarkAsUnreadVisible = false,
isCopyTextVisible = false,
),
),
// ...
) {
// Rest of the UI
}
```

#### Customizing Reactions

By default, the `reactionTypes` parameter uses [`ChatTheme.reactionIconFactory`](../general-customization/chat-theme.mdx#reactioniconfactory) as a value which is exposed by the [`ChatTheme`](../general-customization/chat-theme.mdx) component.

The best way to customize reactions is by overriding `ChatTheme.reactionIconFactory` with your own implementation of `ReactionIconFactory` so that all of your components wrapped inside of `ChatTheme` draw from the same source.

By default `SelectedMessageMenu` looks like a bottom sheet, however you can customize it to look like a completely different component, such as a dialog, a drawer or whatever helps you retain the look and feel of your app.
You can also control the reaction list visibility by using your own implementation of `ReactionOptionsTheme` for the [`ChatTheme.reactionOptionsTheme`](../general-customization/chat-theme.mdx#reactionoptionstheme) parameter.

#### Customizing the Appearance

By default `SelectedMessageMenu` looks like a bottom sheet. However you can customize it to look like a completely different component, such as a dialog, a drawer or whatever helps you retain the look and feel of your app.

```kotlin
if (selectedMessageState is SelectedMessageOptionsState) {
Expand Down Expand Up @@ -154,7 +187,9 @@ The code above will produce the following UI:
|---|---|
| ![Stylised SelectedMessageMenu component](../../assets/compose_custom_selected_message_menu_shape_and_alignment.png) | ![Stylised SelectedMessageMenu component dark](../../assets/compose_custom_selected_message_menu_shape_and_alignment_dark.png) |

`SelectedMessageMenu` provides you with `Composable` slots that are ready for more extensive customizations.
#### Customizing by Using Slots

`SelectedMessageMenu` provides you with `Composable` slots that are ready for more extensive customizations:

```kotlin
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import io.getstream.chat.android.compose.sample.R
import io.getstream.chat.android.compose.state.mediagallerypreview.MediaGalleryPreviewResultType
import io.getstream.chat.android.compose.state.messages.attachments.StatefulStreamMediaRecorder
import io.getstream.chat.android.compose.ui.components.composer.MessageInput
import io.getstream.chat.android.compose.ui.components.messageoptions.MessageOptionItemVisibility
import io.getstream.chat.android.compose.ui.components.messageoptions.defaultMessageOptionsState
import io.getstream.chat.android.compose.ui.components.reactionpicker.ReactionsPicker
import io.getstream.chat.android.compose.ui.components.selectedmessage.SelectedMessageMenu
Expand All @@ -63,6 +64,8 @@ import io.getstream.chat.android.compose.ui.messages.composer.MessageComposer
import io.getstream.chat.android.compose.ui.messages.list.MessageList
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.theme.MessageComposerTheme
import io.getstream.chat.android.compose.ui.theme.MessageOptionsTheme
import io.getstream.chat.android.compose.ui.theme.ReactionOptionsTheme
import io.getstream.chat.android.compose.ui.theme.StreamColors
import io.getstream.chat.android.compose.ui.theme.StreamTypography
import io.getstream.chat.android.compose.ui.util.rememberMessageListState
Expand Down Expand Up @@ -126,6 +129,10 @@ class MessagesActivity : BaseConnectedActivity() {
),
)
},
reactionOptionsTheme = ReactionOptionsTheme.defaultTheme(),
messageOptionsTheme = MessageOptionsTheme.defaultTheme(
optionVisibility = MessageOptionItemVisibility(),
),
) {
MessagesScreen(
viewModelFactory = factory,
Expand Down
Loading
Loading