Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ import {
isImagePickerAvailable,
NativeHandlers,
} from '../../native';
import { ChannelUnreadState, FileTypes } from '../../types/types';
import {
ChannelUnreadStateStore,
ChannelUnreadStateStoreType,
} from '../../state-store/channel-unread-state';
import { FileTypes } from '../../types/types';
import { addReactionToLocalState } from '../../utils/addReactionToLocalState';
import { compressedImageURI } from '../../utils/compressImage';
import { patchMessageTextCommand } from '../../utils/patchMessageTextCommand';
Expand Down Expand Up @@ -420,7 +424,7 @@ export type ChannelPropsWithContext = Pick<ChannelContextValue, 'channel'> &
*/
doMarkReadRequest?: (
channel: ChannelType,
setChannelUnreadUiState?: (state: ChannelUnreadState) => void,
setChannelUnreadUiState?: (data: ChannelUnreadStateStoreType['channelUnreadState']) => void,
) => void;
/**
* Overrides the Stream default send message request (Advanced usage only)
Expand Down Expand Up @@ -765,10 +769,13 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
const [thread, setThread] = useState<LocalMessage | null>(threadProps || null);
const [threadHasMore, setThreadHasMore] = useState(true);
const [threadLoadingMore, setThreadLoadingMore] = useState(false);
const [channelUnreadState, setChannelUnreadState] = useState<ChannelUnreadState | undefined>(
undefined,
const channelUnreadStateStore = useMemo(() => new ChannelUnreadStateStore(), []);
const setChannelUnreadState = useCallback(
(data: ChannelUnreadStateStoreType['channelUnreadState']) => {
channelUnreadStateStore.channelUnreadState = data;
},
[channelUnreadStateStore],
);

const { bottomSheetRef, closePicker, openPicker } = useAttachmentPickerBottomSheet();

const syncingChannelRef = useRef(false);
Expand Down Expand Up @@ -893,16 +900,14 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
}

if (event.type === 'notification.mark_unread') {
setChannelUnreadState((prev) => {
if (!(event.last_read_at && event.user)) {
return prev;
}
return {
first_unread_message_id: event.first_unread_message_id,
last_read: new Date(event.last_read_at),
last_read_message_id: event.last_read_message_id,
unread_messages: event.unread_messages ?? 0,
};
if (!(event.last_read_at && event.user)) {
return;
}
setChannelUnreadState({
first_unread_message_id: event.first_unread_message_id,
last_read: new Date(event.last_read_at),
last_read_message_id: event.last_read_message_id,
unread_messages: event.unread_messages ?? 0,
});
}

Expand Down Expand Up @@ -1758,7 +1763,8 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =

const channelContext = useCreateChannelContext({
channel,
channelUnreadState,
channelUnreadState: channelUnreadStateStore.channelUnreadState,
channelUnreadStateStore,
disabled: !!channel?.data?.frozen,
EmptyStateIndicator,
enableMessageGroupingByUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { ChannelContextValue } from '../../../contexts/channelContext/Chann
export const useCreateChannelContext = ({
channel,
channelUnreadState,
channelUnreadStateStore,
disabled,
EmptyStateIndicator,
enableMessageGroupingByUser,
Expand Down Expand Up @@ -46,12 +47,12 @@ export const useCreateChannelContext = ({
const readUsersLastReads = readUsers
.map(({ last_read }) => last_read?.toISOString() ?? '')
.join();
const stringifiedChannelUnreadState = JSON.stringify(channelUnreadState);

const channelContext: ChannelContextValue = useMemo(
() => ({
channel,
channelUnreadState,
channelUnreadStateStore,
disabled,
EmptyStateIndicator,
enableMessageGroupingByUser,
Expand Down Expand Up @@ -96,7 +97,6 @@ export const useCreateChannelContext = ({
membersLength,
readUsersLength,
readUsersLastReads,
stringifiedChannelUnreadState,
targetedMessage,
threadList,
watcherCount,
Expand Down
15 changes: 0 additions & 15 deletions package/src/components/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
handleRetry,
handleThreadReply,
isTargetedMessage,
lastReceivedId,
members,
message,
messageActions: messageActionsProp = defaultMessageActions,
Expand Down Expand Up @@ -650,7 +649,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
isMessageAIGenerated,
isMyMessage,
lastGroupMessage: groupStyles?.[0] === 'single' || groupStyles?.[0] === 'bottom',
lastReceivedId,
members,
message,
messageContentOrder,
Expand Down Expand Up @@ -783,7 +781,6 @@ const areEqual = (prevProps: MessagePropsWithContext, nextProps: MessagePropsWit
groupStyles: prevGroupStyles,
isAttachmentEqual,
isTargetedMessage: prevIsTargetedMessage,
lastReceivedId: prevLastReceivedId,
members: prevMembers,
message: prevMessage,
messagesContext: prevMessagesContext,
Expand All @@ -797,7 +794,6 @@ const areEqual = (prevProps: MessagePropsWithContext, nextProps: MessagePropsWit
goToMessage: nextGoToMessage,
groupStyles: nextGroupStyles,
isTargetedMessage: nextIsTargetedMessage,
lastReceivedId: nextLastReceivedId,
members: nextMembers,
message: nextMessage,
messagesContext: nextMessagesContext,
Expand Down Expand Up @@ -826,17 +822,6 @@ const areEqual = (prevProps: MessagePropsWithContext, nextProps: MessagePropsWit
return false;
}

const lastReceivedIdChangedAndMatters =
prevLastReceivedId !== nextLastReceivedId &&
(prevLastReceivedId === prevMessage.id ||
prevLastReceivedId === nextMessage.id ||
nextLastReceivedId === prevMessage.id ||
nextLastReceivedId === nextMessage.id);

if (lastReceivedIdChangedAndMatters) {
return false;
}

const goToMessageChangedAndMatters =
nextMessage.quoted_message_id && prevGoToMessage !== nextGoToMessage;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,6 @@ export const MessageContent = (props: MessageContentProps) => {
isEditedMessageOpen,
isMessageAIGenerated,
isMyMessage,
lastReceivedId,
message,
messageContentOrder,
onLongPress,
Expand Down Expand Up @@ -575,7 +574,6 @@ export const MessageContent = (props: MessageContentProps) => {
isEditedMessageOpen,
isMessageAIGenerated,
isMyMessage,
lastReceivedId,
message,
messageContentOrder,
MessageError,
Expand Down
123 changes: 123 additions & 0 deletions package/src/components/Message/MessageSimple/MessageWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from 'react';

import { View } from 'react-native';

import { LocalMessage } from 'stream-chat';

import { MessageListProps } from '../../../components/MessageList/MessageList';
import { useChannelContext } from '../../../contexts/channelContext/ChannelContext';
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
import { MessageContextValue } from '../../../contexts/messageContext/MessageContext';
import { useMessagesContext } from '../../../contexts/messagesContext/MessagesContext';
import { ThemeProvider, useTheme } from '../../../contexts/themeContext/ThemeContext';

import { Theme } from '../../../contexts/themeContext/utils/theme';
import { useStateStore } from '../../../hooks/useStateStore';
import { ChannelUnreadStateStoreType } from '../../../state-store/channel-unread-state';

const channelUnreadStateSelector = (state: ChannelUnreadStateStoreType) => ({
first_unread_message_id: state.channelUnreadState?.first_unread_message_id,
last_read: state.channelUnreadState?.last_read,
last_read_message_id: state.channelUnreadState?.last_read_message_id,
unread_messages: state.channelUnreadState?.unread_messages,
});

export type MessageWrapperProps = Pick<MessageContextValue, 'goToMessage'> &
Pick<MessageListProps, 'onThreadSelect'> & {
isNewestMessage?: boolean;
message: LocalMessage;
modifiedTheme?: Theme;
dateSeparatorDate?: Date;
messageGroupStyles?: string[];
};

export const MessageWrapper = (props: MessageWrapperProps) => {
const {
dateSeparatorDate,
isNewestMessage,
message,
messageGroupStyles,
goToMessage,
onThreadSelect,
modifiedTheme,
} = props;
const { client } = useChatContext();
const { channelUnreadStateStore, channel, highlightedMessageId, threadList } =
useChannelContext();
const {
InlineDateSeparator,
InlineUnreadIndicator,
Message,
MessageSystem,
myMessageTheme,
shouldShowUnreadUnderlay,
} = useMessagesContext();

const { first_unread_message_id, last_read, last_read_message_id, unread_messages } =
useStateStore(channelUnreadStateStore.state, channelUnreadStateSelector);
const {
theme: {
messageList: { messageContainer },
screenPadding,
},
} = useTheme();
if (!channel || channel.disconnected) {
return null;
}

const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
const lastReadTimestamp = last_read?.getTime();
const isLastReadMessage =
last_read_message_id === message.id ||
(!unread_messages && createdAtTimestamp === lastReadTimestamp);

const showUnreadSeparator =
isLastReadMessage &&
!isNewestMessage &&
// The `channelUnreadState?.first_unread_message_id` is here for sent messages unread label
(!!first_unread_message_id || !!unread_messages);

const showUnreadUnderlay = !!shouldShowUnreadUnderlay && showUnreadSeparator;

const wrapMessageInTheme = client.userID === message.user?.id && !!myMessageTheme;
const renderDateSeperator = dateSeparatorDate ? (
<InlineDateSeparator date={dateSeparatorDate} />
) : null;

const renderMessage = (
<Message
goToMessage={goToMessage}
groupStyles={messageGroupStyles ?? []}
isTargetedMessage={highlightedMessageId === message.id}
message={message}
onThreadSelect={onThreadSelect}
showUnreadUnderlay={showUnreadUnderlay}
style={[messageContainer]}
threadList={threadList}
/>
);

return (
<View testID={`message-list-item-${message.id}`}>
{message.type === 'system' ? (
<MessageSystem
message={message}
style={[{ paddingHorizontal: screenPadding }, messageContainer]}
/>
) : wrapMessageInTheme ? (
<ThemeProvider mergedStyle={modifiedTheme}>
<View testID={`message-list-item-${message.id}`}>
{renderDateSeperator}
{renderMessage}
</View>
</ThemeProvider>
) : (
<View testID={`message-list-item-${message.id}`}>
{renderDateSeperator}
{renderMessage}
</View>
)}
{showUnreadUnderlay && <InlineUnreadIndicator />}
</View>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ describe('MessageStatus', () => {
<ChannelsStateProvider>
<Chat client={chatClient} i18nInstance={i18nInstance}>
<Channel channel={channel}>
<MessageStatus
lastReceivedId={staticMessage.id}
message={staticMessage}
readBy={readBy}
/>
<MessageStatus message={staticMessage} readBy={readBy} />
</Channel>
</Chat>
</ChannelsStateProvider>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export const useCreateMessageContext = ({
isMessageAIGenerated,
isMyMessage,
lastGroupMessage,
lastReceivedId,
members,
message,
messageContentOrder,
Expand Down Expand Up @@ -74,7 +73,6 @@ export const useCreateMessageContext = ({
isMessageAIGenerated,
isMyMessage,
lastGroupMessage,
lastReceivedId,
members,
message,
messageContentOrder,
Expand Down Expand Up @@ -105,7 +103,6 @@ export const useCreateMessageContext = ({
hasReactions,
isEditedMessageOpen,
lastGroupMessage,
lastReceivedId,
membersValue,
myMessageThemeString,
reactionsValue,
Expand Down
Loading
Loading