Skip to content

Commit 232d257

Browse files
authored
Merge pull request #2163 from GetStream/develop
Next release
2 parents a1fb3b7 + 4cf6738 commit 232d257

File tree

11 files changed

+128
-88
lines changed

11 files changed

+128
-88
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
## 📖 React Native Chat Tutorial
3535

36-
The best place to start is the [React Native Chat Tutorial](https://github.com/GetStream/stream-chat-react-native/wiki/Tutorial-v3.0). It teaches you how to use this SDK and also shows how to make frequently required changes.
36+
The best place to start is the [React Native Chat Tutorial](https://getstream.io/chat/react-native-chat/tutorial/). It teaches you how to use this SDK and also shows how to make frequently required changes.
3737

3838
## Free for Makers
3939

package/expo-package/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"expo-file-system": "^11.0.2",
4848
"expo-image-manipulator": "^9.1.0",
4949
"expo-image-picker": "^14.1.1",
50-
"expo-media-library": "^12.0.2"
50+
"expo-media-library": "~15.2.3"
5151
},
5252
"scripts": {
5353
"prepack": " cp ../../README.md .",

package/expo-package/src/handlers/getLocalAssetUri.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as MediaLibrary from 'expo-media-library';
22

3-
export const getLocalAssetUri = async (assetId: string): Promise<string> => {
3+
export const getLocalAssetUri = async (assetId: string): Promise<string | undefined> => {
44
try {
55
const { localUri } = await MediaLibrary.getAssetInfoAsync(assetId);
66
return localUri;

package/expo-package/yarn.lock

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,13 +1935,10 @@ expo-keep-awake@~10.0.2:
19351935
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-10.0.2.tgz#706bda839782bb3e8ad4cbe43bde471a56368813"
19361936
integrity sha512-Ro1lgyKldbFs4mxhWM+goX9sg0S2SRR8FiJJeOvaRzf8xNhrZfWA00Zpr+/3ocCoWQ3eEL+X9UF4PXXHf0KoOg==
19371937

1938-
expo-media-library@^12.0.2:
1939-
version "12.1.2"
1940-
resolved "https://registry.yarnpkg.com/expo-media-library/-/expo-media-library-12.1.2.tgz#7a152f5ddf9e5e55d07aa28c8a5bd04113c0ebd2"
1941-
integrity sha512-e2Wh3TD4N2JjmKFFiQ453QgWWARNqc1/vILkEVnxjs34uJmUoT4a89wromr6Xl2fZJUvJDmgmVmL+A9iBWFgaA==
1942-
dependencies:
1943-
"@expo/config-plugins" "^3.0.0"
1944-
expo-modules-core "~0.2.0"
1938+
expo-media-library@~15.2.3:
1939+
version "15.2.3"
1940+
resolved "https://registry.yarnpkg.com/expo-media-library/-/expo-media-library-15.2.3.tgz#188f3c77f58b354f0ea6250f6756ac1e1a226291"
1941+
integrity sha512-Oz8b8Xsvfj7YcutUBtI84NUIqSnt7iCM5HZ5DyKoWKKiDK/+aUuj3RXNQELG8jUw6pQPgEwgbZ1+J8SdH/y9jw==
19451942

19461943
19471944
version "0.5.5"

package/native-package/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4381,10 +4381,10 @@ statuses@~1.5.0:
43814381
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
43824382
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
43834383

4384-
4385-
version "5.15.0"
4386-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.15.0.tgz#e4d52ca3b492b7a3f2550049fccd85e025bfed2e"
4387-
integrity sha512-MJf9qV1MZf0r4HTt0afZGxF5/HytbY+Sap/8QTDNE6OucWmxa44kOY7SfHmfdkxOLTUPHMeK7Glc+wCmYZVVLA==
4384+
4385+
version "5.15.1"
4386+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.15.1.tgz#a7f8f3a5f2998bdd3f779d3dc82e3a0a8e0fec22"
4387+
integrity sha512-UnybqEl9nqDrTrvb8CU4gxDamr73Iv0M56rwxhPrTtPiWiVGpG4gddkfJVGpVGYTyCBm9CKKeNmYBktuEbeW8Q==
43884388
dependencies:
43894389
"@babel/runtime" "^7.12.5"
43904390
"@gorhom/bottom-sheet" "4.4.5"

package/src/components/Message/MessageSimple/MessageStatus.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ const MessageStatusWithContext = <
5656
);
5757
}
5858

59-
if (isMessageWithStylesReadByAndDateSeparator(message) && !threadList) {
59+
if (threadList || message.status === MessageStatusTypes.FAILED) return null;
60+
61+
if (isMessageWithStylesReadByAndDateSeparator(message)) {
6062
return (
6163
<View style={[styles.statusContainer, statusContainer]}>
6264
{typeof message.readBy === 'number' ? (
@@ -76,11 +78,7 @@ const MessageStatusWithContext = <
7678
);
7779
}
7880

79-
if (
80-
message.status === MessageStatusTypes.RECEIVED &&
81-
message.type !== 'ephemeral' &&
82-
!threadList
83-
) {
81+
if (message.status === MessageStatusTypes.RECEIVED && message.type !== 'ephemeral') {
8482
return (
8583
<View style={[styles.statusContainer, statusContainer]} testID='delivered-container'>
8684
<Check pathFill={grey_dark} {...checkIcon} />

package/src/components/MessageInput/UploadProgressIndicator.tsx

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,45 +15,6 @@ import { ProgressIndicatorTypes } from '../../utils/utils';
1515

1616
const REFRESH_ICON_SIZE = 18;
1717

18-
const styles = StyleSheet.create({
19-
activityIndicatorContainer: {
20-
alignItems: 'center',
21-
bottom: 0,
22-
justifyContent: 'center',
23-
left: 0,
24-
position: 'absolute',
25-
right: 0,
26-
top: 0,
27-
},
28-
container: {
29-
alignItems: 'center',
30-
height: '100%',
31-
justifyContent: 'center',
32-
position: 'absolute',
33-
width: '100%',
34-
},
35-
overflowHidden: {
36-
overflow: 'hidden',
37-
},
38-
overlay: {
39-
alignItems: 'center',
40-
height: '100%',
41-
justifyContent: 'center',
42-
opacity: 0,
43-
position: 'absolute',
44-
width: '100%',
45-
},
46-
retryButtonContainer: {
47-
alignItems: 'center',
48-
bottom: 0,
49-
justifyContent: 'center',
50-
left: 0,
51-
position: 'absolute',
52-
right: 0,
53-
top: 0,
54-
},
55-
});
56-
5718
export type UploadProgressIndicatorProps = {
5819
/** Action triggered when clicked indicator */
5920
action?: (event: GestureResponderEvent) => void;
@@ -130,5 +91,44 @@ const RetryIndicator = ({ action }: Pick<UploadProgressIndicatorProps, 'action'>
13091
);
13192
};
13293

94+
const styles = StyleSheet.create({
95+
activityIndicatorContainer: {
96+
alignItems: 'center',
97+
bottom: 0,
98+
justifyContent: 'center',
99+
left: 0,
100+
position: 'absolute',
101+
right: 0,
102+
top: 0,
103+
},
104+
container: {
105+
alignItems: 'center',
106+
height: '100%',
107+
justifyContent: 'center',
108+
position: 'absolute',
109+
width: '100%',
110+
},
111+
overflowHidden: {
112+
overflow: 'hidden',
113+
},
114+
overlay: {
115+
alignItems: 'center',
116+
height: '100%',
117+
justifyContent: 'center',
118+
opacity: 0,
119+
position: 'absolute',
120+
width: '100%',
121+
},
122+
retryButtonContainer: {
123+
alignItems: 'center',
124+
bottom: 0,
125+
justifyContent: 'center',
126+
left: 0,
127+
position: 'absolute',
128+
right: 0,
129+
top: 0,
130+
},
131+
});
132+
133133
UploadProgressIndicator.displayName =
134134
'UploadProgressIndicator{messageInput{uploadProgressIndicator}}';

package/src/components/MessageList/MessageList.tsx

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ import {
5555

5656
import type { DefaultStreamChatGenerics } from '../../types/types';
5757

58+
const WAIT_FOR_SCROLL_TO_OFFSET_TIMEOUT = 150;
59+
const MAX_RETRIES_AFTER_SCROLL_FAILURE = 10;
5860
const styles = StyleSheet.create({
5961
container: {
6062
alignItems: 'center',
@@ -550,6 +552,7 @@ const MessageListWithContext = <
550552
}
551553
return false;
552554
}
555+
553556
const isCurrentMessageUnread = isMessageUnread(index);
554557
const showUnreadUnderlay = isCurrentMessageUnread && scrollToBottomButtonVisible;
555558
const insertInlineUnreadIndicator = showUnreadUnderlay && !isMessageUnread(index + 1); // show only if previous message is read
@@ -783,19 +786,22 @@ const MessageListWithContext = <
783786
}
784787
};
785788

789+
const scrollToIndexFailedRetryCountRef = useRef<number>(0);
790+
const failScrollTimeoutId = useRef<NodeJS.Timeout>();
786791
const onScrollToIndexFailedRef = useRef<
787792
FlatListProps<MessageType<StreamChatGenerics>>['onScrollToIndexFailed']
788793
>((info) => {
789794
// We got a failure as we tried to scroll to an item that was outside the render length
790-
if (flatListRef.current) {
791-
// we dont know the actual size of all items but we can see the average, so scroll to the closest offset
792-
flatListRef.current.scrollToOffset({
793-
animated: false,
794-
offset: info.averageItemLength * info.index,
795-
});
796-
// since we used only an average offset.. we wont go to the center of the item yet
797-
// with a little delay to wait for scroll to offset to complete, we can then scroll to the index
798-
setTimeout(() => {
795+
if (!flatListRef.current) return;
796+
// we don't know the actual size of all items but we can see the average, so scroll to the closest offset
797+
flatListRef.current.scrollToOffset({
798+
animated: false,
799+
offset: info.averageItemLength * info.index,
800+
});
801+
// since we used only an average offset... we won't go to the center of the item yet
802+
// with a little delay to wait for scroll to offset to complete, we can then scroll to the index
803+
failScrollTimeoutId.current = setTimeout(() => {
804+
try {
799805
flatListRef.current?.scrollToIndex({
800806
animated: false,
801807
index: info.index,
@@ -804,8 +810,30 @@ const MessageListWithContext = <
804810
if (messageIdLastScrolledToRef.current) {
805811
setTargetedMessage(messageIdLastScrolledToRef.current);
806812
}
807-
}, 150);
808-
}
813+
scrollToIndexFailedRetryCountRef.current = 0;
814+
} catch (e) {
815+
if (
816+
!onScrollToIndexFailedRef.current ||
817+
scrollToIndexFailedRetryCountRef.current > MAX_RETRIES_AFTER_SCROLL_FAILURE
818+
) {
819+
console.log(
820+
`Scrolling to index failed after ${MAX_RETRIES_AFTER_SCROLL_FAILURE} retries`,
821+
e,
822+
);
823+
scrollToIndexFailedRetryCountRef.current = 0;
824+
return;
825+
}
826+
// At some cases the index we're trying to scroll to, doesn't exist yet in the messageList
827+
// Scrolling to an index not in range of the Flatlist's data will result in a crash that
828+
// won't call onScrollToIndexFailed.
829+
// By catching this error we retry scrolling by calling onScrollToIndexFailedRef
830+
scrollToIndexFailedRetryCountRef.current += 1;
831+
onScrollToIndexFailedRef.current(info);
832+
}
833+
}, WAIT_FOR_SCROLL_TO_OFFSET_TIMEOUT);
834+
835+
// Only when index is greater than 0 and in range of items in FlatList
836+
// this onScrollToIndexFailed will be called again
809837
});
810838

811839
const goToMessage = useCallback(
@@ -814,6 +842,8 @@ const MessageListWithContext = <
814842
(message) => message?.id === messageId,
815843
);
816844
if (indexOfParentInMessageList !== -1 && flatListRef.current) {
845+
clearTimeout(failScrollTimeoutId.current);
846+
scrollToIndexFailedRetryCountRef.current = 0;
817847
flatListRef.current.scrollToIndex({
818848
animated: true,
819849
index: indexOfParentInMessageList,
@@ -855,6 +885,9 @@ const MessageListWithContext = <
855885
(message) => message?.id === messageIdToScroll,
856886
);
857887
if (indexOfParentInMessageList !== -1 && flatListRef.current) {
888+
// By a fresh scroll we should clear the retries for the previous failed scroll
889+
clearTimeout(failScrollTimeoutId.current);
890+
scrollToIndexFailedRetryCountRef.current = 0;
858891
flatListRef.current.scrollToIndex({
859892
animated: false,
860893
index: indexOfParentInMessageList,
@@ -867,6 +900,7 @@ const MessageListWithContext = <
867900
}
868901
}, 150);
869902
return () => {
903+
clearTimeout(failScrollTimeoutId.current);
870904
clearTimeout(scrollToDebounceTimeoutRef.current);
871905
clearTimeout(initialScrollSettingTimeoutRef.current);
872906
};

package/src/contexts/messageInputContext/MessageInputContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ export const MessageInputProvider = <
969969
if (value.doDocUploadRequest) {
970970
response = await value.doDocUploadRequest(file, channel);
971971
} else if (channel && file.uri) {
972-
// For the case of expo messaging app where you need to fetch the file uri from file id. Here it is only done for iOS since for android the file.uri is fine.
972+
// For the case of Expo CLI where you need to fetch the file uri from file id. Here it is only done for iOS since for android the file.uri is fine.
973973
const localAssetURI = Platform.OS === 'ios' && file.id && (await getLocalAssetUri(file.id));
974974
response = await channel.sendFile(localAssetURI || file.uri, file.name, file.type);
975975
}
@@ -990,7 +990,7 @@ export const MessageInputProvider = <
990990
let response = {} as SendFileAPIResponse;
991991

992992
try {
993-
// For the case of expo messaging app where you need to fetch the file uri from file id. Here it is only done for iOS since for android the file.uri is fine.
993+
// For the case of Expo CLI where you need to fetch the file uri from file id. Here it is only done for iOS since for android the file.uri is fine.
994994
const localAssetURI = Platform.OS === 'ios' && file.id && (await getLocalAssetUri(file.id));
995995
const uri = localAssetURI || file.uri || '';
996996
/**

package/src/native.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export let compressImage: CompressImage = fail;
2727
type DeleteFile = ({ uri }: { uri: string }) => Promise<boolean> | never;
2828
export let deleteFile: DeleteFile = fail;
2929

30-
type GetLocalAssetUri = (uriOrAssetId: string) => Promise<string> | never;
30+
type GetLocalAssetUri = (uriOrAssetId: string) => Promise<string | undefined> | never;
3131
export let getLocalAssetUri: GetLocalAssetUri = fail;
3232

3333
type OniOS14LibrarySelectionChange = (callback: () => void) => { unsubscribe: () => void };

0 commit comments

Comments
 (0)