Next Release#3664
Merged
Merged
Conversation
This PR was created automatically by CI. Co-authored-by: Stream Bot <runner@runnervm1li68.tmrcckyg3riehbbdw0tjeliahb.cx.internal.cloudapp.net>
## π― Goal Followup to [this PR](#3637). The patch is unfortunately a noop, because on an `Android` release build it introduces other issues. The only viable idea is sadly to downgrade for now until the upstream RNGH issues are resolved. ## π Implementation details <!-- Provide a description of the implementation --> ## π¨ UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## π§ͺ Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## βοΈ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
1/2 PR for channel details | [Figma](https://www.figma.com/design/Us73erK1xFNcB5EH3hyq6Y/Chat-SDK-Design-System?node-id=21176-240736&m=dev) This PR implements the 20/25 channel details related Figma screens. The rest will come in a separate PR. The missing screens are implemented in SampleApp (as channel details screens are currently implemented there). All new components/hooks/contexts are marked as experimental by the SDK, the flag will be removed once channel details are fully implemented. Some follow-up tasks we discovered with Ivan that are not related to channel details, I'll implement it in separate follow-up PRs: - Move channel actions override to channel preview (and deprecate channel list override?) - Add capability checks to channel actions - Add an alert to existing destructive actions - Add search to members screen - Fix useChannelMemberOnlineCount - Finalize role display Overview of implemented screens: <img width="1792" height="752" alt="Screenshot 2026-06-03 at 12 25 02" src="https://github.com/user-attachments/assets/04e5279c-017c-4646-8048-4a1c0ef79133" /> Some screenshots, mixed from iOS and Android, dark and light theme: <img height="500" alt="IMG_1242" src="https://github.com/user-attachments/assets/36d2b468-25d3-4022-a695-e8b2eeb53103" /> <img height="500" alt="Screenshot_20260602_204533_Chat Sample React Native" src="https://github.com/user-attachments/assets/c943ce6d-dea8-4482-8a6d-d91389fc0f6b" /> <img height="500" alt="IMG_1247" src="https://github.com/user-attachments/assets/bf26308b-2e1e-46ea-891c-e3b8fb6f35b8" /> <img height="500" alt="Screenshot_20260602_204600_Chat Sample React Native" src="https://github.com/user-attachments/assets/b5a877dd-3f52-47cb-b90f-8c387414ae77" /> <img height="500" alt="Screenshot_20260602_204615_Chat Sample React Native" src="https://github.com/user-attachments/assets/7fc08a5a-b553-46dc-81a2-4202789c5df0" /> <img height="500" alt="IMG_1246" src="https://github.com/user-attachments/assets/fd39e56b-94cc-4826-9916-c4591366b2a5" /> <img height="500" alt="Screenshot_20260602_204633_Chat Sample React Native" src="https://github.com/user-attachments/assets/18f172ff-c649-4946-b9bb-76de2960ab99" /> Claude's recap: The headline of this branch is a brand-new **Channel Details screen** shipped as a reusable SDK component, with the SampleApp migrated off its old custom overlay implementation. ## SampleApp **Removed** the entire legacy overlay-based channel info system: - Overlay infrastructure: `AppOverlayContext`, `AppOverlayProvider`, `ChannelInfoOverlayContext`, `UserInfoOverlayContext`, `OverlayBackdrop`, `ChannelInfoOverlay`, `UserInfoOverlay`, `ContactDetailBottomSheet` - Old member UI: `AddMembersBottomSheet`, `AllMembersBottomSheet`, `MemberListItem`, `ChannelDetailProfileSection`, and hooks `useChannelInfoOverlayActions` / `useUserInfoOverlayActions` - Old screens: `GroupChannelDetailsScreen`, `OneOnOneChannelDetailScreen`, `SharedGroupsScreen` **Added / updated:** - New thin `ChannelDetailsScreen` that consumes the SDK component, plus a `ChannelDetailsNavigationSection` override example - New `SendDirectMessage` icon (removed `Archive`, `UserMinus`) - Updated `ChannelListScreen`, `ChannelScreen`, `NewDirectMessagingScreen`, `App.tsx`, `types.ts`, and `SampleAppComponentOverrides` to wire up the new screen ## SDK β new **`ChannelDetailsScreen` component suite** (new export from `components/index.ts`): - Core: `ChannelDetailsScreen`, `ChannelDetailsProfile`, `ChannelDetailsActionsSection`, `ChannelDetailsActionItem`, `ChannelDetailsMemberSection`, `ChannelDetailsNavigationSection`, `ChannelDetailsScreenHeader` - Edit flow: `ChannelEditDetails`, `ChannelEditDetailsModal`, `ChannelEditName`, `ChannelEditImageSheet` - Members: `ChannelMemberList`, `ChannelMemberItem`, `ChannelMemberActionsSheet`, `ChannelAddMembers` (+modal), `ChannelAllMembersModal`, `AddMemberSearchResultItem`, and loading skeletons - Generic `Modal` / `ModalHeader` building blocks **New hooks** β `package/src/hooks/actions/` namespace (`useChannelActions`, `useChannelActionItems`, `useChannelMemberActionItems`, `useUserActions`, shared `types`), feature hooks (`useChannelDetailsActionItems`, `useChannelDetailsMembersPreview`, `useChannelDetailsMemberStatusText`, `useEditChannelImage`, `useUserActivityStatus`, `useChannelAddMembers`, `useChannelAllMembers`, `useMemberRoleLabel`), and reusable channel hooks now exported publicly: `useChannelName`, `useChannelImage`, `useChannelMemberCount`, `useChannelOwnCapabilities`, `useChannelMuteActive`, `useIsDirectChat`, plus `useSyncClientEvents` (reactive channel name/image/member-count updates) **New reusable UI / contexts / icons:** - UI components: `SearchInput`, `SelectionCircle`, `EmptySearchResult` - Contexts: `channelDetailsContext` and `BottomSheetContext` - Icons: `chevron-right`, `x-circle` - ~196 lines of new theme tokens for the new components - ~50 new translation keys across all 14 locales (member roles, add-members, edit-channel, a11y labels) ## SDK β updates to existing - **BottomSheetModal** β reworked (~100 lines); fixes the iOS close-callback-fires-too-early bug and now exposes context via the new `BottomSheetContext` - **ChannelAvatar** β extended to show a live preview of pending channel-image changes - **Hook relocations** β `useChannelActions` / `useChannelActionItems` / `useIsDirectChat` / `useChannelMuteActive` moved out of `ChannelList/hooks` into the shared `src/hooks` tree (and `useChannelActions` significantly extended: `onFailure`/`onSuccess` handlers, member/image/name updates, separate dismiss API) - **componentsContext** β registered the new components as defaults (~31 lines); `OwnCapabilitiesContext` gained a capability - **ChannelPreview** β `ChannelDetailsBottomSheet` and `ChannelSwipableWrapper` updated; `useChannelPreviewDisplayName` / `useUserMuteActive` tweaked - **camera icon redesign** β drove snapshot updates for `AttachButton`, `SendButton`, `Thread` - **notificationTarget** β minor update for channel-delete/edit notifications - Repo housekeeping: `CLAUDE.md` typecheck note, accessibility skill tweak, new RTL skill **Scale:** ~80 commits, +12,961 / β3,635 across 166 files, with a large accompanying test suite (~40 new `__tests__` file --------- Co-authored-by: Ivan Sekovanikj <ivan.sekovanikj@getstream.io>
## π― Goal
This PR resolves an issue where the messages grouped positional padding
leaks into the context menu as it's part of the same message component
tree. This is a sideeffect of the wrapped group styles being applied to
the wrong view, as they were intended to be used in the outermost
wrapper always.
Thus, we move them upwards and calculate accordingly.
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal
This PR fixes some minor poll style inconsistencies with the new design.
It also changes poll dialogs to be `pageSheet`s by default on iOS as
well as removing unnecessary views.
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal
This PR fixes an edge case with audio recordings where purely quoted
message recordings with a transparent background become visibly smaller
(due to padding rules applied). This forces their container to work
granularly.
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal
<!-- Describe why we are making this change -->
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal UI SDK PR for [this](GetStream/stream-chat-js#1771). All details are in the other PR. Fixes [this GH issue](#3642). ## π Implementation details <!-- Provide a description of the implementation --> ## π¨ UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## π§ͺ Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## βοΈ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
## π― Goal
We unfortunately have an issue with audio recording on RN CLI, for iOS
specifically that only happens in Testflight released builds.
After a ton of digging this is an attempt to fix it; if it indeed works
I'll update this description with a more technical explanation of what I
think is going on.
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal This PR reverts `react-native-nitro-sound` to version `0.2.9`. It additionally reverts the fix attempt from earlier as they did not work at all. The reason is this github issue on the repo: `https://github.com/hyochan/react-native-nitro-sound/issues/766`. It contains the full context on why we need to do this for now. ## π Implementation details <!-- Provide a description of the implementation --> ## π¨ UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## π§ͺ Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## βοΈ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
## π― Goal This PR introduces channel pinning (a feature already present imperatively within the SDK) with its own UI layer that comes out of the box. It also extends the API a little bit of the channel actions builder so that it's a bit more flexible. Docs PR: GetStream/docs-content#1367 ## π Implementation details <!-- Provide a description of the implementation --> ## π¨ UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## π§ͺ Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## βοΈ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
## π― Goal
This PR addresses some minor inconsistencies of the design with various
edge cases. Most notably, it covers:
- Audio attachment spacing in some constellations
- Poll headers
- Channel screen header
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal
This PR is a quick fix of channel action ordering, for which the default
was broken since the introduction of pinning.
## π Implementation details
<!-- Provide a description of the implementation -->
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal In a `<ChannelList />` we can customize the styles of just about all the text except for the author's name (text changed to red for demonstrating) <img width="403" height="69" alt="image" src="https://github.com/user-attachments/assets/c9c2027c-02af-4e1b-a74e-d922e55b1e92" /> This is, as far as I can tell, because the `username` in [`ChannelMessagePreviewDeliveryStatus`](https://github.com/GetStream/stream-chat-react-native/blob/develop/package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx#L117-L135) doesn't have any ability to provide theme-based styles like the other props. ## π Implementation details Have added a `username` theme property allowing styles to be provided under `channelPreview` ## π¨ UI Changes Consider: ```ts style: { ...theme, channelPreview: { messageDeliveryStatus: { text: { fontSize: 10, color: 'red', }, username: { fontSize: 10, color: 'red', }, }, }, }, ``` <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <th>Before</th> <th>After</th> </tr> </thead> <tbody> <tr> <td> <img width="405" height="321" alt="Before" src="https://github.com/user-attachments/assets/2ead9a13-15e2-44ee-ad78-f9a82b07f11a" /> </td> <td> <img width="408" height="317" alt="After" src="https://github.com/user-attachments/assets/23cc67b0-2934-41e1-bf90-ec039d32206c" /> </td> </tr> </tbody> </table> </details> ## π§ͺ Testing ## βοΈ Checklist - [X] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [x] PR targets the `develop` branch - [ ] Documentation is updated - n/a as far as I can tell for this change - [x] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - unable as there's reanimated version issues on `develop` but should be identical - [x] Expo iOS and Android
## π― Goal
This PR implements the enhanced mentions featureinto the SDK so RN apps
can mention not just users but also `@channel`, `@here`, custom roles
and user groups - with per type colors in the rendered message and full
offline draft round tripping. Bundles the architectural fixes that
surfaced while wiring this up (Android `a11y` bounds, cross screen
portal teleport leak, composer/list animation sync, iOS multiline
regression).
## π Implementation details
Enhanced mentions
Consumes the LLC's five variant `MentionSuggestion`/`MentionEntity`
union (`user | channel | here | role | user_group`).
Composer suggestion rows - `package/src/components/AutoCompleteInput/`
- `AutoCompleteSuggestionItem.tsx`'s `MentionSuggestionItem` is now a
dispatcher that switches on `item.mentionType` and routes to a per type
row. Still overridable via
`useComponentsContext().MentionSuggestionItem` so integrators can
replace just the mention branch.
- New mentionItems/ directory with one component per variant
(MentionUserItem, MentionBroadcastItem, MentionRoleItem,
MentionUserGroupItem), a shared MentionItem primitive, plus reusable
EnhancedMentionContent, EnhancedMentionIcon, TokenizedSuggestionParts β
all exported for custom dispatcher composition.
- New icons: megaphone.tsx (broadcast), shield.tsx (role). User-group
rows reuse the existing PeopleIcon.
Rendered message text - `Message/MessageItemView/utils/renderText.tsx`
- Builds a `MentionEntity[]` from `mentioned_users` +
`mentioned_channel` + `mentioned_here` + `mentioned_roles` +
`mentioned_groups` (`mentioned_group_ids` fallback).
- Regex alternation built longest-first to avoid prefix collisions
(`@here` mustn't shadow `@here-team`).
- Per type color via semantic tokens (chatTextMentionUser / β¦Broadcast /
β¦Role / β¦Group), each defaulting to the umbrella `chatTextMention` so
existing themes look identical.
- `onPress` now carries `additionalInfo: { mentionedEntity, user? }`.
`user` stays populated for user mentions (for back compatibility
reasons).
- Markdown cache key extended to all five mention sources so the text
rerenders when only non-user mentions change.
Memo comparator β MessageItemView/MessageTextContainer.tsx
- React.memo comparator extended to diff mentioned_channel,
mentioned_here, mentioned_roles, and
mentioned_groups/mentioned_group_ids in addition to mentioned_users.
Without this, messages differing only
in non-user mentions would skip re-render.
Offline draft persistence has also been modified to reflect enhanced
mentions.
**Suggestion list architecture**
The mount location of `<AutoCompleteSuggestionList />` is now moved to
`MessageList.tsx` and `MessageFlashList.tsx` - not
`MessageComposer.tsx`, inside its own `<PortalWhileClosingView
portalHostName='overlay-suggestion-list'
portalName='autocomplete-suggestion-list'>` wrapper.
Why: Android's `getBoundsInScreen()` clamps `a11y` bounds to the
parent's measured rect. The composer's wrapping View (~`228` px with
safe area padding) was clipping the absolutely positioned suggestion
list to inverted/empty bounds - `TalkBack` saw nothing, taps didn't
activate. Hoisting into the `flex: 1` `MessageList` container restores
valid `a11y` bounds. Verified with `uiautomator` dump.
**`PortalWhileClosingView` cross screen leak fix**
Removed the early return guard in `syncPortalLayout`:
```
if (!width || !height) {
return;
}
```
The guard kept unmeasured (0Γ0) wrappers off the closing portal stack,
but as a side effect, wrappers with no children (e.g. autocomplete list
before the user types @) never registered. Navigating `Channel` ->
`Thread` (both mount such wrappers, as an example) left the previous
screen's stale entry as the only thing on the host stack and the closing
overlay teleport then stamped `Channel` autocomplete content into the
`Thread` screen. Removing the guard lets empty wrappers register;
teleport for an empty wrapper renders `null` children so nothing
visible.
Accessibility
- New hook `useAnnounceOnShow(visible, message, { delayMs?, priority?
})` - announces on each visible: false -> true transition and resets on
hide. Unlike `useAnnounceOnStateChange`, it doesn't dedupe consecutive
identical strings, so reshows reannounce.
- Applied to `BottomSheetModal` (replaces adhoc `ref` + `useEffect`) and
`AutoCompleteSuggestionList`
- `ai-docs/accessibility.md` and the team `a11y` skill updated to
document `useAnnounceOnShow`, the menu/menuitem iOS only caveat and a
new "floating overlays need a tall parent for Android a11y" rule.
**ClippingFadeBottom**
New `UIComponents/ClippingFadeBottom.tsx` reusable fade primitive used
at the bottom edge of the suggestion list so long lists fade out instead
of hard clipping at the composer edge.
Bundled bug fixes
- iOS multiline `TextInput` regression after RN upgrade - caret jumping
on newline
- `AutoCompleteSuggestionList` animation desync when swithcing between
attachment picker and keyboard
- Accessibility bugs with the suggestions list
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
## π― Goal Implements the missing screens from channel details: <img width="1560" height="645" alt="Screenshot 2026-06-15 at 12 07 28" src="https://github.com/user-attachments/assets/4f18d1a9-729c-4fb7-ac31-365107175ad4" /> Unrelated to this PR: the Edit channel button is moved to its own component, so integrators using a custom header can reuse this component easily. ## π Implementation details Each screen uses a differently configured `MessageSearchSource` to list the given screen's context. API limitation: the search bar on files list screen is not implemented, reason: [missing backend API](https://getstream.slack.com/archives/C0A3JU6C6G3/p1781281413512769?thread_ts=1781119909.226579&cid=C0A3JU6C6G3) The Photos&Videos and Files screens show only user-uploaded content, but since we can only filter attachments in the message search API by `type`, the search response will contain messages with scraped attachments only, [we filter these on client-side](https://getstream.slack.com/archives/C0A3JU6C6G3/p1781182820206529). ## π¨ UI Changes <img height="500" alt="1" src="https://github.com/user-attachments/assets/4b86d234-f5d1-4d6e-8138-fbd622948194" /> <img height="500" alt="2" src="https://github.com/user-attachments/assets/dcfe4b6d-91c6-4c9d-8da0-988b117df7cb" /> <img height="500" alt="2a" src="https://github.com/user-attachments/assets/1ccfd28b-3b95-4007-917c-9bedb28d6915" /> <img height="500" alt="3" src="https://github.com/user-attachments/assets/e1de498f-f476-4b95-a7b4-01e6d375454a" /> <img height="500" alt="4" src="https://github.com/user-attachments/assets/72746658-2ce9-4b05-875b-4672a50d75c2" /> <img height="500" alt="5" src="https://github.com/user-attachments/assets/a6eff2fc-d8c6-4672-881b-e16145809670" /> ## π§ͺ Testing Tested on iOS and Android ## βοΈ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android --------- Co-authored-by: Ivan Sekovanikj <ivan.sekovanikj@getstream.io>
## π― Goal
The fullscreen ImageGallery was designed for in message galleries (<= 4
attachments per message). The newer `ChannelDetails` "Photos & Videos"
feature opens the same gallery with 50β100+ assets, which exposed
several latent problems:
- Android OOM crashes when swiping through video heavy galleries -
ExoPlayer's default 50s buffer (for `react-native-video` as an example)
+ multiple simultaneous `Video` elements blew the Java heap even on mid
tier devices
- Visible swipe jank on Android driven by an avalanche of per swipe
rerenders cascading from `ImageGallery` down through every mounted slide
and every `useAnimatedStyle` worklet
- Latent bugs: stale closures in the `Image.getSize` fallback for asset
dimensions; phantom `isPlaying === true` state after slide unmount;
`useState` for currentImageHeight causing a redundant parent re-render
per
swipe; redundant `[index, setIndex]` state in the gestures hook
duplicating store-side currentIndex; etc
The goal of this PR is to fix the crashes and reduce per swipe rerenders
to the architectural minimum without changing any gallery interactions
visible to the user.
## π Implementation details
Crash fix - `ExoPlayer` buffer config and instance capping
- `AnimatedGalleryVideo` now uses a tighter mount window than the image
side: `shouldRender = Math.abs(currentIndex - index) < 2` (3 slides -
`prev`, `current`, `next`) instead of the original `< 4` (up to 7
slides). Image slides keep the `< 4` window since they're not subject to
the same memory or decoder slot pressure
- Caps simultaneous mounted `<NativeHandlers.Video>` elements at 3
regardless of how many video assets the gallery contains. This is the
structural fix for the original Android crash: `ExoPlayer` instance
count was the primary axis blowing the Java heap and 7+ simultaneous
instances also exceeded Android's hardware `MediaCodec` decoder cap
(~4β6 slots on most mid-tier devices)
- Hardcoded conservative buffer config in both `Video` wrappers
(`native-package/optionalDependencies/Video.tsx` for
`react-native-video` and `expo-package/optionalDependencies/Video.tsx`
for `expo-video`). Each wrapper uses its lib's native API directly and
we apply this automatically:
- `react-native-video`: `bufferConfig` with `minBufferMs: 5000,
maxBufferMs: 10000, bufferForPlaybackMs: 1000,
bufferForPlaybackAfterRebufferMs: 2000`
- `expo-video`: `player.bufferOptions = {
preferredForwardBufferDuration: 10, minBufferForPlayback: 1,
maxBufferBytes: 6_000_000 }` set inside the `useVideoPlayer` setup
callback
- Per instance Java heap source byte usage drops from `~30 MB` (50s of
buffer read ahead at 5 Mbps) to ~6 MB. With three Video elements alive
in the slide window, baseline drops from ~90 MB to ~18 MB on the 256 MB
heap
- Integrators with different needs can replace the `Video` wrapper via
`registerNativeHandlers({ Video: ... })`
Rerender reduction - single source of truth for `currentIndex`
Historically, our gallery appears to be very unoptimized in React terms.
Aside from having many unnecessary rerenders, we'd also rerender each
attachment in the gallery on every index change. In addition to be
terrible semantically, it's also something that we use purely for
animations/gestures.
Conversely, we don't particularly need state anywhere and so we move
most of these interactions to purely shared values to make sure there is
no work on the JS thread at all (or at least as little as possible in
this iteration). For this, we introduce a SV version of `currentIndex`
within the store itself which we keep in lockstep with
`state.currentIndex` via the existing setter. Most notably:
- Worklet consumers (gesture math in `useImageGalleryGestures`,
transforms in `useAnimatedGalleryStyle`, the `useAnimatedReaction` in
`ImageGallery` that drives `translationX`, the `useDerivedValue` for
`headerFooterOpacity`) read `currentIndexShared.value` directly on the
UI thread. This makes sure that animated styles are not recreated on
every swipe
- Dropped the redundant `[index, setIndex] = useState(currentIndex)` in
`useImageGalleryGestures` - moveToNext/Previous read fresh from
`store.state.getLatestValue()`
- Slide components (`AnimatedGalleryImage`, `AnimatedGalleryVideo`)
replaced their `useStateStore({ currentIndex })` subscription with a
slim per instance `useCallback` selector returning only `{ shouldRender
}`. `useStateStore`'s shallow equality will short circuit when the
boolean doesn't flip so most slides stay silent during swipes; only the
1β2 entering or leaving the mount window rerender
- Wrapped `AnimatedGalleryVideo` in `React.memo` so parent rerenders
don't cascade through to mounted video slides (I am mostly against this
but due to how the gallery works right now it would appear that React
compiler cannot figure out that it should stop rendering in these
instances
- Extracted the accessible `"X of N"` View into a separate
`ImageGalleryA11yProbe` sibling component that subscribes to
`currentIndex` locally only mounted when accessibility is enabled.
`ImageGalleryWithContext` itself no longer subscribes to `currentIndex`
at all.
The calculation of `currentImageHeight` has also been moved to a SV.
Smaller fixes
- `AnimatedGalleryVideo`'s cleanup now calls `videoPlayer.onRemove()`
(was just `playerRef = null`) and pauses the native player and zeroes
pooled JS state (isPlaying, position, duration, progress) so a swipe
back doesn't autoplay from the start with a stale state
- Pause active player on index change moved from a `useEffect` in
`ImageGallery` to the `currentIndex` setter on the store and keeps the
invariant local to the state it depends on.
- `useAnimatedGalleryStyle`'s worklet now derives `selected`/`previous`
from `currentIndexShared.value` inside the worklet
- Pan gesture classification threshold unified across iOS and Android
(`maxXYRatio = 0.25` instead of `isAndroid ? 1 : 0.25`). The previous
Android specific 1 made natural diagonal finger arcs misclassify as
vertical, causing the page flip to snap back instead of advancing unless
the gesture has greater momentum
Note: There are many other, less obvious ways to improve the gallery
however I'd like to do those in a separate PR as such heavy refactorings
we'd like to do carefully.
Also, here are some measured metrics (generated by the new performance
script, specifically for Android):
```
βββββββββββββββββββββββββ¬ββββββββββ¬ββββββββββ¬βββββββββββββββββ
β Metric β Develop β Branch β Ξ β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Memory β β β β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Java Heap PSS β 157 MB β 99 MB β β58 MB (β37%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Total PSS β 1.22 GB β 1.21 GB β ~0 β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Views (Objects) β 2552 β 2367 β β185 (β7%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Frame timing β β β β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β 50p frame β 26 ms β 22 ms β β4 ms (β15%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β 90p frame β 73 ms β 61 ms β β12 ms (β16%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β 95p frame β 117 ms β 89 ms β β28 ms (β24%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β 99p frame β 250 ms β 150 ms β β100 ms (β40%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Frame quality β β β β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Janky frames β 20.7% β 15.3% β β5.4pp (β26%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Janky (legacy) β 59.3% β 41.2% β β18.1pp (β31%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Slow bitmap uploads β 17 β 7 β β10 (β59%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Slow UI thread β 113 β 107 β β6 (β5%) β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌβββββββββββββββββ€
β Frame deadline missed β 116 β 111 β β5 (β4%) β
βββββββββββββββββββββββββ΄ββββββββββ΄ββββββββββ΄βββββββββββββββββ
```
(done comparing the **worst** run on this branch as compared to the
**best** run on [this
one](https://github.com/GetStream/stream-chat-react-native/pulls))
## π¨ UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## π§ͺ Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## βοΈ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android
---------
Co-authored-by: Zita Szupera <szuperaz@gmail.com>
Next releasesv9.4.09.4.0 (2026-06-17)Bug Fixes
Features
Performance Improvementssampleapp@v4.13.04.13.0 (2026-06-17)Bug Fixes
Features |
Contributor
SDK Size
|
szuperaz
approved these changes
Jun 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
π― Goal
π Implementation details
π¨ UI Changes
iOS
Android
π§ͺ Testing
βοΈ Checklist
developbranch