From b22cd858f246f496e878df868401a766160d11fc Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 6 Mar 2026 19:14:33 +0530 Subject: [PATCH 1/2] fix: show message overlay for gallery and files when message errors out --- .../components/Attachment/FileAttachment.tsx | 14 +++++++---- package/src/components/Attachment/Gallery.tsx | 24 ++++++++++++++++--- package/src/components/Message/Message.tsx | 1 + .../Message/hooks/useCreateMessageContext.ts | 3 +++ .../messageContext/MessageContext.tsx | 2 ++ 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/package/src/components/Attachment/FileAttachment.tsx b/package/src/components/Attachment/FileAttachment.tsx index 4cc2571ef3..41fb01711c 100644 --- a/package/src/components/Attachment/FileAttachment.tsx +++ b/package/src/components/Attachment/FileAttachment.tsx @@ -19,7 +19,7 @@ import { useTheme } from '../../contexts/themeContext/ThemeContext'; export type FileAttachmentPropsWithContext = Pick< MessageContextValue, - 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' + 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' | 'isMessageErrorType' > & Pick & { /** The attachment to render */ @@ -46,9 +46,12 @@ const FileAttachmentWithContext = (props: FileAttachmentPropsWithContext) => { onPressIn, preventPress, styles: stylesProp = styles, + isMessageErrorType, } = props; - const defaultOnPress = () => openUrlSafely(attachment.asset_url); + const defaultOnPress = () => { + openUrlSafely(attachment.asset_url); + }; return ( { if (onPress) { onPress({ additionalInfo: { attachment }, - defaultHandler: defaultOnPress, + defaultHandler: isMessageErrorType ? undefined : defaultOnPress, emitter: 'fileAttachment', event, }); @@ -76,7 +79,7 @@ const FileAttachmentWithContext = (props: FileAttachmentPropsWithContext) => { if (onPressIn) { onPressIn({ additionalInfo: { attachment }, - defaultHandler: defaultOnPress, + defaultHandler: isMessageErrorType ? undefined : defaultOnPress, emitter: 'fileAttachment', event, }); @@ -98,7 +101,7 @@ export type FileAttachmentProps = Partial; export const FileAttachment = (props: FileAttachmentProps) => { - const { onLongPress, onPress, onPressIn, preventPress } = useMessageContext(); + const { onLongPress, onPress, onPressIn, preventPress, isMessageErrorType } = useMessageContext(); const { additionalPressableProps, FileAttachmentIcon = FileIconDefault } = useMessagesContext(); return ( @@ -110,6 +113,7 @@ export const FileAttachment = (props: FileAttachmentProps) => { onPress, onPressIn, preventPress, + isMessageErrorType, }} {...props} /> diff --git a/package/src/components/Attachment/Gallery.tsx b/package/src/components/Attachment/Gallery.tsx index 41c4731020..148d341af6 100644 --- a/package/src/components/Attachment/Gallery.tsx +++ b/package/src/components/Attachment/Gallery.tsx @@ -52,6 +52,7 @@ export type GalleryPropsWithContext = Pick & Pick< MessagesContextValue, @@ -85,6 +86,7 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => { videos, VideoThumbnail, messageHasOnlyOneImage = false, + isMessageErrorType, } = props; const { resizableCDNHosts } = useChatConfigContext(); @@ -209,6 +211,7 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => { setOverlay={setOverlay} thumbnail={thumbnail} VideoThumbnail={VideoThumbnail} + isMessageErrorType={isMessageErrorType} /> ); })} @@ -238,7 +241,10 @@ type GalleryThumbnailProps = { | 'ImageReloadIndicator' > & Pick & - Pick & + Pick< + MessageContextValue, + 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' | 'isMessageErrorType' + > & Pick; const GalleryThumbnail = ({ @@ -262,6 +268,7 @@ const GalleryThumbnail = ({ setOverlay, thumbnail, VideoThumbnail, + isMessageErrorType, }: GalleryThumbnailProps) => { const { theme: { @@ -315,7 +322,7 @@ const GalleryThumbnail = ({ if (onPress) { onPress({ additionalInfo: { thumbnail }, - defaultHandler: defaultOnPress, + defaultHandler: isMessageErrorType ? undefined : defaultOnPress, emitter: 'gallery', event, }); @@ -325,7 +332,7 @@ const GalleryThumbnail = ({ if (onPressIn) { onPressIn({ additionalInfo: { thumbnail }, - defaultHandler: defaultOnPress, + defaultHandler: isMessageErrorType ? undefined : defaultOnPress, emitter: 'gallery', event, }); @@ -447,6 +454,7 @@ const areEqual = (prevProps: GalleryPropsWithContext, nextProps: GalleryPropsWit message: prevMessage, myMessageTheme: prevMyMessageTheme, videos: prevVideos, + isMessageErrorType: prevIsMessageErrorType, } = prevProps; const { alignment: nextAlignment, @@ -454,6 +462,7 @@ const areEqual = (prevProps: GalleryPropsWithContext, nextProps: GalleryPropsWit message: nextMessage, myMessageTheme: nextMyMessageTheme, videos: nextVideos, + isMessageErrorType: nextIsMessageErrorType, } = nextProps; const alignmentEqual = prevAlignment === nextAlignment; @@ -461,6 +470,11 @@ const areEqual = (prevProps: GalleryPropsWithContext, nextProps: GalleryPropsWit return false; } + const isMessageErrorTypeEqual = prevIsMessageErrorType === nextIsMessageErrorType; + if (!isMessageErrorTypeEqual) { + return false; + } + const messageEqual = prevMessage?.id === nextMessage?.id && `${prevMessage?.updated_at}` === `${nextMessage?.updated_at}`; @@ -524,6 +538,7 @@ export const Gallery = (props: GalleryProps) => { videos: propVideos, VideoThumbnail: PropVideoThumbnail, messageContentOrder: propMessageContentOrder, + isMessageErrorType: propIsMessageErrorType, } = props; const { imageGalleryStateStore } = useImageGalleryContext(); @@ -537,6 +552,7 @@ export const Gallery = (props: GalleryProps) => { preventPress: contextPreventPress, videos: contextVideos, messageContentOrder: contextMessageContentOrder, + isMessageErrorType: contextIsMessageErrorType, } = useMessageContext(); const { additionalPressableProps: contextAdditionalPressableProps, @@ -570,6 +586,7 @@ export const Gallery = (props: GalleryProps) => { const ImageReloadIndicator = PropImageReloadIndicator || ContextImageReloadIndicator; const myMessageTheme = propMyMessageTheme || contextMyMessageTheme; const messageContentOrder = propMessageContentOrder || contextMessageContentOrder; + const isMessageErrorType = propIsMessageErrorType || contextIsMessageErrorType; const messageHasOnlyOneImage = messageContentOrder?.length === 1 && @@ -598,6 +615,7 @@ export const Gallery = (props: GalleryProps) => { VideoThumbnail, messageHasOnlyOneImage, messageContentOrder, + isMessageErrorType, }} /> ); diff --git a/package/src/components/Message/Message.tsx b/package/src/components/Message/Message.tsx index ab5aa634a1..c1bd029c76 100644 --- a/package/src/components/Message/Message.tsx +++ b/package/src/components/Message/Message.tsx @@ -782,6 +782,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { showMessageStatus: typeof showMessageStatus === 'boolean' ? showMessageStatus : isMyMessage, threadList, videos: attachments.videos, + isMessageErrorType: errorOrFailed, }); const prevActive = useRef(overlayActive); diff --git a/package/src/components/Message/hooks/useCreateMessageContext.ts b/package/src/components/Message/hooks/useCreateMessageContext.ts index 6fc3953a83..ea1cc04a46 100644 --- a/package/src/components/Message/hooks/useCreateMessageContext.ts +++ b/package/src/components/Message/hooks/useCreateMessageContext.ts @@ -53,6 +53,7 @@ export const useCreateMessageContext = ({ threadList, videos, setQuotedMessage, + isMessageErrorType, }: MessageContextValue) => { const stableGroupStyles = useStableRefValue(groupStyles); const reactionsValue = reactions.map(({ count, own, type }) => `${own}${type}${count}`).join(); @@ -105,6 +106,7 @@ export const useCreateMessageContext = ({ showMessageStatus, threadList, videos, + isMessageErrorType, }), // eslint-disable-next-line react-hooks/exhaustive-deps [ @@ -126,6 +128,7 @@ export const useCreateMessageContext = ({ showMessageStatus, threadList, preventPress, + isMessageErrorType, ], ); diff --git a/package/src/contexts/messageContext/MessageContext.tsx b/package/src/contexts/messageContext/MessageContext.tsx index 043c70b793..55e7fe90fb 100644 --- a/package/src/contexts/messageContext/MessageContext.tsx +++ b/package/src/contexts/messageContext/MessageContext.tsx @@ -20,6 +20,8 @@ import { DEFAULT_BASE_CONTEXT_VALUE } from '../utils/defaultBaseContextValue'; export type Alignment = 'right' | 'left'; export type MessageContextValue = { + /** Whether or not the message is an error */ + isMessageErrorType: boolean; /** Whether or not actions can be performed on message */ actionsEnabled: boolean; /** Position of the message, either 'right' or 'left' */ From a51df8585bdeafc76f0e6840733f4e9f04cf58b3 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 6 Mar 2026 19:21:12 +0530 Subject: [PATCH 2/2] fix: show message overlay for gallery and files when message errors out --- .../components/Attachment/FileAttachment.tsx | 14 ++++------- package/src/components/Attachment/Gallery.tsx | 24 +++---------------- package/src/components/Message/Message.tsx | 7 +++++- .../Message/hooks/useCreateMessageContext.ts | 3 --- .../messageContext/MessageContext.tsx | 2 -- 5 files changed, 14 insertions(+), 36 deletions(-) diff --git a/package/src/components/Attachment/FileAttachment.tsx b/package/src/components/Attachment/FileAttachment.tsx index 41fb01711c..4cc2571ef3 100644 --- a/package/src/components/Attachment/FileAttachment.tsx +++ b/package/src/components/Attachment/FileAttachment.tsx @@ -19,7 +19,7 @@ import { useTheme } from '../../contexts/themeContext/ThemeContext'; export type FileAttachmentPropsWithContext = Pick< MessageContextValue, - 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' | 'isMessageErrorType' + 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' > & Pick & { /** The attachment to render */ @@ -46,12 +46,9 @@ const FileAttachmentWithContext = (props: FileAttachmentPropsWithContext) => { onPressIn, preventPress, styles: stylesProp = styles, - isMessageErrorType, } = props; - const defaultOnPress = () => { - openUrlSafely(attachment.asset_url); - }; + const defaultOnPress = () => openUrlSafely(attachment.asset_url); return ( { if (onPress) { onPress({ additionalInfo: { attachment }, - defaultHandler: isMessageErrorType ? undefined : defaultOnPress, + defaultHandler: defaultOnPress, emitter: 'fileAttachment', event, }); @@ -79,7 +76,7 @@ const FileAttachmentWithContext = (props: FileAttachmentPropsWithContext) => { if (onPressIn) { onPressIn({ additionalInfo: { attachment }, - defaultHandler: isMessageErrorType ? undefined : defaultOnPress, + defaultHandler: defaultOnPress, emitter: 'fileAttachment', event, }); @@ -101,7 +98,7 @@ export type FileAttachmentProps = Partial; export const FileAttachment = (props: FileAttachmentProps) => { - const { onLongPress, onPress, onPressIn, preventPress, isMessageErrorType } = useMessageContext(); + const { onLongPress, onPress, onPressIn, preventPress } = useMessageContext(); const { additionalPressableProps, FileAttachmentIcon = FileIconDefault } = useMessagesContext(); return ( @@ -113,7 +110,6 @@ export const FileAttachment = (props: FileAttachmentProps) => { onPress, onPressIn, preventPress, - isMessageErrorType, }} {...props} /> diff --git a/package/src/components/Attachment/Gallery.tsx b/package/src/components/Attachment/Gallery.tsx index 148d341af6..41c4731020 100644 --- a/package/src/components/Attachment/Gallery.tsx +++ b/package/src/components/Attachment/Gallery.tsx @@ -52,7 +52,6 @@ export type GalleryPropsWithContext = Pick & Pick< MessagesContextValue, @@ -86,7 +85,6 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => { videos, VideoThumbnail, messageHasOnlyOneImage = false, - isMessageErrorType, } = props; const { resizableCDNHosts } = useChatConfigContext(); @@ -211,7 +209,6 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => { setOverlay={setOverlay} thumbnail={thumbnail} VideoThumbnail={VideoThumbnail} - isMessageErrorType={isMessageErrorType} /> ); })} @@ -241,10 +238,7 @@ type GalleryThumbnailProps = { | 'ImageReloadIndicator' > & Pick & - Pick< - MessageContextValue, - 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' | 'isMessageErrorType' - > & + Pick & Pick; const GalleryThumbnail = ({ @@ -268,7 +262,6 @@ const GalleryThumbnail = ({ setOverlay, thumbnail, VideoThumbnail, - isMessageErrorType, }: GalleryThumbnailProps) => { const { theme: { @@ -322,7 +315,7 @@ const GalleryThumbnail = ({ if (onPress) { onPress({ additionalInfo: { thumbnail }, - defaultHandler: isMessageErrorType ? undefined : defaultOnPress, + defaultHandler: defaultOnPress, emitter: 'gallery', event, }); @@ -332,7 +325,7 @@ const GalleryThumbnail = ({ if (onPressIn) { onPressIn({ additionalInfo: { thumbnail }, - defaultHandler: isMessageErrorType ? undefined : defaultOnPress, + defaultHandler: defaultOnPress, emitter: 'gallery', event, }); @@ -454,7 +447,6 @@ const areEqual = (prevProps: GalleryPropsWithContext, nextProps: GalleryPropsWit message: prevMessage, myMessageTheme: prevMyMessageTheme, videos: prevVideos, - isMessageErrorType: prevIsMessageErrorType, } = prevProps; const { alignment: nextAlignment, @@ -462,7 +454,6 @@ const areEqual = (prevProps: GalleryPropsWithContext, nextProps: GalleryPropsWit message: nextMessage, myMessageTheme: nextMyMessageTheme, videos: nextVideos, - isMessageErrorType: nextIsMessageErrorType, } = nextProps; const alignmentEqual = prevAlignment === nextAlignment; @@ -470,11 +461,6 @@ const areEqual = (prevProps: GalleryPropsWithContext, nextProps: GalleryPropsWit return false; } - const isMessageErrorTypeEqual = prevIsMessageErrorType === nextIsMessageErrorType; - if (!isMessageErrorTypeEqual) { - return false; - } - const messageEqual = prevMessage?.id === nextMessage?.id && `${prevMessage?.updated_at}` === `${nextMessage?.updated_at}`; @@ -538,7 +524,6 @@ export const Gallery = (props: GalleryProps) => { videos: propVideos, VideoThumbnail: PropVideoThumbnail, messageContentOrder: propMessageContentOrder, - isMessageErrorType: propIsMessageErrorType, } = props; const { imageGalleryStateStore } = useImageGalleryContext(); @@ -552,7 +537,6 @@ export const Gallery = (props: GalleryProps) => { preventPress: contextPreventPress, videos: contextVideos, messageContentOrder: contextMessageContentOrder, - isMessageErrorType: contextIsMessageErrorType, } = useMessageContext(); const { additionalPressableProps: contextAdditionalPressableProps, @@ -586,7 +570,6 @@ export const Gallery = (props: GalleryProps) => { const ImageReloadIndicator = PropImageReloadIndicator || ContextImageReloadIndicator; const myMessageTheme = propMyMessageTheme || contextMyMessageTheme; const messageContentOrder = propMessageContentOrder || contextMessageContentOrder; - const isMessageErrorType = propIsMessageErrorType || contextIsMessageErrorType; const messageHasOnlyOneImage = messageContentOrder?.length === 1 && @@ -615,7 +598,6 @@ export const Gallery = (props: GalleryProps) => { VideoThumbnail, messageHasOnlyOneImage, messageContentOrder, - isMessageErrorType, }} /> ); diff --git a/package/src/components/Message/Message.tsx b/package/src/components/Message/Message.tsx index c1bd029c76..4e039f6593 100644 --- a/package/src/components/Message/Message.tsx +++ b/package/src/components/Message/Message.tsx @@ -745,9 +745,15 @@ const MessageWithContext = (props: MessagePropsWithContext) => { }; const handleOnPress = () => { + if (errorOrFailed) { + onPress(true); + return; + } + if (onPressMessageProp) { return onPressMessageProp(onPressArgs); } + if (payload.defaultHandler) { return payload.defaultHandler(); } @@ -782,7 +788,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => { showMessageStatus: typeof showMessageStatus === 'boolean' ? showMessageStatus : isMyMessage, threadList, videos: attachments.videos, - isMessageErrorType: errorOrFailed, }); const prevActive = useRef(overlayActive); diff --git a/package/src/components/Message/hooks/useCreateMessageContext.ts b/package/src/components/Message/hooks/useCreateMessageContext.ts index ea1cc04a46..6fc3953a83 100644 --- a/package/src/components/Message/hooks/useCreateMessageContext.ts +++ b/package/src/components/Message/hooks/useCreateMessageContext.ts @@ -53,7 +53,6 @@ export const useCreateMessageContext = ({ threadList, videos, setQuotedMessage, - isMessageErrorType, }: MessageContextValue) => { const stableGroupStyles = useStableRefValue(groupStyles); const reactionsValue = reactions.map(({ count, own, type }) => `${own}${type}${count}`).join(); @@ -106,7 +105,6 @@ export const useCreateMessageContext = ({ showMessageStatus, threadList, videos, - isMessageErrorType, }), // eslint-disable-next-line react-hooks/exhaustive-deps [ @@ -128,7 +126,6 @@ export const useCreateMessageContext = ({ showMessageStatus, threadList, preventPress, - isMessageErrorType, ], ); diff --git a/package/src/contexts/messageContext/MessageContext.tsx b/package/src/contexts/messageContext/MessageContext.tsx index 55e7fe90fb..043c70b793 100644 --- a/package/src/contexts/messageContext/MessageContext.tsx +++ b/package/src/contexts/messageContext/MessageContext.tsx @@ -20,8 +20,6 @@ import { DEFAULT_BASE_CONTEXT_VALUE } from '../utils/defaultBaseContextValue'; export type Alignment = 'right' | 'left'; export type MessageContextValue = { - /** Whether or not the message is an error */ - isMessageErrorType: boolean; /** Whether or not actions can be performed on message */ actionsEnabled: boolean; /** Position of the message, either 'right' or 'left' */