Skip to content

Commit 8d003bc

Browse files
authored
Merge pull request #3552 from GetStream/develop
Next Release
2 parents 6681c12 + 96b3cd3 commit 8d003bc

File tree

946 files changed

+58731
-34259
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

946 files changed

+58731
-34259
lines changed

.github/actions/install-and-build-sdk/action.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ runs:
1616
cd package/native-package/
1717
yarn
1818
shell: bash
19-
- name: Install & Build the Expo Package
20-
run: |
21-
cd package/expo-package/
22-
yarn
23-
shell: bash
2419
- name: Install & Build the Sample App
2520
working-directory: examples/SampleApp
2621
run: yarn

.github/workflows/changelog-preview.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
uses: actions/setup-node@v4
1818
with:
1919
node-version: ${{ matrix.node-version }}
20+
- name: Install Linux build tools
21+
run: sudo apt-get update && sudo apt-get install -y build-essential
2022
- uses: actions/checkout@v2
2123
with:
2224
ref: develop

.github/workflows/check-pr.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323
uses: actions/setup-node@v4
2424
with:
2525
node-version: ${{ matrix.node-version }}
26+
- name: Install Linux build tools
27+
run: sudo apt-get update && sudo apt-get install -y build-essential
2628
- name: Install && Build - SDK and Sample App
2729
uses: ./.github/actions/install-and-build-sdk
2830
- name: Lint

.github/workflows/release.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ on:
77
- develop
88

99
permissions:
10-
id-token: write # for OIDC / npm provenance if you use it
11-
actions: write # if you dispatch other workflows
12-
contents: write # commits / tags / merge-back
10+
id-token: write # for OIDC / npm provenance if you use it
11+
actions: write # if you dispatch other workflows
12+
contents: write # commits / tags / merge-back
1313

1414
jobs:
1515
publish:
@@ -21,7 +21,7 @@ jobs:
2121
steps:
2222
- uses: actions/checkout@v2
2323
with:
24-
fetch-depth: "0"
24+
fetch-depth: '0'
2525

2626
- name: Fetch tags
2727
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
@@ -30,7 +30,9 @@ jobs:
3030
uses: actions/setup-node@v4
3131
with:
3232
node-version: ${{ matrix.node-version }}
33-
registry-url: "https://registry.npmjs.org"
33+
registry-url: 'https://registry.npmjs.org'
34+
- name: Install Linux build tools
35+
run: sudo apt-get update && sudo apt-get install -y build-essential
3436

3537
- name: Prepare git
3638
run: |

.github/workflows/sample-distribution.yml

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
runs-on: [macos-15]
1818
strategy:
1919
matrix:
20-
node-version: [ 24.x ]
20+
node-version: [24.x]
2121
steps:
2222
- name: Connect Bot
2323
uses: webfactory/ssh-agent@v0.7.0
@@ -30,7 +30,7 @@ jobs:
3030
- uses: actions/checkout@v3
3131
- uses: maxim-lobanov/setup-xcode@v1
3232
with:
33-
xcode-version: '16.4.0' # Update as needed
33+
xcode-version: '26.2' # Update as needed
3434
- uses: ./.github/actions/ruby-cache
3535
- name: Install && Build - SDK and Sample App
3636
uses: ./.github/actions/install-and-build-sdk
@@ -51,49 +51,40 @@ jobs:
5151
bundle exec pod install
5252
- name: Build and release Testflight QA
5353
working-directory: examples/SampleApp
54-
run: bundle exec fastlane deploy_to_testflight_qa deploy:${{ github.ref == 'refs/heads/develop' }};
54+
run: bundle exec fastlane ios deploy_to_testflight_qa deploy:${{ github.ref == 'refs/heads/develop' }};
5555
env:
5656
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
5757
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}
5858
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
5959

