Skip to content

Commit 9a54ed0

Browse files
isekovanicszuperaz
andauthored
feat: native multipart upload (#3566)
## 🎯 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>
1 parent fcbdae0 commit 9a54ed0

80 files changed

Lines changed: 5201 additions & 382 deletions

File tree

Some content is hidden

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

examples/SampleApp/App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ const DrawerNavigatorWrapper: React.FC<{
341341
enableOfflineSupport
342342
isMessageAIGenerated={isMessageAIGenerated}
343343
i18nInstance={i18nInstance}
344+
useNativeMultipartUpload
344345
>
345346
<StreamChatProvider>
346347
<AppOverlayProvider>

examples/SampleApp/ios/Podfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,34 @@ require Pod::Executable.execute_command('node', ['-p',
55
{paths: [process.argv[1]]},
66
)', __dir__]).strip
77

8+
react_native_path = File.dirname(
9+
Pod::Executable.execute_command('node', ['-p',
10+
'require.resolve(
11+
"react-native/package.json",
12+
{paths: [process.argv[1]]},
13+
)', __dir__]).strip,
14+
)
15+
16+
fmt_podspec_path = File.join(react_native_path, 'third-party-podspecs', 'fmt.podspec')
17+
rct_folly_podspec_path = File.join(react_native_path, 'third-party-podspecs', 'RCT-Folly.podspec')
18+
19+
fmt_podspec = File.read(fmt_podspec_path)
20+
fmt_podspec = fmt_podspec.gsub('spec.version = "11.0.2"', 'spec.version = "12.1.0"')
21+
fmt_podspec = fmt_podspec.gsub(':tag => "11.0.2"', ':tag => "12.1.0"')
22+
fmt_podspec = fmt_podspec.gsub(
23+
'"GCC_WARN_INHIBIT_ALL_WARNINGS" => "YES" # Disable warnings because we don\'t control this library',
24+
"\"GCC_WARN_INHIBIT_ALL_WARNINGS\" => \"YES\", \"OTHER_CPLUSPLUSFLAGS\" => \"$(inherited) -DFMT_USE_CONSTEVAL=0\" # Disable warnings because we don't control this library",
25+
)
26+
File.write(fmt_podspec_path, fmt_podspec)
27+
28+
rct_folly_podspec = File.read(rct_folly_podspec_path)
29+
rct_folly_podspec = rct_folly_podspec.gsub('spec.dependency "fmt", "11.0.2"', 'spec.dependency "fmt", "12.1.0"')
30+
rct_folly_podspec = rct_folly_podspec.gsub(
31+
'"GCC_WARN_INHIBIT_ALL_WARNINGS" => "YES" # Disable warnings because we don\'t control this library',
32+
"\"GCC_WARN_INHIBIT_ALL_WARNINGS\" => \"YES\", \"OTHER_CPLUSPLUSFLAGS\" => \"$(inherited) -DFMT_USE_CONSTEVAL=0\" # Disable warnings because we don't control this library",
33+
)
34+
File.write(rct_folly_podspec_path, rct_folly_podspec)
35+
836
platform :ios, min_ios_version_supported
937
prepare_react_native_project!
1038

@@ -55,5 +83,18 @@ target 'SampleApp' do
5583
:mac_catalyst_enabled => false,
5684
# :ccache_enabled => true
5785
)
86+
87+
installer.pods_project.targets.each do |target|
88+
next unless ['fmt', 'RCT-Folly'].include?(target.name)
89+
90+
target.build_configurations.each do |config|
91+
flags = Array(config.build_settings['OTHER_CPLUSPLUSFLAGS'] || '$(inherited)')
92+
unless flags.include?('-DFMT_USE_CONSTEVAL=0')
93+
flags << '-DFMT_USE_CONSTEVAL=0'
94+
end
95+
config.build_settings['OTHER_CPLUSPLUSFLAGS'] = flags
96+
end
97+
end
98+
5899
end
59100
end

examples/SampleApp/ios/Podfile.lock

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ PODS:
7373
- GoogleUtilities/Reachability (~> 8.1)
7474
- GoogleUtilities/UserDefaults (~> 8.1)
7575
- nanopb (~> 3.30910.0)
76-
- FirebaseRemoteConfigInterop (11.14.0)
76+
- FirebaseRemoteConfigInterop (11.15.0)
7777
- FirebaseSessions (11.13.0):
7878
- FirebaseCore (~> 11.13.0)
7979
- FirebaseCoreExtension (~> 11.13.0)
@@ -83,7 +83,7 @@ PODS:
8383
- GoogleUtilities/UserDefaults (~> 8.1)
8484
- nanopb (~> 3.30910.0)
8585
- PromisesSwift (~> 2.1)
86-
- fmt (11.0.2)
86+
- fmt (12.1.0)
8787
- glog (0.3.5)
8888
- GoogleAppMeasurement (11.13.0):
8989
- GoogleAppMeasurement/AdIdSupport (= 11.13.0)
@@ -138,6 +138,11 @@ PODS:
138138
- hermes-engine (0.81.6):
139139
- hermes-engine/Pre-built (= 0.81.6)
140140
- hermes-engine/Pre-built (0.81.6)
141+
- libavif/core (0.11.1)
142+
- libavif/libdav1d (0.11.1):
143+
- libavif/core
144+
- libdav1d (>= 0.6.0)
145+
- libdav1d (1.2.0)
141146
- libwebp (1.5.0):
142147
- libwebp/demux (= 1.5.0)
143148
- libwebp/mux (= 1.5.0)
@@ -251,20 +256,20 @@ PODS:
251256
- boost
252257
- DoubleConversion
253258
- fast_float (= 8.0.0)
254-
- fmt (= 11.0.2)
259+
- fmt (= 12.1.0)
255260
- glog
256261
- RCT-Folly/Default (= 2024.11.18.00)
257262
- RCT-Folly/Default (2024.11.18.00):
258263
- boost
259264
- DoubleConversion
260265
- fast_float (= 8.0.0)
261-
- fmt (= 11.0.2)
266+
- fmt (= 12.1.0)
262267
- glog
263268
- RCT-Folly/Fabric (2024.11.18.00):
264269
- boost
265270
- DoubleConversion
266271
- fast_float (= 8.0.0)
267-
- fmt (= 11.0.2)
272+
- fmt (= 12.1.0)
268273
- glog
269274
- RCTDeprecation (0.81.6)
270275
- RCTRequired (0.81.6)
@@ -2893,10 +2898,40 @@ PODS:
28932898
- ReactCommon/turbomodule/core
28942899
- SocketRocket
28952900
- Yoga
2896-
- RNFastImage (8.6.3):
2901+
- RNFastImage (8.13.0):
2902+
- boost
2903+
- DoubleConversion
2904+
- fast_float
2905+
- fmt
2906+
- glog
2907+
- hermes-engine
2908+
- libavif/core (~> 0.11.1)
2909+
- libavif/libdav1d (~> 0.11.1)
2910+
- RCT-Folly
2911+
- RCT-Folly/Fabric
2912+
- RCTRequired
2913+
- RCTTypeSafety
28972914
- React-Core
2898-
- SDWebImage (~> 5.11.1)
2899-
- SDWebImageWebPCoder (~> 0.8.4)
2915+
- React-debug
2916+
- React-Fabric
2917+
- React-featureflags
2918+
- React-graphics
2919+
- React-ImageManager
2920+
- React-jsi
2921+
- React-NativeModulesApple
2922+
- React-RCTFabric
2923+
- React-renderercss
2924+
- React-rendererdebug
2925+
- React-utils
2926+
- ReactCodegen
2927+
- ReactCommon/turbomodule/bridging
2928+
- ReactCommon/turbomodule/core
2929+
- SDWebImage (>= 5.19.1)
2930+
- SDWebImageAVIFCoder (~> 0.11.0)
2931+
- SDWebImageSVGCoder (~> 1.7.0)
2932+
- SDWebImageWebPCoder (~> 0.14)
2933+
- SocketRocket
2934+
- Yoga
29002935
- RNFBApp (22.2.1):
29012936
- Firebase/CoreOnly (= 11.13.0)
29022937
- React-Core
@@ -3292,12 +3327,17 @@ PODS:
32923327
- ReactCommon/turbomodule/core
32933328
- SocketRocket
32943329
- Yoga
3295-
- SDWebImage (5.11.1):
3296-
- SDWebImage/Core (= 5.11.1)
3297-
- SDWebImage/Core (5.11.1)
3298-
- SDWebImageWebPCoder (0.8.5):
3330+
- SDWebImage (5.21.7):
3331+
- SDWebImage/Core (= 5.21.7)
3332+
- SDWebImage/Core (5.21.7)
3333+
- SDWebImageAVIFCoder (0.11.1):
3334+
- libavif/core (>= 0.11.0)
3335+
- SDWebImage (~> 5.10)
3336+
- SDWebImageSVGCoder (1.7.0):
3337+
- SDWebImage/Core (~> 5.6)
3338+
- SDWebImageWebPCoder (0.15.0):
32993339
- libwebp (~> 1.0)
3300-
- SDWebImage/Core (~> 5.10)
3340+
- SDWebImage/Core (~> 5.17)
33013341
- SocketRocket (0.7.1)
33023342
- stream-chat-react-native (8.1.0):
33033343
- boost
@@ -3476,7 +3516,7 @@ DEPENDENCIES:
34763516
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
34773517
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
34783518
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
3479-
- RNFastImage (from `../node_modules/react-native-fast-image`)
3519+
- "RNFastImage (from `../node_modules/@d11/react-native-fast-image`)"
34803520
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
34813521
- "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)"
34823522
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
@@ -3508,11 +3548,15 @@ SPEC REPOS:
35083548
- GoogleAppMeasurement
35093549
- GoogleDataTransport
35103550
- GoogleUtilities
3551+
- libavif
3552+
- libdav1d
35113553
- libwebp
35123554
- nanopb
35133555
- PromisesObjC
35143556
- PromisesSwift
35153557
- SDWebImage
3558+
- SDWebImageAVIFCoder
3559+
- SDWebImageSVGCoder
35163560
- SDWebImageWebPCoder
35173561
- SocketRocket
35183562

@@ -3689,7 +3733,7 @@ EXTERNAL SOURCES:
36893733
RNCClipboard:
36903734
:path: "../node_modules/@react-native-clipboard/clipboard"
36913735
RNFastImage:
3692-
:path: "../node_modules/react-native-fast-image"
3736+
:path: "../node_modules/@d11/react-native-fast-image"
36933737
RNFBApp:
36943738
:path: "../node_modules/@react-native-firebase/app"
36953739
RNFBMessaging:
@@ -3731,22 +3775,24 @@ SPEC CHECKSUMS:
37313775
FirebaseCrashlytics: 8281e577b6f85a08ea7aeb8b66f95e1ae430c943
37323776
FirebaseInstallations: 0ee9074f2c1e86561ace168ee1470dc67aabaf02
37333777
FirebaseMessaging: 195bbdb73e6ca1dbc76cd46e73f3552c084ef6e4
3734-
FirebaseRemoteConfigInterop: 7b74ceaa54e28863ed17fa39da8951692725eced
3778+
FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa
37353779
FirebaseSessions: eaa8ec037e7793769defe4201c20bd4d976f9677
3736-
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
3780+
fmt: 12a698626610c2fef5e7d8de472b100baf225f93
37373781
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
37383782
GoogleAppMeasurement: 0dfca1a4b534d123de3945e28f77869d10d0d600
37393783
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
37403784
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
37413785
hermes-engine: 7219f6e751ad6ec7f3d7ec121830ee34dae40749
3786+
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
3787+
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
37423788
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
37433789
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
37443790
NitroModules: 62786c3090e21b6e28baf91ea69257b1b75fdcfd
37453791
NitroSound: ef03d951a0f7bb504f13bdc27ce1271c4c422e22
37463792
op-sqlite: 2e58f87227360fa6251d1fe103d189f11ae8c95f
37473793
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
37483794
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
3749-
RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f
3795+
RCT-Folly: 5a8bea092f38495b327c6eff2dc52ee25c10f637
37503796
RCTDeprecation: d4ef510f229cea15314176aee5e3ba10064a8496
37513797
RCTRequired: 1e41b794629558f6626e2bc39c166ac0ec1c5878
37523798
RCTTypeSafety: 62c8105cf08af634c93d38ea1e8ec8a57b7abc2c
@@ -3821,7 +3867,7 @@ SPEC CHECKSUMS:
38213867
ReactCommon: 66eb46e6696f1f4816b250ab2807389018bacd78
38223868
RNCAsyncStorage: fd44f4b03e007e642e98df6726737bc66e9ba609
38233869
RNCClipboard: e560338bf6cc4656a09ff90610b62ddc0dbdad65
3824-
RNFastImage: 462a183c4b0b6b26fdfd639e1ed6ba37536c3b87
3870+
RNFastImage: 674d5912e174468a60971d2ba9efc7bb43d116fa
38253871
RNFBApp: db9c2e6d36fe579ab19b82c0a4a417ff7569db7e
38263872
RNFBMessaging: de62448d205095171915d622ed5fb45c2be5e075
38273873
RNGestureHandler: 6bc8f2f56c8a68f3380cd159f3a1ae06defcfabb
@@ -3832,13 +3878,15 @@ SPEC CHECKSUMS:
38323878
RNShare: c0f25f3d0ec275239c35cadbc98c94053118bee7
38333879
RNSVG: b1cb00d54dbc3066a3e98732e5418c8361335124
38343880
RNWorklets: 68ab13976d7eba39fb2f0844994a51380e76046d
3835-
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
3836-
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
3881+
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
3882+
SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
3883+
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
3884+
SDWebImageWebPCoder: 0e06e365080397465cc73a7a9b472d8a3bd0f377
38373885
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
38383886
stream-chat-react-native: d15df89b47c1a08bc7db90c316d34b8ac4e13900
38393887
Teleport: ed828b19e62ca8b9ec101d991bf0594b1c1c8812
38403888
Yoga: ff16d80456ce825ffc9400eeccc645a0dfcccdf5
38413889

3842-
PODFILE CHECKSUM: 4f662370295f8f9cee909f1a4c59a614999a209d
3890+
PODFILE CHECKSUM: 84efea5f3e8c9c79671ee6e525f700f244c17388
38433891

38443892
COCOAPODS: 1.15.2

examples/SampleApp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"fastlane:ios-deploy": "bundle exec fastlane ios deploy_to_testflight_qa deploy:true"
3333
},
3434
"dependencies": {
35+
"@d11/react-native-fast-image": "^8.13.0",
3536
"@emoji-mart/data": "^1.2.1",
3637
"@notifee/react-native": "^9.1.8",
3738
"@op-engineering/op-sqlite": "^14.0.4",
@@ -54,7 +55,6 @@
5455
"react": "19.1.4",
5556
"react-native": "0.81.6",
5657
"react-native-blob-util": "^0.22.2",
57-
"react-native-fast-image": "^8.6.3",
5858
"react-native-gesture-handler": "^2.31.0",
5959
"react-native-haptic-feedback": "^2.3.3",
6060
"react-native-image-picker": "^8.2.1",

examples/SampleApp/src/components/SampleAppComponentOverrides.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
22
import { Platform, StyleSheet, useColorScheme, View } from 'react-native';
33
import type { ComponentOverrides } from 'stream-chat-react-native';
44
import { BlurView } from '@react-native-community/blur';
5-
import FastImage from 'react-native-fast-image';
5+
import FastImage from '@d11/react-native-fast-image';
66
import {
77
useTheme,
88
} from 'stream-chat-react-native';

examples/SampleApp/yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,11 @@
11241124
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
11251125
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
11261126

1127+
"@d11/react-native-fast-image@^8.13.0":
1128+
version "8.13.0"
1129+
resolved "https://registry.yarnpkg.com/@d11/react-native-fast-image/-/react-native-fast-image-8.13.0.tgz#ae73d61fdc54b6c0b97cb97860773fb9f8db2b7f"
1130+
integrity sha512-zfsBtYNttiZVV/NwEnN/PzgW3PGlGYqn0/6DUOQ/tCv1lO0gO7+S0GiANmNDl35oVmh8o0DK81lF8xAhYz/aNA==
1131+
11271132
"@egjs/hammerjs@^2.0.17":
11281133
version "2.0.17"
11291134
resolved "https://registry.yarnpkg.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124"
@@ -7574,11 +7579,6 @@ react-native-drawer-layout@^4.1.10:
75747579
dependencies:
75757580
use-latest-callback "^0.2.3"
75767581

7577-
react-native-fast-image@^8.6.3:
7578-
version "8.6.3"
7579-
resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.6.3.tgz#6edc3f9190092a909d636d93eecbcc54a8822255"
7580-
integrity sha512-Sdw4ESidXCXOmQ9EcYguNY2swyoWmx53kym2zRsvi+VeFCHEdkO+WG1DK+6W81juot40bbfLNhkc63QnWtesNg==
7581-
75827582
react-native-gesture-handler@^2.31.0:
75837583
version "2.31.0"
75847584
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.31.0.tgz#7963b37b5566134bb6006024ec6a20d215a5b1a0"

package/expo-package/android/build.gradle

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ if (isNewArchitectureEnabled()) {
2929
def getExtOrIntegerDefault(name) {
3030
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["StreamChatExpo_" + name]).toInteger()
3131
}
32+
def canonicalProjectDir = projectDir.getCanonicalFile()
3233
def localSharedNativeRootDir = new File(projectDir, "src/main/java/com/streamchatreactnative/shared")
33-
def sharedNativeRootDir = new File(projectDir, "../../shared-native/android")
34+
def sharedNativeRootDir = new File(canonicalProjectDir, "../../shared-native/android")
3435
def hasNativeSources = { File dir ->
3536
dir.exists() && !fileTree(dir).matching { include "**/*.kt"; include "**/*.java" }.files.isEmpty()
3637
}
@@ -88,10 +89,10 @@ tasks.register("syncSharedShimmerSources") {
8889
outputs.upToDateWhen { false }
8990
doLast {
9091
def sourceRootDir = null
91-
if (hasNativeSources(localSharedNativeRootDir)) {
92-
sourceRootDir = localSharedNativeRootDir
93-
} else if (hasNativeSources(sharedNativeRootDir)) {
92+
if (hasNativeSources(sharedNativeRootDir)) {
9493
sourceRootDir = sharedNativeRootDir
94+
} else if (hasNativeSources(localSharedNativeRootDir)) {
95+
sourceRootDir = localSharedNativeRootDir
9596
}
9697

9798
if (sourceRootDir == null) {

package/expo-package/android/src/main/java/com/streamchatexpo/StreamChatExpoPackage.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414
import java.util.Map;
1515

1616
public class StreamChatExpoPackage extends TurboReactPackage {
17+
private static final String STREAM_MULTIPART_UPLOADER_MODULE = "StreamMultipartUploader";
1718
private static final String STREAM_VIDEO_THUMBNAIL_MODULE = "StreamVideoThumbnail";
1819

1920
@Nullable
2021
@Override
2122
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
22-
if (name.equals(STREAM_VIDEO_THUMBNAIL_MODULE) && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
23+
if (name.equals(STREAM_MULTIPART_UPLOADER_MODULE)) {
24+
return createNewArchModule("com.streamchatexpo.StreamMultipartUploaderModule", reactContext);
25+
}
26+
27+
if (name.equals(STREAM_VIDEO_THUMBNAIL_MODULE)) {
2328
return createNewArchModule("com.streamchatexpo.StreamVideoThumbnailModule", reactContext);
2429
}
2530

@@ -30,7 +35,17 @@ public NativeModule getModule(String name, ReactApplicationContext reactContext)
3035
public ReactModuleInfoProvider getReactModuleInfoProvider() {
3136
return () -> {
3237
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
33-
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
38+
moduleInfos.put(
39+
STREAM_MULTIPART_UPLOADER_MODULE,
40+
new ReactModuleInfo(
41+
STREAM_MULTIPART_UPLOADER_MODULE,
42+
STREAM_MULTIPART_UPLOADER_MODULE,
43+
false, // canOverrideExistingModule
44+
false, // needsEagerInit
45+
false, // hasConstants
46+
false, // isCxxModule
47+
true // isTurboModule
48+
));
3449
moduleInfos.put(
3550
STREAM_VIDEO_THUMBNAIL_MODULE,
3651
new ReactModuleInfo(
@@ -40,7 +55,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() {
4055
false, // needsEagerInit
4156
false, // hasConstants
4257
false, // isCxxModule
43-
isTurboModule // isTurboModule
58+
true // isTurboModule
4459
));
4560
return moduleInfos;
4661
};

0 commit comments

Comments
 (0)