Skip to content

Commit

Permalink
Merge pull request #2780 from GetStream/develop
Browse files Browse the repository at this point in the history
Next Release
  • Loading branch information
isekovanic authored Nov 14, 2024
2 parents 2603ff1 + 834d124 commit 052a0cd
Show file tree
Hide file tree
Showing 20 changed files with 487 additions and 164 deletions.
8 changes: 4 additions & 4 deletions package/expo-package/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2929,10 +2929,10 @@ [email protected]:
resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"
integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==

[email protected].3:
version "5.41.3"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.3.tgz#83db713f15725fa49b8afb84d7ef01d668b98af5"
integrity sha512-Xr0iQCoRP5c2dKwlxq+EWxKLzBXHXAGagn2aShxxU7PCW5TcdUrewWIhDxOo1iZjGfzdBSZyCFX6ilhYq332RA==
[email protected].4:
version "5.41.4"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.4.tgz#55104e1eb10f464b27d82b9566a18005723ea26d"
integrity sha512-Fe2AnbfZ98nRfP5BwMOwR2iae/hT8N5oEiYOb2FwbgtJqot4UFABZDCxMVcoYcFouOK1gc5BkTjdnXYYm/L8EQ==
dependencies:
"@gorhom/bottom-sheet" "^4.6.4"
dayjs "1.10.5"
Expand Down
8 changes: 4 additions & 4 deletions package/native-package/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4244,10 +4244,10 @@ statuses@~1.5.0:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==

[email protected].3:
version "5.41.3"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.3.tgz#83db713f15725fa49b8afb84d7ef01d668b98af5"
integrity sha512-Xr0iQCoRP5c2dKwlxq+EWxKLzBXHXAGagn2aShxxU7PCW5TcdUrewWIhDxOo1iZjGfzdBSZyCFX6ilhYq332RA==
[email protected].4:
version "5.41.4"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.41.4.tgz#55104e1eb10f464b27d82b9566a18005723ea26d"
integrity sha512-Fe2AnbfZ98nRfP5BwMOwR2iae/hT8N5oEiYOb2FwbgtJqot4UFABZDCxMVcoYcFouOK1gc5BkTjdnXYYm/L8EQ==
dependencies:
"@gorhom/bottom-sheet" "^4.6.4"
dayjs "1.10.5"
Expand Down
2 changes: 1 addition & 1 deletion package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"path": "0.12.7",
"react-native-markdown-package": "1.8.2",
"react-native-url-polyfill": "^1.3.0",
"stream-chat": "8.42.0"
"stream-chat": "8.44.0"
},
"peerDependencies": {
"react-native-quick-sqlite": ">=5.1.0",
Expand Down
27 changes: 17 additions & 10 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,7 @@ const ChannelWithContext = <
await channel.query({}, 'latest');
}
await channel.state.loadMessageIntoState('latest');
setMessages([...channel.state.messages]);
});

const loadChannel = () =>
Expand Down Expand Up @@ -1403,13 +1404,17 @@ const ChannelWithContext = <
}, [enableOfflineSupport, shouldSyncChannel]);

const reloadChannel = () =>
channelQueryCallRef.current(async () => {
setLoading(true);
await loadLatestMessagesRef.current(true);
setLoading(false);
channel?.state.setIsUpToDate(true);
setHasNoMoreRecentMessagesToLoad(true);
});
channelQueryCallRef.current(
async () => {
setLoading(true);
await loadLatestMessagesRef.current(true);
setLoading(false);
},
() => {
channel?.state.setIsUpToDate(true);
setHasNoMoreRecentMessagesToLoad(true);
},
);

