Skip to content

Next Release#3567

Merged
isekovanic merged 5 commits intomainfrom
develop
Apr 24, 2026
Merged

Next Release#3567
isekovanic merged 5 commits intomainfrom
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 5 commits April 20, 2026 13:21
This PR was created automatically by CI.

Co-authored-by: Ivan Sekovanikj <31964049+isekovanic@users.noreply.github.com>
Co-authored-by: Stream Bot <runner@runnervmeorf1.mdwwigey15hubdk4xsiuhudezb.dx.internal.cloudapp.net>
…3562)

## Summary

Migrates the remaining JS test infrastructure to TypeScript, then
type-tightens the whole test suite with full `noImplicitAny: true`
strictness and wires `yarn test:typecheck` into CI as a required check.

### Migration (baseline)
- 44 mock-builders (`package/src/mock-builders/`): API response
builders, event dispatchers, data generators, and the core `mock.ts`
client helper
- 36 `.test.js` files → `.test.ts` / `.test.tsx` across components and
utils
- 2 offline-support helpers → `.tsx`
- `test-utils/BetterSqlite.js` → `.ts`
- `jest-setup.js` → `.tsx` (contains JSX for the `BottomSheetModal`
mock)
- New `package/tsconfig.test.json` so tests and mock-builders are
type-checked (base `tsconfig.json` still excludes them from the
published build)
- New `yarn test:typecheck` script, wired into
`.github/workflows/check-pr.yml`

### Type-tightening
- **fix(store,messagelist):** type-annotate empty arrays in 8 source
files where `const queries = []` was inferring `never[]` under the
broader include scope. Real latent issues; no behavior change.
- **refactor(mock-builders):** tighten types in generators and event
dispatchers using SDK types from `stream-chat`; drop fields not on
`Attachment`; add missing `reminders` on default channel config; narrow
`client.channel(...)` args.
- **refactor(mock-builders): `generateMessage` now returns
`LocalMessage`.** Previously typed as `MessageResponse` but at runtime
produced `Date` objects for `created_at`/`updated_at`/`pinned_at` — the
`LocalMessage` shape. Making the type honest eliminated 33 `as unknown
as LocalMessage` casts and 57 `toLocalMessage(…)` wrapper calls across
the suite. API mocks and event dispatchers that legitimately need the
wire shape accept `MessageResponse | LocalMessage` at their boundary.
- **refactor(tests):** annotate all test bodies. Uses the established
`{...} as unknown as XContextValue` pattern for partial context mocks.
Replaces every bogus `as unknown as FileUpload` (leftover silent bug —
`FileUpload` was never imported) with the correct SDK type
(`LocalAudioAttachment` / `LocalVoiceRecordingAttachment`). Uses
`LocalAttachment` (not `Partial<Attachment>`) for attachment mocks that
set `localMetadata`. Uses `ComponentProps<typeof X>` for
`renderComponent({ props })` typings.
- **refactor(tests): flip `noImplicitAny: true`** and annotate the ~630
resulting errors across ~20 test files. `let chatClient: StreamChat`,
typed destructured params, typed `jest.fn()` callbacks,
`ComponentProps<typeof X>` for helper prop shapes. Zero `any` / `as any`
added.

