Skip to content

Commit f8ae2af

Browse files
committed
feat: listen to notification.mark_read and notification.mark_unread event and introduce improvements
1 parent 2603ff1 commit f8ae2af

14 files changed

+588
-113
lines changed

package/src/components/ChannelPreview/ChannelPreview.tsx

Lines changed: 15 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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

55
import { useLatestMessagePreview } from './hooks/useLatestMessagePreview';
66

@@ -11,6 +11,8 @@ import {
1111
import { ChatContextValue, useChatContext } from '../../contexts/chatContext/ChatContext';
1212

1313
import type { DefaultStreamChatGenerics } from '../../types/types';
14+
import { useChannelPreviewData } from './hooks/useChannelPreviewData';
15+
import { useIsChannelMuted } from './hooks/useIsChannelMuted';
1416

1517
export type ChannelPreviewPropsWithContext<
1618
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
@@ -31,87 +33,19 @@ const ChannelPreviewWithContext = <
3133
>(
3234
props: ChannelPreviewPropsWithContext<StreamChatGenerics>,
3335
) => {
34-
const { channel, client, forceUpdate: channelListForceUpdate, Preview } = props;
35-
36-
const [lastMessage, setLastMessage] = useState<
37-
| ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>
38-
| MessageResponse<StreamChatGenerics>
39-
| undefined
40-
>(channel.state.messages[channel.state.messages.length - 1]);
41-
42-
const [forceUpdate, setForceUpdate] = useState(0);
43-
const [unread, setUnread] = useState(channel.countUnread());
44-
36+
const { forceUpdate, channel, client, Preview } = props;
37+
const { muted } = useIsChannelMuted(channel);
38+
const { lastMessage, unread } = useChannelPreviewData(channel, client, forceUpdate, muted);
4539
const latestMessagePreview = useLatestMessagePreview(channel, forceUpdate, lastMessage);
4640

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} />;
41+
return (
42+
<Preview
43+
channel={channel}
44+
latestMessagePreview={latestMessagePreview}
45+
muted={muted}
46+
unread={unread}
47+
/>
48+
);
11549
};
11650

11751
export type ChannelPreviewProps<

package/src/components/ChannelPreview/ChannelPreviewMessenger.tsx

Lines changed: 5 additions & 15 deletions
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
};
@@ -116,6 +117,7 @@ const ChannelPreviewMessengerWithContext = <
116117
PreviewStatus = ChannelPreviewStatus,
117118
PreviewTitle = ChannelPreviewTitle,
118119
PreviewUnreadCount = ChannelPreviewUnreadCount,
120+
muted,
119121
unread,
120122
} = props;
121123
const { vw } = useViewport();
@@ -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

Lines changed: 2 additions & 7 deletions
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)