Skip to content

Commit c059844

Browse files
authored
fix: reanimated 4.3.0 attachment preview list (#3569)
## 🎯 Goal This PR fixes an issue that was unfortunately introduced with upgrading `react-native-reanimated` to `4.3.0` amongst other things. The issue stems from how `reanimated` actually synchronizes values with state and scrolling behaviour, which has clearly changed. Because of that, it was very common for our scrollable area (the calculated one) to become completely out of sync with the list because of the correction we were applying. For now, this has been fixed by ditching that approach entirely and relying purely on a resizable spacer that waits for animations to finish and all frames to settle before reducing its width. Essentially, it's deferred list resizing that forces waiting for animations to finish before that. A lot of code has been added, but now the animations are smooth on both versions of reanimated. ## 🛠 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 parent b70f8d5 commit c059844

4 files changed

Lines changed: 514 additions & 194 deletions

File tree

examples/ExpoMessaging/yarn.lock

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,10 +1578,10 @@
15781578
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.4.tgz#9d5b4b6f23309260a12856cb574c5e64e6c133f7"
15791579
integrity sha512-6m8+P+dE/RPl4OPzjTxcTbQ0rGeRyeTvAi9KwIffBVCiAMKrfXfLZaqD1F+m8t4B5/Q5aHsMozOgirkH1F5oMQ==
15801580

1581-
"@gorhom/bottom-sheet@5.1.8":
1582-
version "5.1.8"
1583-
resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.1.8.tgz#65547917f5b1dae5a1291dabd4ea8bfee09feba4"
1584-
integrity sha512-QuYIVjn3K9bW20n5bgOSjvxBYoWG4YQXiLGOheEAMgISuoT6sMcA270ViSkkb0fenPxcIOwzCnFNuxmr739T9A==
1581+
"@gorhom/bottom-sheet@5.2.9":
1582+
version "5.2.9"
1583+
resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.2.9.tgz#57d26ab8a4a881bb4be8fd45a4b9539929c9f198"
1584+
integrity sha512-YwieCsEnTQnN2QW4VBKfCGszzxaw2ID7FydusEgqo7qB817fZ45N88kptcuNwZFnnauCjdyzKdrVBWmLmpl9oQ==
15851585
dependencies:
15861586
"@gorhom/portal" "1.0.14"
15871587
invariant "^2.2.4"
@@ -2583,6 +2583,15 @@ axios@^1.12.2:
25832583
form-data "^4.0.4"
25842584
proxy-from-env "^1.1.0"
25852585

2586+
axios@^1.15.1:
2587+
version "1.15.2"
2588+
resolved "https://registry.yarnpkg.com/axios/-/axios-1.15.2.tgz#eb8fb6d30349abace6ade5b4cb4d9e8a0dc23e5b"
2589+
integrity sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==
2590+
dependencies:
2591+
follow-redirects "^1.15.11"
2592+
form-data "^4.0.5"
2593+
proxy-from-env "^2.1.0"
2594+
25862595
babel-jest@^29.7.0:
25872596
version "29.7.0"
25882597
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5"
@@ -3750,6 +3759,11 @@ flow-enums-runtime@^0.0.6:
37503759
resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787"
37513760
integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==
37523761

3762+
follow-redirects@^1.15.11:
3763+
version "1.16.0"
3764+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc"
3765+
integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==
3766+
37533767
follow-redirects@^1.15.6:
37543768
version "1.15.11"
37553769
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340"
@@ -3771,6 +3785,17 @@ form-data@^4.0.4:
37713785
hasown "^2.0.2"
37723786
mime-types "^2.1.12"
37733787

3788+
form-data@^4.0.5:
3789+
version "4.0.5"
3790+
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053"
3791+
integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==
3792+
dependencies:
3793+
asynckit "^0.4.0"
3794+
combined-stream "^1.0.8"
3795+
es-set-tostringtag "^2.1.0"
3796+
hasown "^2.0.2"
3797+
mime-types "^2.1.12"
3798+
37743799
fresh@0.5.2:
37753800
version "0.5.2"
37763801
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -5410,6 +5435,11 @@ proxy-from-env@^1.1.0:
54105435
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
54115436
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
54125437

5438+
proxy-from-env@^2.1.0:
5439+
version "2.1.0"
5440+
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba"
5441+
integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==
5442+
54135443
punycode@^2.1.1:
54145444
version "2.3.1"
54155445
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
@@ -6043,14 +6073,14 @@ stream-chat-react-native-core@8.1.0:
60436073
version "0.0.0"
60446074
uid ""
60456075

6046-
stream-chat@^9.40.0:
6047-
version "9.41.0"
6048-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.41.0.tgz#ad88d7919aaf1d3c35b4a431a8cd464cb640f146"
6049-
integrity sha512-Rgp3vULGKYxHZ/aCeundly6ngdBGttTPz+YknmWhbqvNlEhPB/RM61CpQPHgPyfkSm+osJT3tEV9fKd+I/S77g==
6076+
stream-chat@^9.42.1:
6077+
version "9.42.1"
6078+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.42.1.tgz#8b6aa4e3e73a39ed07bb2a4f2a6829ba9354567a"
6079+
integrity sha512-o+9wQO4Ruu1A48T0IrX9ZH8+9F5xPgGLPvflaswaPeLyIZXcy8bsQdcT/HSrPmT7gs0WGD3qcbXaAJU5lMQezQ==
60506080
dependencies:
60516081
"@types/jsonwebtoken" "^9.0.8"
60526082
"@types/ws" "^8.5.14"
6053-
axios "^1.12.2"
6083+
axios "^1.15.1"
60546084
base64-js "^1.5.1"
60556085
form-data "^4.0.4"
60566086
isomorphic-ws "^5.0.0"

examples/SampleApp/yarn.lock

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,14 +3565,14 @@ available-typed-arrays@^1.0.7:
35653565
dependencies:
35663566
possible-typed-array-names "^1.0.0"
35673567

3568-
axios@^1.12.2:
3569-
version "1.12.2"
3570-
resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7"
3571-
integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==
3568+
axios@^1.15.1:
3569+
version "1.15.2"
3570+
resolved "https://registry.yarnpkg.com/axios/-/axios-1.15.2.tgz#eb8fb6d30349abace6ade5b4cb4d9e8a0dc23e5b"
3571+
integrity sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==
35723572
dependencies:
3573-
follow-redirects "^1.15.6"
3574-
form-data "^4.0.4"
3575-
proxy-from-env "^1.1.0"
3573+
follow-redirects "^1.15.11"
3574+
form-data "^4.0.5"
3575+
proxy-from-env "^2.1.0"
35763576

35773577
axios@^1.6.0:
35783578
version "1.7.9"
@@ -5088,6 +5088,11 @@ flow-enums-runtime@^0.0.6:
50885088
resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787"
50895089
integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==
50905090

5091+
follow-redirects@^1.15.11:
5092+
version "1.16.0"
5093+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc"
5094+
integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==
5095+
50915096
follow-redirects@^1.15.6:
50925097
version "1.15.9"
50935098
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
@@ -5129,6 +5134,17 @@ form-data@^4.0.4:
51295134
hasown "^2.0.2"
51305135
mime-types "^2.1.12"
51315136

5137+
form-data@^4.0.5:
5138+
version "4.0.5"
5139+
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053"
5140+
integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==
5141+
dependencies:
5142+
asynckit "^0.4.0"
5143+
combined-stream "^1.0.8"
5144+
es-set-tostringtag "^2.1.0"
5145+
hasown "^2.0.2"
5146+
mime-types "^2.1.12"
5147+
51325148
fresh@0.5.2:
51335149
version "0.5.2"
51345150
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -7482,6 +7498,11 @@ proxy-from-env@^1.1.0:
74827498
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
74837499
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
74847500

7501+
proxy-from-env@^2.1.0:
7502+
version "2.1.0"
7503+
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba"
7504+
integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==
7505+
74857506
punycode@^2.1.0, punycode@^2.1.1:
74867507
version "2.3.1"
74877508
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
@@ -8270,14 +8291,14 @@ stream-chat-react-native-core@8.1.0:
82708291
version "0.0.0"
82718292
uid ""
82728293

8273-
stream-chat@^9.41.1:
8274-
version "9.41.1"
8275-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.41.1.tgz#a877c8aa800d78b497eec2fad636345d4422309c"
8276-
integrity sha512-W8zjfINYol2UtdRMz2t/NN2GyjDrvb4pJgKmhtuRYzCY1u0Cjezcsu5OCNgyAM0QsenlY6tRqnvAU8Qam5R49Q==
8294+
stream-chat@^9.42.1:
8295+
version "9.42.1"
8296+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.42.1.tgz#8b6aa4e3e73a39ed07bb2a4f2a6829ba9354567a"
8297+
integrity sha512-o+9wQO4Ruu1A48T0IrX9ZH8+9F5xPgGLPvflaswaPeLyIZXcy8bsQdcT/HSrPmT7gs0WGD3qcbXaAJU5lMQezQ==
82778298
dependencies:
82788299
"@types/jsonwebtoken" "^9.0.8"
82798300
"@types/ws" "^8.5.14"
8280-
axios "^1.12.2"
8301+
axios "^1.15.1"
82818302
base64-js "^1.5.1"
82828303
form-data "^4.0.4"
82838304
isomorphic-ws "^5.0.0"

package/src/components/MessageInput/__tests__/AttachmentUploadPreviewList.test.tsx

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { ComponentProps } from 'react';
22

3-
import { ActivityIndicator } from 'react-native';
3+
import { ActivityIndicator, ScrollView } from 'react-native';
44

55
import type { ReactTestInstance } from 'react-test-renderer';
66

@@ -178,6 +178,51 @@ describe('AttachmentUploadPreviewList', () => {
178178
});
179179

180180
describe('FileAttachmentUploadPreview', () => {
181+
it('anchors the preview list to the end when content shrinks near the end', () => {
182+
const scrollToSpy = jest
183+
.spyOn(ScrollView.prototype, 'scrollTo')
184+
.mockImplementation(() => undefined);
185+
try {
186+
const attachments = [
187+
generateFileAttachment({
188+
localMetadata: {
189+
id: 'file-attachment-1',
190+
uploadState: FileState.FINISHED,
191+
},
192+
}),
193+
generateFileAttachment({
194+
localMetadata: {
195+
id: 'file-attachment-2',
196+
uploadState: FileState.FINISHED,
197+
},
198+
}),
199+
];
200+
const props = {};
201+
202+
act(() => {
203+
channel.messageComposer.attachmentManager.upsertAttachments(attachments);
204+
});
205+
206+
renderComponent({ channel, client, props });
207+
208+
const list = screen.UNSAFE_getByType(ScrollView);
209+
210+
act(() => {
211+
fireEvent(list, 'layout', { nativeEvent: { layout: { width: 100 } } });
212+
list.props.onContentSizeChange(300, 0);
213+
list.props.onScroll({ nativeEvent: { contentOffset: { x: 190 } } });
214+
list.props.onContentSizeChange(250, 0);
215+
});
216+
217+
expect(scrollToSpy).toHaveBeenCalledWith({
218+
animated: false,
219+
x: 150,
220+
});
221+
} finally {
222+
scrollToSpy.mockRestore();
223+
}
224+
});
225+
181226
it('should render FileAttachmentUploadPreview with all uploading files', async () => {
182227
const attachments = [
183228
generateFileAttachment({

0 commit comments

Comments
 (0)