Skip to content

Next Release#3664

Merged
isekovanic merged 17 commits into
mainfrom
develop
Jun 17, 2026
Merged

Next Release#3664
isekovanic merged 17 commits into
mainfrom
develop

Conversation

@isekovanic

Copy link
Copy Markdown
Contributor

🎯 Goal

πŸ›  Implementation details

🎨 UI Changes

iOS
Before After
Android
Before After

πŸ§ͺ Testing

β˜‘οΈ Checklist

  • I have signed the Stream CLA (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

Stream-SDK-Bot and others added 17 commits June 10, 2026 10:54
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>
@isekovanic isekovanic requested review from oliverlaz and szuperaz June 17, 2026 15:27
@github-actions

Copy link
Copy Markdown

Next releases

v9.4.0

9.4.0 (2026-06-17)

Bug Fixes

Features

Performance Improvements

sampleapp@v4.13.0

4.13.0 (2026-06-17)

Bug Fixes

Features

@Stream-SDK-Bot

Copy link
Copy Markdown
Contributor

SDK Size

title develop branch diff status
js_bundle_size 1952 KB 1952 KB 0 B 🟒

@isekovanic isekovanic merged commit c0fb731 into main Jun 17, 2026
16 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants