stream-chat-react-native-core 3.9.0-next.8 → 3.9.2-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/Attachment/Gallery.js +3 -5
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/AutoCompleteInput/AutoCompleteInput.js +5 -5
- package/lib/commonjs/components/AutoCompleteInput/AutoCompleteInput.js.map +1 -1
- package/lib/commonjs/components/ChannelList/ChannelListLoadingIndicator.js +6 -4
- package/lib/commonjs/components/ChannelList/ChannelListLoadingIndicator.js.map +1 -1
- package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js +32 -11
- package/lib/commonjs/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewMessage.js +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewMessage.js.map +1 -1
- package/lib/commonjs/components/Chat/hooks/useIsOnline.js +23 -24
- package/lib/commonjs/components/Chat/hooks/useIsOnline.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +3 -0
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/hooks/useIsMountedRef.js +19 -0
- package/lib/commonjs/hooks/useIsMountedRef.js.map +1 -0
- package/lib/commonjs/hooks/useStreami18n.js +4 -1
- package/lib/commonjs/hooks/useStreami18n.js.map +1 -1
- package/lib/commonjs/i18n/fr.json +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/Gallery.js +3 -5
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/AutoCompleteInput/AutoCompleteInput.js +5 -5
- package/lib/module/components/AutoCompleteInput/AutoCompleteInput.js.map +1 -1
- package/lib/module/components/ChannelList/ChannelListLoadingIndicator.js +6 -4
- package/lib/module/components/ChannelList/ChannelListLoadingIndicator.js.map +1 -1
- package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js +32 -11
- package/lib/module/components/ChannelList/hooks/usePaginatedChannels.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewMessage.js +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewMessage.js.map +1 -1
- package/lib/module/components/Chat/hooks/useIsOnline.js +23 -24
- package/lib/module/components/Chat/hooks/useIsOnline.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/utils/renderText.js +1 -1
- package/lib/module/components/Message/MessageSimple/utils/renderText.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +3 -0
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/hooks/useIsMountedRef.js +19 -0
- package/lib/module/hooks/useIsMountedRef.js.map +1 -0
- package/lib/module/hooks/useStreami18n.js +4 -1
- package/lib/module/hooks/useStreami18n.js.map +1 -1
- package/lib/module/i18n/fr.json +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +3 -0
- package/lib/typescript/hooks/useIsMountedRef.d.ts +20 -0
- package/lib/typescript/hooks/useStreami18n.d.ts +1 -1
- package/lib/typescript/i18n/fr.json +1 -1
- package/package.json +1 -1
- package/src/components/Attachment/Gallery.tsx +3 -3
- package/src/components/AutoCompleteInput/AutoCompleteInput.tsx +3 -8
- package/src/components/ChannelList/ChannelListLoadingIndicator.tsx +2 -1
- package/src/components/ChannelList/hooks/usePaginatedChannels.ts +7 -1
- package/src/components/ChannelPreview/ChannelPreviewMessage.tsx +1 -1
- package/src/components/Chat/hooks/useIsOnline.ts +16 -17
- package/src/components/Message/MessageSimple/utils/renderText.tsx +1 -1
- package/src/contexts/themeContext/utils/theme.ts +6 -0
- package/src/hooks/useIsMountedRef.ts +36 -0
- package/src/hooks/useStreami18n.ts +5 -3
- package/src/i18n/fr.json +1 -1
- package/src/version.json +1 -1
|
@@ -288,12 +288,7 @@ const AutoCompleteInputWithContext = <
|
|
|
288
288
|
|
|
289
289
|
const textToModify = text.slice(0, selectionEnd.current);
|
|
290
290
|
|
|
291
|
-
const startOfTokenPosition = textToModify.
|
|
292
|
-
/**
|
|
293
|
-
* It's important to escape the trigger char for chars like [, (,...
|
|
294
|
-
*/
|
|
295
|
-
new RegExp(`\\${trigger}${`[^\\${trigger}${'\\s'}]`}*$`),
|
|
296
|
-
);
|
|
291
|
+
const startOfTokenPosition = textToModify.lastIndexOf(trigger, selectionEnd.current);
|
|
297
292
|
|
|
298
293
|
const newCaretPosition = computeCaretPosition(newTokenString, startOfTokenPosition);
|
|
299
294
|
|
|
@@ -335,7 +330,7 @@ const AutoCompleteInputWithContext = <
|
|
|
335
330
|
};
|
|
336
331
|
|
|
337
332
|
const handleMentions = ({ tokenMatch }: { tokenMatch: RegExpMatchArray | null }) => {
|
|
338
|
-
const lastToken = tokenMatch?.[tokenMatch.length - 1]
|
|
333
|
+
const lastToken = tokenMatch?.[tokenMatch.length - 1];
|
|
339
334
|
const handleMentionsTrigger =
|
|
340
335
|
(lastToken && Object.keys(triggerSettings).find((trigger) => trigger === lastToken[0])) ||
|
|
341
336
|
null;
|
|
@@ -401,7 +396,7 @@ const AutoCompleteInputWithContext = <
|
|
|
401
396
|
} else if (giphyEnabled && !(await handleCommand(text))) {
|
|
402
397
|
const mentionTokenMatch = text
|
|
403
398
|
.slice(0, selectionEnd.current)
|
|
404
|
-
.match(/(?!^|\W)?@[^\s]*\s?[^\s]*$/g);
|
|
399
|
+
.match(/(?!^|\W)?@[^\s@]*\s?[^\s@]*$/g);
|
|
405
400
|
if (mentionTokenMatch) {
|
|
406
401
|
handleMentions({ tokenMatch: mentionTokenMatch });
|
|
407
402
|
} else {
|
|
@@ -13,6 +13,7 @@ const styles = StyleSheet.create({
|
|
|
13
13
|
export const ChannelListLoadingIndicator: React.FC = () => {
|
|
14
14
|
const {
|
|
15
15
|
theme: {
|
|
16
|
+
channelListLoadingIndicator: { container },
|
|
16
17
|
colors: { white_snow },
|
|
17
18
|
},
|
|
18
19
|
} = useTheme();
|
|
@@ -20,7 +21,7 @@ export const ChannelListLoadingIndicator: React.FC = () => {
|
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
23
|
<View
|
|
23
|
-
style={[styles.container, { backgroundColor: white_snow }]}
|
|
24
|
+
style={[styles.container, { backgroundColor: white_snow }, container]}
|
|
24
25
|
testID='channel-list-loading-indicator'
|
|
25
26
|
>
|
|
26
27
|
{Array.from(Array(numberOfSkeletons)).map((_, index) => (
|
|
@@ -3,6 +3,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
|
|
|
3
3
|
import { MAX_QUERY_CHANNELS_LIMIT } from '../utils';
|
|
4
4
|
|
|
5
5
|
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
|
|
6
|
+
import { useIsMountedRef } from '../../../hooks/useIsMountedRef';
|
|
6
7
|
|
|
7
8
|
import type { Channel, ChannelFilters, ChannelOptions, ChannelSort } from 'stream-chat';
|
|
8
9
|
|
|
@@ -58,9 +59,10 @@ export const usePaginatedChannels = <
|
|
|
58
59
|
const [loadingChannels, setLoadingChannels] = useState(false);
|
|
59
60
|
const [loadingNextPage, setLoadingNextPage] = useState(false);
|
|
60
61
|
const [refreshing, setRefreshing] = useState(false);
|
|
62
|
+
const isMounted = useIsMountedRef();
|
|
61
63
|
|
|
62
64
|
const queryChannels = async (queryType = '', retryCount = 0): Promise<void> => {
|
|
63
|
-
if (!client || loadingChannels || loadingNextPage || refreshing) return;
|
|
65
|
+
if (!client || loadingChannels || loadingNextPage || refreshing || !isMounted.current) return;
|
|
64
66
|
|
|
65
67
|
if (queryType === 'reload') {
|
|
66
68
|
setLoadingChannels(true);
|
|
@@ -79,6 +81,8 @@ export const usePaginatedChannels = <
|
|
|
79
81
|
try {
|
|
80
82
|
const channelQueryResponse = await client.queryChannels(filters, sort, newOptions);
|
|
81
83
|
|
|
84
|
+
if (!isMounted.current) return;
|
|
85
|
+
|
|
82
86
|
channelQueryResponse.forEach((channel) => channel.state.setIsUpToDate(true));
|
|
83
87
|
|
|
84
88
|
const newChannels =
|
|
@@ -92,6 +96,8 @@ export const usePaginatedChannels = <
|
|
|
92
96
|
} catch (err) {
|
|
93
97
|
await wait(2000);
|
|
94
98
|
|
|
99
|
+
if (!isMounted.current) return;
|
|
100
|
+
|
|
95
101
|
if (retryCount === 3) {
|
|
96
102
|
setLoadingChannels(false);
|
|
97
103
|
setLoadingNextPage(false);
|
|
@@ -51,7 +51,7 @@ export const ChannelPreviewMessage: React.FC<ChannelPreviewMessageProps> = ({
|
|
|
51
51
|
preview.text ? (
|
|
52
52
|
<Text
|
|
53
53
|
key={`${preview.text}_${index}`}
|
|
54
|
-
style={[{ color: grey }, preview.bold ? styles.bold : {}]}
|
|
54
|
+
style={[{ color: grey }, preview.bold ? styles.bold : {}, message]}
|
|
55
55
|
>
|
|
56
56
|
{preview.text}
|
|
57
57
|
</Text>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { useAppStateListener } from '../../../hooks/useAppStateListener';
|
|
4
|
+
import { useIsMountedRef } from '../../../hooks/useIsMountedRef';
|
|
4
5
|
import { NetInfo } from '../../../native';
|
|
5
6
|
|
|
6
7
|
import type { NetInfoSubscription } from '@react-native-community/netinfo';
|
|
@@ -35,10 +36,9 @@ export const useIsOnline = <
|
|
|
35
36
|
client: StreamChat<At, Ch, Co, Ev, Me, Re, Us>,
|
|
36
37
|
closeConnectionOnBackground = true,
|
|
37
38
|
) => {
|
|
38
|
-
const [unsubscribeNetInfo, setUnsubscribeNetInfo] = useState<NetInfoSubscription>();
|
|
39
39
|
const [isOnline, setIsOnline] = useState(true);
|
|
40
40
|
const [connectionRecovering, setConnectionRecovering] = useState(false);
|
|
41
|
-
|
|
41
|
+
const isMounted = useIsMountedRef();
|
|
42
42
|
const clientExits = !!client;
|
|
43
43
|
|
|
44
44
|
const onBackground = useCallback(() => {
|
|
@@ -83,35 +83,34 @@ export const useIsOnline = <
|
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
let unsubscribeNetInfo: NetInfoSubscription;
|
|
87
|
+
const setNetInfoListener = () => {
|
|
87
88
|
NetInfo.fetch().then((netInfoState) => {
|
|
88
89
|
notifyChatClient(netInfoState);
|
|
89
90
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}),
|
|
94
|
-
);
|
|
91
|
+
unsubscribeNetInfo = NetInfo.addEventListener((netInfoState) => {
|
|
92
|
+
notifyChatClient(netInfoState);
|
|
93
|
+
});
|
|
95
94
|
};
|
|
96
95
|
|
|
97
96
|
const setInitialOnlineState = async () => {
|
|
98
97
|
const status = await NetInfo.fetch();
|
|
99
|
-
|
|
98
|
+
|
|
99
|
+
if (isMounted.current) setIsOnline(status);
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
setInitialOnlineState();
|
|
103
|
+
const chatListeners: Array<ReturnType<StreamChat['on']>> = [];
|
|
104
|
+
|
|
103
105
|
if (client) {
|
|
104
|
-
client.on('connection.changed', handleChangedEvent);
|
|
105
|
-
client.on('connection.recovered', handleRecoveredEvent);
|
|
106
|
-
|
|
106
|
+
chatListeners.push(client.on('connection.changed', handleChangedEvent));
|
|
107
|
+
chatListeners.push(client.on('connection.recovered', handleRecoveredEvent));
|
|
108
|
+
setNetInfoListener();
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
return () => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (unsubscribeNetInfo) {
|
|
113
|
-
unsubscribeNetInfo();
|
|
114
|
-
}
|
|
112
|
+
chatListeners.forEach((listener) => listener.unsubscribe?.());
|
|
113
|
+
unsubscribeNetInfo?.();
|
|
115
114
|
};
|
|
116
115
|
}, [clientExits]);
|
|
117
116
|
|
|
@@ -262,7 +262,7 @@ export const renderText = <
|
|
|
262
262
|
<Markdown
|
|
263
263
|
key={`${JSON.stringify(mentioned_users)}-${onlyEmojis}-${
|
|
264
264
|
messageOverlay ? JSON.stringify(markdownStyles) : undefined
|
|
265
|
-
}`}
|
|
265
|
+
}-${JSON.stringify(colors)}`}
|
|
266
266
|
onLink={onLink}
|
|
267
267
|
rules={{
|
|
268
268
|
...customRules,
|
|
@@ -110,6 +110,9 @@ export type Theme = {
|
|
|
110
110
|
container: ViewStyle;
|
|
111
111
|
errorText: TextStyle;
|
|
112
112
|
};
|
|
113
|
+
channelListLoadingIndicator: {
|
|
114
|
+
container: ViewStyle;
|
|
115
|
+
};
|
|
113
116
|
channelListMessenger: {
|
|
114
117
|
flatList: ViewStyle;
|
|
115
118
|
flatListContent: ViewStyle;
|
|
@@ -531,6 +534,9 @@ export const defaultTheme: Theme = {
|
|
|
531
534
|
container: {},
|
|
532
535
|
errorText: {},
|
|
533
536
|
},
|
|
537
|
+
channelListLoadingIndicator: {
|
|
538
|
+
container: {},
|
|
539
|
+
},
|
|
534
540
|
channelListMessenger: {
|
|
535
541
|
flatList: {},
|
|
536
542
|
flatListContent: {},
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns mount status of component. This hook can be used for purpose of avoiding any
|
|
5
|
+
* setState calls (within async operation) after component gets unmounted.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```
|
|
9
|
+
* const isMounted = useIsMountedRef();
|
|
10
|
+
* const [dummyValue, setDummyValue] = useState(false);
|
|
11
|
+
*
|
|
12
|
+
* useEffect(() => {
|
|
13
|
+
* someAsyncOperation().then(() => {
|
|
14
|
+
* if (isMounted.current) setDummyValue(true);
|
|
15
|
+
* })
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @returns isMounted {Object} Mount status ref for the component.
|
|
20
|
+
*/
|
|
21
|
+
export const useIsMountedRef = () => {
|
|
22
|
+
// Initial value has been set to true, since this hook exist only for sole purpose of
|
|
23
|
+
// avoiding any setState calls (within async operation) after component gets unmounted.
|
|
24
|
+
// Basically we don't need to know about state change from component being initialized -> mounted.
|
|
25
|
+
// We only need a state change from initialized or mounted state -> unmounted state.
|
|
26
|
+
const isMounted = useRef(true);
|
|
27
|
+
|
|
28
|
+
useEffect(
|
|
29
|
+
() => () => {
|
|
30
|
+
isMounted.current = false;
|
|
31
|
+
},
|
|
32
|
+
[],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return isMounted;
|
|
36
|
+
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { useIsMountedRef } from './useIsMountedRef';
|
|
4
4
|
import { Streami18n } from '../utils/Streami18n';
|
|
5
5
|
|
|
6
|
+
import type { TranslationContextValue } from '../contexts/translationContext/TranslationContext';
|
|
7
|
+
|
|
6
8
|
export const useStreami18n = ({
|
|
7
9
|
i18nInstance,
|
|
8
10
|
setTranslators,
|
|
@@ -11,7 +13,7 @@ export const useStreami18n = ({
|
|
|
11
13
|
i18nInstance?: Streami18n;
|
|
12
14
|
}) => {
|
|
13
15
|
const [loadingTranslators, setLoadingTranslators] = useState(true);
|
|
14
|
-
|
|
16
|
+
const isMounted = useIsMountedRef();
|
|
15
17
|
const i18nInstanceExists = !!i18nInstance;
|
|
16
18
|
useEffect(() => {
|
|
17
19
|
let streami18n: Streami18n;
|
|
@@ -26,7 +28,7 @@ export const useStreami18n = ({
|
|
|
26
28
|
setTranslators((prevTranslator) => ({ ...prevTranslator, t })),
|
|
27
29
|
);
|
|
28
30
|
streami18n.getTranslators().then((translator) => {
|
|
29
|
-
if (translator) setTranslators(translator);
|
|
31
|
+
if (translator && isMounted.current) setTranslators(translator);
|
|
30
32
|
});
|
|
31
33
|
|
|
32
34
|
setLoadingTranslators(false);
|
package/src/i18n/fr.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"Copy Message": "Copier le message",
|
|
10
10
|
"Delete": "Supprimer",
|
|
11
11
|
"Delete Message": "Supprimer un message",
|
|
12
|
-
"Dismiss": "
|
|
12
|
+
"Dismiss": "Fermer",
|
|
13
13
|
"Do you want to send a copy of this message to a moderator for further investigation?": "Voulez-vous envoyer une copie de ce message à un modérateur pour une enquête plus approfondie?",
|
|
14
14
|
"Edit Message": "Éditer un message",
|
|
15
15
|
"Editing Message": "Édite un message",
|
package/src/version.json
CHANGED