Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
MessageFooterProps,
MessageHeaderProps,
MessagePinnedHeader,
Time,
useMessageContext,
useMessageReminder,
useStateStore,
useTheme,
useTranslationContext,
} from 'stream-chat-react-native';
import { ReminderState } from 'stream-chat';
Expand All @@ -12,12 +15,16 @@ const reminderStateSelector = (state: ReminderState) => ({
timeLeftMs: state.timeLeftMs,
});

export const MessageReminderHeader = ({ message }: MessageFooterProps) => {
export const MessageReminderHeader = ({ message }: MessageHeaderProps) => {
const messageId = message?.id ?? '';
const reminder = useMessageReminder(messageId);
const { timeLeftMs } = useStateStore(reminder?.state, reminderStateSelector) ?? {};
const { t } = useTranslationContext();

const {
theme: { semantics },
} = useTheme();

const stopRefreshBoundaryMs = reminder?.timer.stopRefreshBoundaryMs;
const stopRefreshTimeStamp =
reminder?.remindAt && stopRefreshBoundaryMs
Expand All @@ -43,8 +50,8 @@ export const MessageReminderHeader = ({ message }: MessageFooterProps) => {
if (reminder.remindAt && timeLeftMs !== null) {
return (
<View style={styles.headerContainer}>
<Time height={16} width={16} />
<Text style={styles.headerTitle}>
<Time height={16} width={16} stroke={semantics.chatTextTimestamp} />
<Text style={[styles.headerTitle, { color: semantics.chatTextTimestamp }]}>
{isBehindRefreshBoundary
? t('Due since {{ dueSince }}', {
dueSince: t('timestamp/ReminderNotification', {
Expand All @@ -62,6 +69,16 @@ export const MessageReminderHeader = ({ message }: MessageFooterProps) => {
}
};

export const MessageHeader = () => {
const { message } = useMessageContext();
return (
<>
<MessageReminderHeader message={message} />
<MessagePinnedHeader />
</>
);
};

const styles = StyleSheet.create({
headerContainer: {
flexDirection: 'row',
Expand Down
4 changes: 2 additions & 2 deletions examples/SampleApp/src/screens/ChannelScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { useChannelMembersStatus } from '../hooks/useChannelMembersStatus';
import type { StackNavigatorParamList } from '../types';
import { NetworkDownIndicator } from '../components/NetworkDownIndicator';
import { useCreateDraftFocusEffect } from '../utils/useCreateDraftFocusEffect.tsx';
import { MessageReminderHeader } from '../components/Reminders/MessageReminderHeader.tsx';
import { MessageHeader } from '../components/Reminders/MessageReminderHeader.tsx';
import { channelMessageActions } from '../utils/messageActions.tsx';
import { MessageLocation } from '../components/LocationSharing/MessageLocation.tsx';
import { useStreamChatContext } from '../context/StreamChatContext.tsx';
Expand Down Expand Up @@ -233,7 +233,7 @@ export const ChannelScreen: React.FC<ChannelScreenProps> = ({
initialScrollToFirstUnreadMessage
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : -300}
messageActions={messageActions}
MessageHeader={MessageReminderHeader}
MessageHeader={MessageHeader}
MessageLocation={MessageLocation}
messageId={messageId}
NetworkDownIndicator={() => null}
Expand Down
2 changes: 1 addition & 1 deletion examples/SampleApp/src/utils/messageActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function channelMessageActions({
},
actionType: reminder ? 'remove-from-later' : 'save-for-later',
title: reminder ? 'Remove from Later' : 'Save for Later',
icon: <Time width={20} height={20} pathFill={semantics.textSecondary} />,
icon: <Time width={20} height={20} stroke={semantics.textSecondary} />,
type: 'standard',
});
actions.push({
Expand Down
7 changes: 2 additions & 5 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ import { MessageBlocked as MessageBlockedDefault } from '../Message/MessageSimpl
import { MessageBounce as MessageBounceDefault } from '../Message/MessageSimple/MessageBounce';
import { MessageContent as MessageContentDefault } from '../Message/MessageSimple/MessageContent';
import { MessageDeleted as MessageDeletedDefault } from '../Message/MessageSimple/MessageDeleted';
import { MessageEditedTimestamp as MessageEditedTimestampDefault } from '../Message/MessageSimple/MessageEditedTimestamp';
import { MessageError as MessageErrorDefault } from '../Message/MessageSimple/MessageError';
import { MessageFooter as MessageFooterDefault } from '../Message/MessageSimple/MessageFooter';
import { MessageHeader as MessageHeaderDefault } from '../Message/MessageSimple/MessageHeader';
import { MessagePinnedHeader as MessagePinnedHeaderDefault } from '../Message/MessageSimple/MessagePinnedHeader';
import { MessageReplies as MessageRepliesDefault } from '../Message/MessageSimple/MessageReplies';
import { MessageRepliesAvatars as MessageRepliesAvatarsDefault } from '../Message/MessageSimple/MessageRepliesAvatars';
Expand Down Expand Up @@ -359,7 +359,6 @@ export type ChannelPropsWithContext = Pick<ChannelContextValue, 'channel'> &
| 'MessageContent'
| 'messageContentOrder'
| 'MessageDeleted'
| 'MessageEditedTimestamp'
| 'MessageError'
| 'MessageFooter'
| 'MessageHeader'
Expand Down Expand Up @@ -673,11 +672,10 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
'location',
],
MessageDeleted = MessageDeletedDefault,
MessageEditedTimestamp = MessageEditedTimestampDefault,
MessageError = MessageErrorDefault,
messageInputFloating = false,
MessageFooter = MessageFooterDefault,
MessageHeader,
MessageHeader = MessageHeaderDefault,
messageId,
MessageList = MessageListDefault,
MessageLocation,
Expand Down Expand Up @@ -1931,7 +1929,6 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
MessageContent,
messageContentOrder,
MessageDeleted,
MessageEditedTimestamp,
MessageError,
MessageFooter,
MessageHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export const useCreateMessagesContext = ({
MessageContent,
messageContentOrder,
MessageDeleted,
MessageEditedTimestamp,
MessageError,
MessageFooter,
MessageHeader,
Expand Down Expand Up @@ -171,7 +170,6 @@ export const useCreateMessagesContext = ({
MessageContent,
messageContentOrder,
MessageDeleted,
MessageEditedTimestamp,
MessageError,
MessageFooter,
MessageHeader,
Expand Down
12 changes: 3 additions & 9 deletions package/src/components/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ import {
hasOnlyEmojis,
isBlockedMessage,
isBouncedMessage,
isEditedMessage,
MessageStatusTypes,
} from '../../utils/utils';
import type { Thumbnail } from '../Attachment/utils/buildGallery/types';
Expand Down Expand Up @@ -243,7 +242,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
const [isErrorInMessage, setIsErrorInMessage] = useState(false);
const [showMessageReactions, setShowMessageReactions] = useState(true);
const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false);
const [isEditedMessageOpen, setIsEditedMessageOpen] = useState(false);
// const [selectedReaction, setSelectedReaction] = useState<string | undefined>(undefined);

const {
Expand Down Expand Up @@ -319,9 +317,10 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
const { client } = chatContext;
const {
theme: {
colors: { targetedMessageBackground, bg_gradient_start },
colors: { bg_gradient_start },
messageSimple: { targetedMessageContainer, unreadUnderlayColor = bg_gradient_start, wrapper },
screenPadding,
semantics,
},
} = useTheme();

Expand Down Expand Up @@ -391,9 +390,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
if (dismissKeyboardOnMessageTouch) {
dismissKeyboard();
}
if (isEditedMessage(message)) {
setIsEditedMessageOpen((prevState) => !prevState);
}
const quotedMessage = message.quoted_message;
if (error) {
setIsErrorInMessage(true);
Expand Down Expand Up @@ -706,7 +702,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
handleToggleReaction,
hasReactions,
images: attachments.images,
isEditedMessageOpen,
isMessageAIGenerated,
isMyMessage,
lastGroupMessage: groupStyles?.[0] === 'single' || groupStyles?.[0] === 'bottom',
Expand Down Expand Up @@ -779,7 +774,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
preventPress: overlayActive ? true : preventPress,
reactions,
readBy,
setIsEditedMessageOpen,
setQuotedMessage,
showAvatar,
showMessageOverlay,
Expand Down Expand Up @@ -827,7 +821,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
wrapper,
(isTargetedMessage || message.pinned) && !isMessageTypeDeleted
? {
backgroundColor: targetedMessageBackground,
backgroundColor: semantics.backgroundCoreHighlight,
...targetedMessageContainer,
}
: {},
Expand Down
18 changes: 7 additions & 11 deletions package/src/components/Message/MessageSimple/MessageAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,28 @@ import { avatarSizes } from '../../ui/Avatar/constants';

export type MessageAvatarPropsWithContext = Pick<
MessageContextValue,
'alignment' | 'lastGroupMessage' | 'message' | 'showAvatar'
'lastGroupMessage' | 'message' | 'showAvatar'
> &
Partial<Pick<AvatarProps, 'size'>>;

const MessageAvatarWithContext = (props: MessageAvatarPropsWithContext) => {
const { alignment, lastGroupMessage, message, showAvatar, size } = props;
const { lastGroupMessage, message, showAvatar, size } = props;
const {
theme: {
messageSimple: {
avatarWrapper: { container, leftAlign, rightAlign },
avatarWrapper: { container },
},
},
} = useTheme();

const visible = typeof showAvatar === 'boolean' ? showAvatar : lastGroupMessage;

return (
<View
style={[alignment === 'left' ? leftAlign : rightAlign, container]}
testID='message-avatar'
>
<View style={container} testID='message-avatar'>
{visible && message.user ? (
<UserAvatar user={message.user} size={size ?? 'sm'} />
<UserAvatar user={message.user} size={size ?? 'md'} />
) : (
<View style={avatarSizes[size ?? 'sm']} testID='spacer' />
<View style={avatarSizes[size ?? 'md']} testID='spacer' />
)}
</View>
);
Expand Down Expand Up @@ -72,12 +69,11 @@ const MemoizedMessageAvatar = React.memo(
export type MessageAvatarProps = Partial<MessageAvatarPropsWithContext>;

export const MessageAvatar = (props: MessageAvatarProps) => {
const { alignment, lastGroupMessage, message, showAvatar } = useMessageContext();
const { lastGroupMessage, message, showAvatar } = useMessageContext();

return (
<MemoizedMessageAvatar
{...{
alignment,
lastGroupMessage,
message,
showAvatar,
Expand Down
26 changes: 22 additions & 4 deletions package/src/components/Message/MessageSimple/MessageBubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ import { MessagesContextValue, useTheme } from '../../../contexts';

import { useStableCallback } from '../../../hooks';
import { NativeHandlers } from '../../../native';
import { MessageStatusTypes } from '../../../utils/utils';

export type MessageBubbleProps = Pick<
MessageSimplePropsWithContext,
'reactionListPosition' | 'MessageContent' | 'ReactionListTop'
MessagesContextValue,
'reactionListPosition' | 'MessageContent' | 'ReactionListTop' | 'MessageError'
> &
Pick<
MessageContentProps,
Expand All @@ -30,6 +31,7 @@ export type MessageBubbleProps = Pick<
| 'messageGroupedSingleOrBottom'
| 'noBorder'
| 'setMessageContentWidth'
| 'message'
> &
Pick<ReactionListTopProps, 'messageContentWidth'>;

Expand All @@ -44,15 +46,19 @@ export const MessageBubble = React.memo(
isVeryLastMessage,
messageGroupedSingleOrBottom,
noBorder,
MessageError,
message,
}: MessageBubbleProps) => {
const {
theme: {
messageSimple: { contentWrapper },
messageSimple: { contentContainer },
},
} = useTheme();
const isMessageErrorType =
message?.type === 'error' || message?.status === MessageStatusTypes.FAILED;

return (
<View style={[styles.contentWrapper, contentWrapper]}>
<View style={[styles.contentContainer, contentContainer]}>
<MessageContent
backgroundColor={backgroundColor}
isVeryLastMessage={isVeryLastMessage}
Expand All @@ -63,6 +69,11 @@ export const MessageBubble = React.memo(
{reactionListPosition === 'top' && ReactionListTop ? (
<ReactionListTop messageContentWidth={messageContentWidth} />
) : null}
{isMessageErrorType ? (
<View style={styles.errorContainer}>
<MessageError />
</View>
) : null}
</View>
);
},
Expand Down Expand Up @@ -210,10 +221,17 @@ const styles = StyleSheet.create({
contentWrapper: {
alignItems: 'center',
flexDirection: 'row',
zIndex: 1, // To hide the stick inside the message content
},
contentContainer: {},
swipeContentContainer: {
flexShrink: 0,
overflow: 'hidden',
position: 'relative',
},
errorContainer: {
position: 'absolute',
top: 8,
right: -12,
},
});
Loading
Loading