### Dead-prop cleanup
Removing spread+cast and `@ts-ignore` escape hatches made TypeScript
surface a slew of props tests were passing that target components don't
actually accept. 15+ dead props removed across 16 test files. Notable:
- `MessageAuthor`: `alignment`, `groupStyles` (live on
`MessageContextValue`; `MessageAuthor` doesn't pick them).
- `MessageReplies`: `groupStyles`, `MessageRepliesAvatars`, `openThread`
(typo — real prop is `onOpenThread`; silently dropped).
- `Message`: `reactionsEnabled`, `MessageFooter` override.
- `ScrollToBottomButton`: `t` (supplied via `TranslationProvider`).
- `ChannelPreviewView`: `client`, `latestMessagePreview`, `watchers`,
`latestMessage`, `latestMessageLength`.
- `MessageList`: `channelUnreadState` (internal state, never a prop).
- `Channel`: `client` (comes from `ChatContext`, caught on
`Thread.test.tsx`).
- `Giphy` test helper: widened `Record<string, unknown>` →
`ComponentProps<typeof Giphy>`.

Also: zero `@ts-ignore` / `@ts-expect-error` directives remain in any
`*.test.*` file.

### Dependency changes
- `@types/jest`: `^29.5.14` → `^30.0.0` (matches installed `jest@30`)
- `jest`: `^30.0.0` → `^30.3.0`
- `@total-typescript/shoehorn`: new devDependency — `fromPartial<T>()`
for type-safe partial mocks, replacing `as any` / `Record<string, any>`
patterns

### Source-file changes
All zero-behavior-change type annotations:
- `src/store/apis/{addPendingTask,deleteMessage,upsertDraft}.ts`
-
`src/store/sqlite-utils/{appendOrderByClause,appendWhereCluase,createCreateTableQuery}.ts`
- `src/components/MessageList/hooks/useMessageList.ts`
- `src/components/Message/MessageItemView/utils/renderText.tsx` —
`@ts-expect-error` on the untyped `react-native-markdown-package` import
switched to `@ts-ignore` so both base and test tsconfigs agree.

### Follow-ups (out of scope)
- `package/src/store/apis/upsertDraft.ts:55` — `queries.concat(query)`
is a no-op (returns a new array that's never used). Kept out of scope
since fixing it is a behavior change on production code.
- `MessageStatus.test.tsx` had `it.each('string', fn)` (malformed —
string iterated as characters). Converted to `it.skip` to preserve
pre-migration runtime behavior. Un-skipping and rewriting is a
follow-up.

## Test plan

- [x] `yarn build` passes
- [x] `yarn lint` passes
- [x] `yarn test:typecheck` — **0 errors with `noImplicitAny: true` and
full strict mode**
- [x] `yarn test:unit` — 751 passed, 14 skipped. Only the pre-existing
SQLite-isolation flake in `offline-support/index.test.ts` fails
intermittently (baseline on develop was 5 failures; this branch is 1 —
no regressions)
- [x] Zero `@ts-ignore` / `@ts-expect-error` directives remain in any
`*.test.*` file
- [x] `yarn test:typecheck` is wired as a required check in
`.github/workflows/check-pr.yml`
- [x] CI green on push
## 🎯 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

Depends on: GetStream/stream-chat-js#1715

## 🛠 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

---------

Co-authored-by: Ivan Sekovanikj <ivan.sekovanikj@getstream.io>
## 🎯 Goal

This PR adds optional native multipart upload support for React Native
and Expo packages, with native iOS/Android uploaders, a JS axios
adapter, upload progress propagation and new attachment progress UI.
Additionally, it also moves pending attachment uploads onto
`client.uploadManager`, adds local attachment id tracking, improves
video/document attachment handling, and updates SampleApp to exercise
the new native upload path.

The reason why we decided to add an opt-in native upload is related to
the fact that `axios` does not always report upload progress correctly
on React Native, especially Android. It will sometimes either not update
the progress at all or report it badly, causing UI glitches.
Additionally, native uploads are much, much faster as we take advantage
of streaming directly without any intermediate ephemeral files in order
to do that. Finally, `axios` can easily break if an override to the
underlying RN's `fetch` implementation has been made, especially on
`Android`.

  ## What Changed

- Added a shared native multipart upload module for iOS and Android,
including request parsing, file/text multipart parts, progress events,
cancellation, timeouts, response handling, and bounded response body
reads.
- Added native package and Expo package bindings for
`StreamMultipartUploader`, plus native handler registration through
`stream-chat-react-native` and `stream-chat-expo`
- Added core JS helpers and public types for native multipart upload
requests, responses, progress events, abort handling, and uploader
creation
- Added `installNativeMultipartAdapter` /
`wrapAxiosAdapterWithNativeMultipart` to route multipart `FormData`
axios requests through the native uploader when available, while leaving
non-multipart requests on the existing adapter
- Added `Chat` support for enabling native multipart uploads via
`useNativeMultipartUpload`; SampleApp enables this path
- Reworked pending message attachment uploads to use
`client.uploadManager.upload` by local attachment id instead of directly
calling `channel.sendImage` / `channel.sendFile`
- Added `localId` propagation from local attachments into message
attachments so pending uploads can be correlated with
`client.uploadManager`
- Updated message sendability and upload indicator behavior to depend on
`allowSendBeforeAttachmentsUpload` rather than offline support
- Added upload progress UI for image, video, file, and audio
attachments, including circular determinate progress, media overlays,
file/audio byte progress labels, and a short completion hold to avoid UI
flicker
- Added new overrideable/default components for attachment upload
progress: `AttachmentUploadIndicator`, `CircularProgressIndicator`, and
`MediaUploadProgressOverlay`
- Updated gallery/video thumbnail rendering so pending media attachments
can show upload progress overlays
- Updated document picking in both native and Expo packages to generate
thumbnails for picked video files (this was missing from V9 initially)
- Updated iOS video thumbnail URL handling to strip query and fragment
data from local file URLs
- Refined native iOS shimmer behavior to reduce animation restarts,
handle foreground/background transitions, visibility, alpha, trait
changes, and resolved color updates more reliably (this should improve
shimmer performance for iOS significantly)
- Updated `Android` shared native source syncing to resolve shared
native sources from the canonical project path
- Replaced SampleApp’s `react-native-fast-image` dependency with
`@d11/react-native-fast-image`

## 🛠 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

---------

Co-authored-by: Zita Szupera <szuperaz@gmail.com>
@Stream-SDK-Bot
Copy link
Copy Markdown
Contributor

SDK Size

title develop branch diff status
js_bundle_size 360 KB 360 KB 0 B 🟢

@github-actions
Copy link
Copy Markdown

Next releases

v9.1.0

9.1.0 (2026-04-24)

sampleapp@v4.11.0

4.11.0 (2026-04-24)

@isekovanic isekovanic merged commit b70f8d5 into main Apr 24, 2026
6 of 7 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