@@ -90,7 +90,16 @@ export type MessageSimplePropsWithContext = Pick<
9090 | 'reactionListPosition'
9191 | 'ReactionListTop'
9292 | 'setQuotedMessageState'
93- > ;
93+ > & {
94+ /**
95+ * Will determine whether the swipeable wrapper is always rendered for each
96+ * message. If set to false, the animated wrapper will be rendered only when
97+ * a swiping gesture is active and not otherwise.
98+ * Since stateful components would lose their state if we remount them while
99+ * an animation is happening, this should always be set to true in those instances.
100+ */
101+ shouldRenderSwipeableWrapper : boolean ;
102+ } ;
94103
95104const MessageSimpleWithContext = ( props : MessageSimplePropsWithContext ) => {
96105 const [ messageContentWidth , setMessageContentWidth ] = useState ( 0 ) ;
@@ -123,6 +132,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
123132 ReactionListTop,
124133 setQuotedMessageState,
125134 showMessageStatus,
135+ shouldRenderSwipeableWrapper,
126136 } = props ;
127137
128138 const {
@@ -202,7 +212,9 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
202212 const translateX = useSharedValue ( 0 ) ;
203213 const touchStart = useSharedValue < { x : number ; y : number } | null > ( null ) ;
204214 const isSwiping = useSharedValue < boolean > ( false ) ;
205- const [ isBeingSwiped , setIsBeingSwiped ] = useState < boolean > ( false ) ;
215+ const [ shouldRenderAnimatedWrapper , setShouldRenderAnimatedWrapper ] = useState < boolean > (
216+ shouldRenderSwipeableWrapper ,
217+ ) ;
206218
207219 const onSwipeToReply = useCallback ( ( ) => {
208220 clearQuotedMessageState ( ) ;
@@ -233,7 +245,9 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
233245 if ( isHorizontalPanning ) {
234246 state . activate ( ) ;
235247 isSwiping . value = true ;
236- runOnJS ( setIsBeingSwiped ) ( isSwiping . value ) ;
248+ if ( ! shouldRenderSwipeableWrapper ) {
249+ runOnJS ( setShouldRenderAnimatedWrapper ) ( isSwiping . value ) ;
250+ }
237251 } else {
238252 state . fail ( ) ;
239253 }
@@ -263,11 +277,21 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
263277 stiffness : 1 ,
264278 } ,
265279 ( ) => {
266- runOnJS ( setIsBeingSwiped ) ( isSwiping . value ) ;
280+ if ( ! shouldRenderSwipeableWrapper ) {
281+ runOnJS ( setShouldRenderAnimatedWrapper ) ( isSwiping . value ) ;
282+ }
267283 } ,
268284 ) ;
269285 } ) ,
270- [ isSwiping , messageSwipeToReplyHitSlop , onSwipeToReply , touchStart , translateX , triggerHaptic ] ,
286+ [
287+ isSwiping ,
288+ messageSwipeToReplyHitSlop ,
289+ onSwipeToReply ,
290+ touchStart ,
291+ translateX ,
292+ triggerHaptic ,
293+ shouldRenderSwipeableWrapper ,
294+ ] ,
271295 ) ;
272296
273297 const messageBubbleAnimatedStyle = useAnimatedStyle (
@@ -326,7 +350,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
326350 ( ) => (
327351 < GestureDetector gesture = { swipeGesture } >
328352 < View hitSlop = { messageSwipeToReplyHitSlop } style = { [ styles . contentWrapper , contentWrapper ] } >
329- { isBeingSwiped ? (
353+ { shouldRenderAnimatedWrapper ? (
330354 < >
331355 < AnimatedWrapper
332356 style = { [
@@ -350,7 +374,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
350374 [
351375 MessageSwipeContent ,
352376 contentWrapper ,
353- isBeingSwiped ,
377+ shouldRenderAnimatedWrapper ,
354378 messageBubbleAnimatedStyle ,
355379 messageSwipeToReplyHitSlop ,
356380 renderMessageBubble ,
@@ -586,6 +610,7 @@ export const MessageSimple = (props: MessageSimpleProps) => {
586610 onlyEmojis,
587611 otherAttachments,
588612 showMessageStatus,
613+ isMessageAIGenerated,
589614 } = useMessageContext ( ) ;
590615 const {
591616 clearQuotedMessageState,
@@ -607,6 +632,11 @@ export const MessageSimple = (props: MessageSimpleProps) => {
607632 ReactionListTop,
608633 setQuotedMessageState,
609634 } = useMessagesContext ( ) ;
635+ const isAIGenerated = useMemo (
636+ ( ) => isMessageAIGenerated ( message ) ,
637+ [ message , isMessageAIGenerated ] ,
638+ ) ;
639+ const shouldRenderSwipeableWrapper = ( message ?. attachments || [ ] ) . length > 0 || isAIGenerated ;
610640
611641 return (
612642 < MemoizedMessageSimple
@@ -639,6 +669,7 @@ export const MessageSimple = (props: MessageSimpleProps) => {
639669 reactionListPosition,
640670 ReactionListTop,
641671 setQuotedMessageState,
672+ shouldRenderSwipeableWrapper,
642673 showMessageStatus,
643674 } }
644675 { ...props }
0 commit comments