Skip to content

Commit 052a0cd

Browse files
authored
Merge pull request #2780 from GetStream/develop
Next Release
2 parents 2603ff1 + 834d124 commit 052a0cd

20 files changed

+487
-164
lines changed

package/expo-package/yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -2929,10 +2929,10 @@ stream-buffers@2.2.x:
29292929
resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"
29302930
integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==
29312931

2932-
stream-chat-react-native-core@5.41.3:
2933-
version "5.41.3"
2934-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.3.tgz#83db713f15725fa49b8afb84d7ef01d668b98af5"
2935-
integrity sha512-Xr0iQCoRP5c2dKwlxq+EWxKLzBXHXAGagn2aShxxU7PCW5TcdUrewWIhDxOo1iZjGfzdBSZyCFX6ilhYq332RA==
2932+
stream-chat-react-native-core@5.41.4:
2933+
version "5.41.4"
2934+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.4.tgz#55104e1eb10f464b27d82b9566a18005723ea26d"
2935+
integrity sha512-Fe2AnbfZ98nRfP5BwMOwR2iae/hT8N5oEiYOb2FwbgtJqot4UFABZDCxMVcoYcFouOK1gc5BkTjdnXYYm/L8EQ==
29362936
dependencies:
29372937
"@gorhom/bottom-sheet" "^4.6.4"
29382938
dayjs "1.10.5"

package/native-package/yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -4244,10 +4244,10 @@ statuses@~1.5.0:
42444244
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
42454245
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
42464246

4247-
stream-chat-react-native-core@5.41.3:
4248-
version "5.41.3"
4249-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.3.tgz#83db713f15725fa49b8afb84d7ef01d668b98af5"
4250-
integrity sha512-Xr0iQCoRP5c2dKwlxq+EWxKLzBXHXAGagn2aShxxU7PCW5TcdUrewWIhDxOo1iZjGfzdBSZyCFX6ilhYq332RA==
4247+
stream-chat-react-native-core@5.41.4:
4248+
version "5.41.4"
4249+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.4.tgz#55104e1eb10f464b27d82b9566a18005723ea26d"
4250+
integrity sha512-Fe2AnbfZ98nRfP5BwMOwR2iae/hT8N5oEiYOb2FwbgtJqot4UFABZDCxMVcoYcFouOK1gc5BkTjdnXYYm/L8EQ==
42514251
dependencies:
42524252
"@gorhom/bottom-sheet" "^4.6.4"
42534253
dayjs "1.10.5"

package/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"path": "0.12.7",
7979
"react-native-markdown-package": "1.8.2",
8080
"react-native-url-polyfill": "^1.3.0",
81-
"stream-chat": "8.42.0"
81+
"stream-chat": "8.44.0"
8282
},
8383
"peerDependencies": {
8484
"react-native-quick-sqlite": ">=5.1.0",

package/src/components/Channel/Channel.tsx

+17-10
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,7 @@ const ChannelWithContext = <
12071207
await channel.query({}, 'latest');
12081208
}
12091209
await channel.state.loadMessageIntoState('latest');
1210+
setMessages([...channel.state.messages]);
12101211
});
12111212

12121213
const loadChannel = () =>
@@ -1403,13 +1404,17 @@ const ChannelWithContext = <
14031404
}, [enableOfflineSupport, shouldSyncChannel]);
14041405

14051406
const reloadChannel = () =>
1406-
channelQueryCallRef.current(async () => {
1407-
setLoading(true);
1408-
await loadLatestMessagesRef.current(true);
1409-
setLoading(false);
1410-
channel?.state.setIsUpToDate(true);
1411-
setHasNoMoreRecentMessagesToLoad(true);
1412-
});
1407+
channelQueryCallRef.current(
1408+
async () => {
1409+
setLoading(true);
1410+
await loadLatestMessagesRef.current(true);
1411+
setLoading(false);
1412+
},
1413+
() => {
1414+
channel?.state.setIsUpToDate(true);
1415+
setHasNoMoreRecentMessagesToLoad(true);
1416+
},
1417+
);
14131418