/**
* @deprecated
Expand Down Expand Up @@ -1888,10 +1893,12 @@ const ChannelWithContext = <
const latestLengthBeforeMerge = latestMessageSet?.messages.length || 0;
const didMerge = mergeOverlappingMessageSetsRef.current(true);
if (didMerge) {
if (latestMessageSet && latestLengthBeforeMerge >= limit) {
if (latestMessageSet && latestLengthBeforeMerge > 0) {
const shouldSetStateUpToDate =
latestMessageSet.messages.length < limit && latestMessageSet.isCurrent;
setLoadingMoreRecent(true);
channel.state.setIsUpToDate(true);
setHasNoMoreRecentMessagesToLoad(true);
channel.state.setIsUpToDate(shouldSetStateUpToDate);
setHasNoMoreRecentMessagesToLoad(shouldSetStateUpToDate);
loadMoreRecentFinished(channel.state.messages);
restartSetsMergeFuncRef.current();
return;
Expand Down
127 changes: 24 additions & 103 deletions package/src/components/ChannelPreview/ChannelPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react';
import React from 'react';

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

import { useChannelPreviewData } from './hooks/useChannelPreviewData';
import { useLatestMessagePreview } from './hooks/useLatestMessagePreview';

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

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

export type ChannelPreviewPropsWithContext<
export type ChannelPreviewProps<
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
> = Pick<ChatContextValue<StreamChatGenerics>, 'client'> &
Pick<ChannelsContextValue<StreamChatGenerics>, 'Preview' | 'forceUpdate'> & {
> = Partial<Pick<ChatContextValue<StreamChatGenerics>, 'client'>> &
Partial<Pick<ChannelsContextValue<StreamChatGenerics>, 'Preview' | 'forceUpdate'>> & {
/**
* Instance of Channel from stream-chat package.
*/
channel: Channel<StreamChatGenerics>;
};

/**
* This component manages state for the ChannelPreviewMessenger UI component and receives
* all props from the ChannelListMessenger component.
*/
const ChannelPreviewWithContext = <
export const ChannelPreview = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
>(
props: ChannelPreviewPropsWithContext<StreamChatGenerics>,
props: ChannelPreviewProps<StreamChatGenerics>,
) => {
const { channel, client, forceUpdate: channelListForceUpdate, Preview } = props;
const { channel, client: propClient, forceUpdate: propForceUpdate, Preview: propPreview } = props;

const [lastMessage, setLastMessage] = useState<
| ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>
| MessageResponse<StreamChatGenerics>
| undefined
>(channel.state.messages[channel.state.messages.length - 1]);
const { client: contextClient } = useChatContext<StreamChatGenerics>();
const { forceUpdate: contextForceUpdate, Preview: contextPreview } =
useChannelsContext<StreamChatGenerics>();

const [forceUpdate, setForceUpdate] = useState(0);
const [unread, setUnread] = useState(channel.countUnread());
const client = propClient || contextClient;
const forceUpdate = propForceUpdate || contextForceUpdate;
const Preview = propPreview || contextPreview;

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

const channelLastMessage = channel.lastMessage();
const channelLastMessageString = `${channelLastMessage?.id}${channelLastMessage?.updated_at}`;

useEffect(() => {
const { unsubscribe } = client.on('notification.mark_read', () => {
setUnread(channel.countUnread());
});
return unsubscribe;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (
channelLastMessage &&
(channelLastMessage.id !== lastMessage?.id ||
channelLastMessage.updated_at !== lastMessage?.updated_at)
) {
setLastMessage(channelLastMessage);
}

const newUnreadCount = channel.countUnread();
setUnread(newUnreadCount);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [channelLastMessageString, channelListForceUpdate]);

useEffect(() => {
const handleNewMessageEvent = (event: Event<StreamChatGenerics>) => {
const message = event.message;
if (message && (!message.parent_id || message.show_in_channel)) {
setLastMessage(event.message);
setUnread(channel.countUnread());
}
};

const handleUpdatedOrDeletedMessage = (event: Event<StreamChatGenerics>) => {
setLastMessage((prevLastMessage) => {
if (prevLastMessage?.id === event.message?.id) {
return event.message;
}
return prevLastMessage;
});
};

const listeners = [
channel.on('message.new', handleNewMessageEvent),
channel.on('message.updated', handleUpdatedOrDeletedMessage),
channel.on('message.deleted', handleUpdatedOrDeletedMessage),
];

return () => listeners.forEach((l) => l.unsubscribe());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
const handleReadEvent = (event: Event<StreamChatGenerics>) => {
if (event.user?.id === client.userID) {
setUnread(0);
} else if (event.user?.id) {
setForceUpdate((prev) => prev + 1);
}
};

const listener = channel.on('message.read', handleReadEvent);
return () => listener.unsubscribe();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return <Preview channel={channel} latestMessagePreview={latestMessagePreview} unread={unread} />;
};

export type ChannelPreviewProps<
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
> = Partial<Omit<ChannelPreviewPropsWithContext<StreamChatGenerics>, 'channel'>> &
Pick<ChannelPreviewPropsWithContext<StreamChatGenerics>, 'channel'>;

export const ChannelPreview = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
>(
props: ChannelPreviewProps<StreamChatGenerics>,
) => {
const { client } = useChatContext<StreamChatGenerics>();
const { forceUpdate, Preview } = useChannelsContext<StreamChatGenerics>();

return <ChannelPreviewWithContext {...{ client, forceUpdate, Preview }} {...props} />;
return (
<Preview
channel={channel}
latestMessagePreview={latestMessagePreview}
muted={muted}
unread={unread}
/>
);
};
20 changes: 5 additions & 15 deletions package/src/components/ChannelPreview/ChannelPreviewMessenger.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';

Expand All @@ -17,7 +17,6 @@ import {
ChannelsContextValue,
useChannelsContext,
} from '../../contexts/channelsContext/ChannelsContext';
import { useChatContext } from '../../contexts/chatContext/ChatContext';
import { useTheme } from '../../contexts/themeContext/ThemeContext';
import { useViewport } from '../../hooks/useViewport';
import type { DefaultStreamChatGenerics } from '../../types/types';
Expand Down Expand Up @@ -95,6 +94,8 @@ export type ChannelPreviewMessengerPropsWithContext<
* default formatted date. This default logic is part of ChannelPreview component.
*/
formatLatestMessageDate?: (date: Date) => string;
/** If the channel is muted. */
muted?: boolean;
/** Number of unread messages on the channel */
unread?: number;
};
Expand All @@ -109,6 +110,7 @@ const ChannelPreviewMessengerWithContext = <
formatLatestMessageDate,
latestMessagePreview,
maxUnreadCount,
muted,
onSelect,
PreviewAvatar = ChannelAvatar,
PreviewMessage = ChannelPreviewMessage,
Expand All @@ -129,23 +131,11 @@ const ChannelPreviewMessengerWithContext = <
},
} = useTheme();