60-
build_and_deploy_android_s3:
60+
build_and_deploy_android_firebase:
6161
name: Build SampleApp Android and Deploy-${{ github.ref == 'refs/heads/develop' }}
6262
runs-on: ubuntu-latest
6363
strategy:
6464
matrix:
65-
node-version: [ 24.x ]
65+
node-version: [24.x]
6666
steps:
6767
- name: Use Node.js ${{ matrix.node-version }}
6868
uses: actions/setup-node@v4
6969
with:
7070
node-version: ${{ matrix.node-version }}
7171
- uses: actions/checkout@v2
72+
- name: Install Linux build tools
73+
run: sudo apt-get update && sudo apt-get install -y build-essential
7274
- uses: actions/setup-java@v3
7375
with:
7476
distribution: 'zulu'
7577
java-version: '17'
7678
check-latest: true
79+
- name: Setup Android SDK
80+
uses: amyu/setup-android@v5
81+
82+
- uses: ./.github/actions/ruby-cache
7783
- name: Install && Build - SDK and Sample App
7884
uses: ./.github/actions/install-and-build-sdk
79-
- name: Build
85+
- name: Build and deploy Android Firebase
8086
working-directory: examples/SampleApp
81-
run: |
82-
mkdir android/app/src/main/assets
83-
mkdir tmp
84-
yarn react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest tmp
85-
cd android
86-
rm -rf $HOME/.gradle/caches/ && ./gradlew assembleRelease
87-
- name: Configure AWS credentials
88-
uses: aws-actions/configure-aws-credentials@v1
89-
if: ${{ github.ref == 'refs/heads/develop' }}
90-
with:
91-
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
92-
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
93-
aws-region: us-east-1
94-
- name: Upload APK
95-
if: ${{ github.ref == 'refs/heads/develop' }}
96-
# https://getstream.io/downloads/rn-sample-app.apk
97-
run: |
98-
cp examples/SampleApp/android/app/build/outputs/apk/release/app-release.apk rn-sample-app.apk
99-
aws s3 cp rn-sample-app.apk s3://${{ secrets.AWS_S3_BUCKET }} --sse AES256
87+
run: bundle exec fastlane android firebase_build_and_upload deploy:${{ github.ref == 'refs/heads/develop' }};
88+
env:
89+
ANDROID_FIREBASE_APP_ID: ${{ secrets.ANDROID_FIREBASE_APP_ID }}
90+
FIREBASE_CREDENTIALS_JSON: ${{ secrets.FIREBASE_CREDENTIALS_JSON }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ index.android.bundle
2323
*.app
2424
*.DSYM.zip
2525
**/metrics/
26+
package/shared-native/.sync-state/

CLAUDE.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Repository Overview
6+
7+
Stream Chat React Native SDK monorepo. The main SDK code lives in `package/` (published as `stream-chat-react-native-core`). Built on top of the `stream-chat` JS client library.
8+
9+
## Common Commands
10+
11+
All commands below run from the repo root unless noted otherwise.
12+
13+
### Build
14+
15+
```bash
16+
yarn build # Build all packages (runs in package/)
17+
cd package && yarn build # Build SDK directly
18+
```
19+
20+
### Lint & Format
21+
22+
```bash
23+
cd package && yarn lint # Check prettier + eslint + translation validation (max-warnings 0)
24+
cd package && yarn lint-fix # Auto-fix lint and formatting issues
25+
```
26+
27+
### Test
28+
29+
```bash
30+
cd package && yarn test:unit # Run all unit tests (sets TZ=UTC)
31+
cd package && yarn test:coverage # Run with coverage report
32+
cd package && TZ=UTC npx jest path/to/test.test.tsx # Run a single test file
33+
```
34+
35+
Tests use Jest with `react-native` preset and `@testing-library/react-native`. Test files live alongside source at `src/**/__tests__/*.test.ts(x)`. Mock builders are in `src/mock-builders/`.
36+
37+
To run a single test, you can also temporarily add the file path to the `testRegex` array in `package/jest.config.js`.
38+
39+
### Install
40+
41+
```bash
42+
yarn install --frozen-lockfile # Root dependencies
43+
cd package && yarn install-all # SDK + native-package + expo-package
44+
```
45+
46+
### Sample App
47+
48+
```bash
49+
cd examples/SampleApp && yarn install
50+
cd examples/SampleApp && yarn start # Metro bundler
51+
cd examples/SampleApp && yarn ios # Run iOS
52+
cd examples/SampleApp && yarn android # Run Android
53+
```
54+
55+
## Architecture
56+
57+
### Package Structure
58+
59+
- `package/` — Main SDK (`stream-chat-react-native-core`)
60+
- `package/native-package/` — React Native native module wrappers
61+
- `package/expo-package/` — Expo-compatible wrapper
62+
- `examples/SampleApp/` — Full sample app with navigation
63+
- `release/` — Semantic release scripts
64+
65+
### SDK Source (`package/src/`)
66+
67+
**Component hierarchy**: `<Chat>``<Channel>``<MessageList>` / `<MessageInput>` / `<Thread>`
68+
69+
- `components/` — UI components (~28 major ones: ChannelList, MessageList, MessageInput, Thread, Poll, ImageGallery, etc.)
70+
- `contexts/` — React Context providers (~33 contexts). The primary way components receive state and callbacks. Key contexts: `ChatContext`, `ChannelContext`, `MessagesContext`, `ThemeContext`, `TranslationContext`
71+
- `hooks/` — Custom hooks (~27+). Access contexts via `useChannelContext()`, `useMessageContext()`, etc.
72+
- `state-store/` — Client-side state stores using `useSyncExternalStore` with selector pattern (audio player, image gallery, message overlay, etc.)
73+
- `store/` — Offline SQLite persistence layer. `OfflineDB` class with mappers for channels, messages, reactions, members, drafts, reminders. Schema in `store/schema.ts`
74+
- `theme/` — Deep theming system (colors, typography, spacing, per-component overrides) via `ThemeContext`
75+
- `i18n/` — Internationalization with i18next (14 languages). `Streami18n` wrapper class
76+
- `middlewares/` — Command UI middlewares (attachments, emoji)
77+
- `icons/` — SVG icon components
78+
79+
### Key Patterns
80+
81+
**Component override pattern**: Nearly every UI element is replaceable via props. Parent components (e.g., `Channel`) accept 50+ `React.ComponentType` props for sub-components (`Message`, `MessageContent`, `DateHeader`, `TypingIndicator`, etc.). These props are forwarded into Context providers so deeply nested children can access them without prop drilling.
82+
83+
**Context three-layer pattern**: Each context follows the same structure:
84+
85+
1. `createContext()` with a sentinel default value (`DEFAULT_BASE_CONTEXT_VALUE`)
86+
2. A `<XProvider>` wrapper component
87+
3. A `useXContext()` hook that throws if used outside the provider (suppressed in test env via `isTestEnvironment()`)
88+
89+
Context values are assembled in dedicated `useCreateXContext()` hooks (e.g., `useCreateChannelContext`) that carefully memoize with selective dependencies to avoid unnecessary re-renders.
90+
91+
**Native module abstraction**: `native.ts` defines TypeScript interfaces for all platform-specific capabilities (image picking, compression, haptics, audio/video, clipboard). Implementations are injected at runtime via `registerNativeHandlers()``stream-chat-expo` provides Expo implementations, `stream-chat-react-native` provides bare RN ones. Calling an unregistered handler throws with a message to import the right package.
92+
93+
**State stores**: `useSyncExternalStore`-based stores in `state-store/` with `useStateStore(store, selector)` for fine-grained subscriptions outside the context system.
94+
95+
**Memoization**: Components use `React.memo()` with custom `areEqual` comparators (not HOCs) to prevent re-renders.
96+
97+
**Offline-first**: SQLite-backed persistence with sync status tracking and pending task management.
98+
99+
**Builder-bob builds**: Outputs CommonJS (`lib/commonjs`), ESM (`lib/module`), and TypeScript declarations (`lib/typescript`).
100+
101+
### Testing Patterns
102+
103+
Tests use `renderHook()` and `render()` from `@testing-library/react-native`. Components/hooks must be wrapped in the required provider stack (e.g., `Chat``Channel` → feature provider).
104+
105+
**Mock builders** (`src/mock-builders/`):
106+
107+
- `api/initiateClientWithChannels.js` — creates a test client + channels in one call
108+
- `generator/` — factories: `generateMessage()`, `generateChannel()`, `generateUser()`, `generateMember()`, `generateStaticMessage(seed)` (deterministic via UUID v5)
109+
- `attachments.js``generateImageAttachment()`, `generateFileAttachment()`, `generateAudioAttachment()`
110+
111+
Reanimated and native modules are mocked via Proxy patterns in test setup files.
112+
113+
### Theme System
114+
115+
Themes follow a three-tier token architecture: **Primitives** (raw colors) → **Semantics** (e.g., `colors.error.primary`) → **Components** (per-component overrides). Token references use `$key` string syntax (e.g., `"$blue500"`) and are resolved via topological sort in `theme/topologicalResolution.ts`, so declaration order doesn't matter.
116+
117+
Platform-specific tokens are **generated** files in `src/theme/generated/{light,dark}/StreamTokens.{ios,android,web}.ts` — regenerate via `sync-theme.sh` if design tokens change; don't hand-edit.
118+
119+
Custom themes are passed as `style` prop to `<Chat>`. `mergeThemes()` deep-merges custom style over base theme (deep-cloned via `JSON.parse(JSON.stringify())`). Light/dark mode is auto-detected via `useColorScheme()`.
120+
121+
### Native / Expo Package Relationship
122+
123+
`native-package/` and `expo-package/` are thin wrappers around `stream-chat-react-native-core`. They:
124+
125+
1. Call `registerNativeHandlers()` with platform-specific implementations (native modules vs Expo APIs)
126+
2. Export optional dependency wrappers (`Audio`, `Video`, `FlatList`) from `src/optionalDependencies/`
127+
3. Re-export everything from core: `export * from 'stream-chat-react-native-core'`
128+
129+
Platform branching uses runtime `Platform.select()` / `Platform.OS` checks — there are no `.ios.ts` / `.android.ts` source file splits.
130+
131+
### Chat Component (Root Provider)
132+
133+
`<Chat client={client}>` is the entry point. It:
134+
135+
- Sets SDK metadata on the `stream-chat` client (identifier, device info)
136+
- Disables the JS client's `recoverStateOnReconnect` (the SDK handles recovery itself)
137+
- Registers subscriptions for threads, polls, and reminders (cleaned up on unmount)
138+
- Initializes `OfflineDB` if `enableOfflineSupport` is true
139+
- Wraps children in: `ChatProvider``TranslationProvider``ThemeProvider``ChannelsStateProvider`
140+
141+
### Offline DB
142+
143+
SQLite schema is in `store/schema.ts`. DB versioning uses `PRAGMA user_version` — a version mismatch triggers full DB reinit (no incremental migrations). Current version is tracked in `SqliteClient.dbVersion`.
144+
145+
### Translations
146+
147+
Translation JSON files live in `src/i18n/`. `validate-translations` (run as part of `yarn lint`) checks that no translation key has an empty string value. When adding/updating translations, run `yarn build-translations` (i18next-cli sync) to keep files in sync.
148+
149+
## Conventions
150+
151+
- **Conventional commits** enforced by commitlint: `feat:`, `fix:`, `docs:`, `refactor:`, etc.
152+
- **ESLint 9 flat config** at `package/eslint.config.mjs`, strict (max-warnings 0)
153+
- **Prettier**: single quotes, trailing commas, 100 char width (see `.prettierrc`)
154+
- **TypeScript strict mode** with platform-specific module suffixes (`.ios`, `.android`, `.web`)
155+
- Git branches: PRs target `develop`, `main` is production releases only
156+
- **Shared native sync**: Run `yarn shared-native:sync` from `package/` after modifying shared native code to copy to native-package and expo-package

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
[![NPM](https://img.shields.io/npm/v/stream-chat-react-native.svg)](https://www.npmjs.com/package/stream-chat-react-native)
1111
[![Build Status](https://github.com/GetStream/stream-chat-react-native/actions/workflows/release.yml/badge.svg)](https://github.com/GetStream/stream-chat-react-native/actions)
1212
[![Component Reference](https://img.shields.io/badge/docs-component%20reference-blue.svg)](https://getstream.io/chat/docs/sdk/reactnative)
13-
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-302%20KB-blue)
13+
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-304%20KB-blue)
1414

1515
<img align="right" src="https://getstream.imgix.net/images/ios-chat-tutorial/iphone_chat_art@3x.png?auto=format,enhance" width="50%" />
1616

examples/ExpoMessaging/app.json

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"experiments": {
1919
"reactCompiler": true
2020
},
21-
"assetBundlePatterns": ["**/*"],
21+
"assetBundlePatterns": [
22+
"**/*"
23+
],
2224
"ios": {
2325
"supportsTablet": true,
2426
"usesIcloudStorage": true,
@@ -86,16 +88,21 @@
8688
"expo-build-properties",
8789
{
8890
"android": {
89-
"extraMavenRepos": ["$rootDir/../../../node_modules/@notifee/react-native/android/libs"]
91+
"extraMavenRepos": [
92+
"$rootDir/../../../node_modules/@notifee/react-native/android/libs"
93+
]
9094
},
9195
"ios": {
9296
"useFrameworks": "static",
93-
"forceStaticLinking": ["RNFBApp", "RNFBMessaging"]
97+
"forceStaticLinking": [
98+
"RNFBApp",
99+
"RNFBMessaging"
100+
]
94101
}
95102
}
96103
],
97-
"./plugins/keyboardInsetMainActivityListener.js",
98-
"./plugins/opSqliteSwiftPlugin.js"
104+
"./plugins/opSqliteSwiftPlugin.js",
105+
"expo-sharing"
99106
]
100107
}
101108
}

0 commit comments

Comments
 (0)