14141419
/**
14151420
* @deprecated
@@ -1888,10 +1893,12 @@ const ChannelWithContext = <
18881893
const latestLengthBeforeMerge = latestMessageSet?.messages.length || 0;
18891894
const didMerge = mergeOverlappingMessageSetsRef.current(true);
18901895
if (didMerge) {
1891-
if (latestMessageSet && latestLengthBeforeMerge >= limit) {
1896+
if (latestMessageSet && latestLengthBeforeMerge > 0) {
1897+
const shouldSetStateUpToDate =
1898+
latestMessageSet.messages.length < limit && latestMessageSet.isCurrent;
18921899
setLoadingMoreRecent(true);
1893-
channel.state.setIsUpToDate(true);
1894-
setHasNoMoreRecentMessagesToLoad(true);
1900+
channel.state.setIsUpToDate(shouldSetStateUpToDate);
1901+
setHasNoMoreRecentMessagesToLoad(shouldSetStateUpToDate);
18951902
loadMoreRecentFinished(channel.state.messages);
18961903
restartSetsMergeFuncRef.current();
18971904
return;
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React from 'react';
22

3-
import type { Channel, ChannelState, Event, MessageResponse } from 'stream-chat';
3+
import type { Channel } from 'stream-chat';
44

5+
import { useChannelPreviewData } from './hooks/useChannelPreviewData';
56
import { useLatestMessagePreview } from './hooks/useLatestMessagePreview';
67

78
import {
@@ -12,120 +13,40 @@ import { ChatContextValue, useChatContext } from '../../contexts/chatContext/Cha
1213

1314
import type { DefaultStreamChatGenerics } from '../../types/types';
1415

15-
export type ChannelPreviewPropsWithContext<
16+
export type ChannelPreviewProps<
1617
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
17-
> = Pick<ChatContextValue<StreamChatGenerics>, 'client'> &
18-
Pick<ChannelsContextValue<StreamChatGenerics>, 'Preview' | 'forceUpdate'> & {
18+
> = Partial<Pick<ChatContextValue<StreamChatGenerics>, 'client'>> &
19+
Partial<Pick<ChannelsContextValue<StreamChatGenerics>, 'Preview' | 'forceUpdate'>> & {
1920
/**
2021
* Instance of Channel from stream-chat package.
2122
*/
2223
channel: Channel<StreamChatGenerics>;
2324
};
2425

25-
/**
26-
* This component manages state for the ChannelPreviewMessenger UI component and receives
27-
* all props from the ChannelListMessenger component.
28-
*/
29-
const ChannelPreviewWithContext = <
26+
export const ChannelPreview = <
3027
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
3128
>(
32-
props: ChannelPreviewPropsWithContext<StreamChatGenerics>,
29+
props: ChannelPreviewProps<StreamChatGenerics>,
3330
) => {
34-
const { channel, client, forceUpdate: channelListForceUpdate, Preview } = props;
31+
const { channel, client: propClient, forceUpdate: propForceUpdate, Preview: propPreview } = props;
3532

36-
const [lastMessage, setLastMessage] = useState<
37-
| ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>
38-
| MessageResponse<StreamChatGenerics>
39-
| undefined
40-
>(channel.state.messages[channel.state.messages.length - 1]);
33+
const { client: contextClient } = useChatContext<StreamChatGenerics>();
34+
const { forceUpdate: contextForceUpdate, Preview: contextPreview } =
35+
useChannelsContext<StreamChatGenerics>();
4136

42-
const [forceUpdate, setForceUpdate] = useState(0);
43-
const [unread, setUnread] = useState(channel.countUnread());
37+
const client = propClient || contextClient;
38+
const forceUpdate = propForceUpdate || contextForceUpdate;
39+
const Preview = propPreview || contextPreview;
4440

41+
const { lastMessage, muted, unread } = useChannelPreviewData(channel, client, forceUpdate);
4542
const latestMessagePreview = useLatestMessagePreview(channel, forceUpdate, lastMessage);
4643

47-
const channelLastMessage = channel.lastMessage();
48-
const channelLastMessageString = `${channelLastMessage?.id}${channelLastMessage?.updated_at}`;
49-
50-
useEffect(() => {
51-
const { unsubscribe } = client.on('notification.mark_read', () => {
52-
setUnread(channel.countUnread());
53-
});
54-
return unsubscribe;
55-
// eslint-disable-next-line react-hooks/exhaustive-deps
56-
}, []);
57-
58-
useEffect(() => {
59-
if (
60-
channelLastMessage &&
61-
(channelLastMessage.id !== lastMessage?.id ||
62-
channelLastMessage.updated_at !== lastMessage?.updated_at)
63-
) {
64-
setLastMessage(channelLastMessage);
65-
}
66-
67-
const newUnreadCount = channel.countUnread();
68-
setUnread(newUnreadCount);
69-
// eslint-disable-next-line react-hooks/exhaustive-deps
70-
}, [channelLastMessageString, channelListForceUpdate]);
71-
72-
useEffect(() => {
73-
const handleNewMessageEvent = (event: Event<StreamChatGenerics>) => {
74-
const message = event.message;
75-
if (message && (!message.parent_id || message.show_in_channel)) {
76-
setLastMessage(event.message);
77-
setUnread(channel.countUnread());
78-
}
79-
};
80-
81-
const handleUpdatedOrDeletedMessage = (event: Event<StreamChatGenerics>) => {
82-
setLastMessage((prevLastMessage) => {
83-
if (prevLastMessage?.id === event.message?.id) {
84-
return event.message;
85-
}
86-
return prevLastMessage;
87-
});
88-
};
89-
90-
const listeners = [
91-
channel.on('message.new', handleNewMessageEvent),
92-
channel.on('message.updated', handleUpdatedOrDeletedMessage),
93-
channel.on('message.deleted', handleUpdatedOrDeletedMessage),
94-
];
95-
96-
return () => listeners.forEach((l) => l.unsubscribe());
97-
// eslint-disable-next-line react-hooks/exhaustive-deps
98-
}, []);
99-
100-
useEffect(() => {
101-
const handleReadEvent = (event: Event<StreamChatGenerics>) => {
102-
if (event.user?.id === client.userID) {
103-
setUnread(0);
104-
} else if (event.user?.id) {
105-
setForceUpdate((prev) => prev + 1);
106-
}
107-
};
108-
109-
const listener = channel.on('message.read', handleReadEvent);
110-
return () => listener.unsubscribe();
111-
// eslint-disable-next-line react-hooks/exhaustive-deps
112-
}, []);
113-
114-
return <Preview channel={channel} latestMessagePreview={latestMessagePreview} unread={unread} />;
115-
};
116-
117-
export type ChannelPreviewProps<
118-
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
119-
> = Partial<Omit<ChannelPreviewPropsWithContext<StreamChatGenerics>, 'channel'>> &
120-
Pick<ChannelPreviewPropsWithContext<StreamChatGenerics>, 'channel'>;
121-
122-
export const ChannelPreview = <
123-
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
124-
>(
125-
props: ChannelPreviewProps<StreamChatGenerics>,
126-
) => {
127-
const { client } = useChatContext<StreamChatGenerics>();
128-
const { forceUpdate, Preview } = useChannelsContext<StreamChatGenerics>();
129-
130-
return <ChannelPreviewWithContext {...{ client, forceUpdate, Preview }} {...props} />;
44+
return (
45+
<Preview
46+
channel={channel}
47+
latestMessagePreview={latestMessagePreview}
48+
muted={muted}
49+
unread={unread}
50+
/>
51+
);
13152
};