const { client } = useChatContext<StreamChatGenerics>();

const displayName = useChannelPreviewDisplayName(
channel,
Math.floor(maxWidth / ((title.fontSize || styles.title.fontSize) / 2)),
);

const [isChannelMuted, setIsChannelMuted] = useState(() => channel.muteStatus().muted);

useEffect(() => {
const handleEvent = () => setIsChannelMuted(channel.muteStatus().muted);

client.on('notification.channel_mutes_updated', handleEvent);
return () => client.off('notification.channel_mutes_updated', handleEvent);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [client]);

return (
<TouchableOpacity
onPress={() => {
Expand All @@ -168,7 +158,7 @@ const ChannelPreviewMessengerWithContext = <
<View style={[styles.row, row]}>
<PreviewTitle channel={channel} displayName={displayName} />
<View style={[styles.statusContainer, row]}>
{isChannelMuted && <PreviewMutedStatus />}
{muted && <PreviewMutedStatus />}
<PreviewUnreadCount channel={channel} maxUnreadCount={maxUnreadCount} unread={unread} />
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,11 @@ export const ChannelPreviewMutedStatus = () => {
channelPreview: {
mutedStatus: { height, iconStyle, width },
},
colors: { grey_dark },
colors: { grey },
},
} = useTheme();

return (
<Mute
height={height}
pathFill={grey_dark}
style={[styles.iconStyle, iconStyle]}
width={width}
/>
<Mute height={height} pathFill={grey} style={[styles.iconStyle, iconStyle]} width={width} />
);
};
Loading

0 comments on commit 052a0cd

Please sign in to comment.