package/src/components/ChannelPreview/ChannelPreviewMessenger.tsx

+5-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React from 'react';
22
import { StyleSheet, View } from 'react-native';
33
import { TouchableOpacity } from 'react-native-gesture-handler';
44

@@ -17,7 +17,6 @@ import {
1717
ChannelsContextValue,
1818
useChannelsContext,
1919
} from '../../contexts/channelsContext/ChannelsContext';
20-
import { useChatContext } from '../../contexts/chatContext/ChatContext';
2120
import { useTheme } from '../../contexts/themeContext/ThemeContext';
2221
import { useViewport } from '../../hooks/useViewport';
2322
import type { DefaultStreamChatGenerics } from '../../types/types';
@@ -95,6 +94,8 @@ export type ChannelPreviewMessengerPropsWithContext<
9594
* default formatted date. This default logic is part of ChannelPreview component.
9695
*/
9796
formatLatestMessageDate?: (date: Date) => string;
97+
/** If the channel is muted. */
98+
muted?: boolean;
9899
/** Number of unread messages on the channel */
99100
unread?: number;
100101
};
@@ -109,6 +110,7 @@ const ChannelPreviewMessengerWithContext = <
109110
formatLatestMessageDate,
110111
latestMessagePreview,
111112
maxUnreadCount,
113+
muted,
112114
onSelect,
113115
PreviewAvatar = ChannelAvatar,
114116
PreviewMessage = ChannelPreviewMessage,
@@ -129,23 +131,11 @@ const ChannelPreviewMessengerWithContext = <
129131
},
130132
} = useTheme();
131133

132-
const { client } = useChatContext<StreamChatGenerics>();
133-
134134
const displayName = useChannelPreviewDisplayName(
135135
channel,
136136
Math.floor(maxWidth / ((title.fontSize || styles.title.fontSize) / 2)),
137137
);
138138

139-
const [isChannelMuted, setIsChannelMuted] = useState(() => channel.muteStatus().muted);
140-
141-
useEffect(() => {
142-
const handleEvent = () => setIsChannelMuted(channel.muteStatus().muted);
143-
144-
client.on('notification.channel_mutes_updated', handleEvent);
145-
return () => client.off('notification.channel_mutes_updated', handleEvent);
146-
// eslint-disable-next-line react-hooks/exhaustive-deps
147-
}, [client]);
148-
149139
return (
150140
<TouchableOpacity
151141
onPress={() => {
@@ -168,7 +158,7 @@ const ChannelPreviewMessengerWithContext = <
168158
<View style={[styles.row, row]}>
169159
<PreviewTitle channel={channel} displayName={displayName} />
170160
<View style={[styles.statusContainer, row]}>
171-
{isChannelMuted && <PreviewMutedStatus />}
161+
{muted && <PreviewMutedStatus />}
172162
<PreviewUnreadCount channel={channel} maxUnreadCount={maxUnreadCount} unread={unread} />
173163
</View>
174164
</View>

package/src/components/ChannelPreview/ChannelPreviewMutedStatus.tsx

+2-7
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,11 @@ export const ChannelPreviewMutedStatus = () => {
2020
channelPreview: {
2121
mutedStatus: { height, iconStyle, width },
2222
},
23-
colors: { grey_dark },
23+
colors: { grey },
2424
},
2525
} = useTheme();
2626

2727
return (
28-
<Mute
29-
height={height}
30-
pathFill={grey_dark}
31-
style={[styles.iconStyle, iconStyle]}
32-
width={width}
33-
/>
28+
<Mute height={height} pathFill={grey} style={[styles.iconStyle, iconStyle]} width={width} />
3429
);
3530
};

0 commit comments

Comments
 (0)