1- import React , { useMemo , useRef , useState } from 'react' ;
1+ import React , { useEffect , useMemo , useRef , useState } from 'react' ;
22import {
3+ Alert ,
34 findNodeHandle ,
45 GestureResponderEvent ,
56 Keyboard ,
7+ LayoutAnimation ,
68 Pressable ,
79 StyleProp ,
10+ StyleSheet ,
811 TouchableWithoutFeedback ,
912 UIManager ,
1013 View ,
1114 ViewStyle ,
1215} from 'react-native' ;
1316
17+ import Animated , { Easing , FadeIn , FadeOut , useSharedValue } from 'react-native-reanimated' ;
1418import { Portal } from 'react-native-teleport' ;
1519
1620import type { Attachment , LocalMessage , UserResponse } from 'stream-chat' ;
@@ -21,8 +25,10 @@ import { useMessageActions } from './hooks/useMessageActions';
2125import { useMessageDeliveredData } from './hooks/useMessageDeliveryData' ;
2226import { useMessageReadData } from './hooks/useMessageReadData' ;
2327import { useProcessReactions } from './hooks/useProcessReactions' ;
28+ import { MessageOverlayBundle } from './MessageOverlayBundle' ;
2429import { messageActions as defaultMessageActions } from './utils/messageActions' ;
2530
31+ import { closeOverlay , openOverlay , useOverlayController } from '../../contexts' ;
2632import {
2733 ChannelContextValue ,
2834 useChannelContext ,
@@ -241,12 +247,12 @@ export type MessagePropsWithContext = Pick<
241247 * each individual Message component.
242248 */
243249const MessageWithContext = ( props : MessagePropsWithContext ) => {
244- const [ messageOverlayVisible , setMessageOverlayVisible ] = useState < {
245- x : number ;
246- y : number ;
247- w : number ;
248- h : number ;
249- } | null > ( null ) ;
250+ // const [messageOverlayVisible, setMessageOverlayVisible] = useState<{
251+ // x: number;
252+ // y: number;
253+ // w: number;
254+ // h: number;
255+ // } | null>(null);
250256 const [ isErrorInMessage , setIsErrorInMessage ] = useState ( false ) ;
251257 const [ showMessageReactions , setShowMessageReactions ] = useState ( true ) ;
252258 const [ isBounceDialogOpen , setIsBounceDialogOpen ] = useState ( false ) ;
@@ -326,19 +332,28 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
326332 } ,
327333 } = useTheme ( ) ;
328334
335+ const topH = useSharedValue < { w : number ; h : number ; x : number ; y : number } | undefined > (
336+ undefined ,
337+ ) ;
338+ const bottomH = useSharedValue ( { w : 0 , h : 0 , x : 0 , y : 0 } ) ;
339+
329340 const showMessageOverlay = async ( showMessageReactions = false , selectedReaction ?: string ) => {
330341 await dismissKeyboard ( ) ;
331- const layout = await measureInWindow ( messageWrapperRef . current ) ;
332- setShowMessageReactions ( showMessageReactions ) ;
333- setMessageOverlayVisible ( layout ) ;
334- setSelectedReaction ( selectedReaction ) ;
342+ try {
343+ const layout = await measureInWindow ( messageWrapperRef . current ) ;
344+ setShowMessageReactions ( showMessageReactions ) ;
345+ // LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
346+ openOverlay ( message . id , { state : { isMyMessage, rect : layout } , topH, bottomH } ) ;
347+ setSelectedReaction ( selectedReaction ) ;
348+ } catch ( e ) {
349+ console . error ( e ) ;
350+ }
335351 } ;
336352
337353 const { setNativeScrollability } = useMessageListItemContext ( ) ;
338354
339355 const dismissOverlay = ( ) => {
340- setNativeScrollability ( true ) ;
341- setMessageOverlayVisible ( null ) ;
356+ closeOverlay ( ) ;
342357 } ;
343358
344359 const actionsEnabled =
@@ -762,6 +777,16 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
762777 videos : attachments . videos ,
763778 } ) ;
764779
780+ const { state, id, closing } = useOverlayController ( ) ;
781+
782+ const active = id === message . id ;
783+
784+ useEffect ( ( ) => {
785+ if ( ! active && setNativeScrollability ) {
786+ setNativeScrollability ( true ) ;
787+ }
788+ } , [ setNativeScrollability , active ] ) ;
789+
765790 if ( ! ( isMessageTypeDeleted || messageContentOrder . length ) ) {
766791 return null ;
767792 }
@@ -770,6 +795,8 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
770795 return < MessageBlocked message = { message } /> ;
771796 }
772797
798+ console . log ( 'ACTIVE: ' , active ) ;
799+
773800 return (
774801 < MessageProvider value = { messageContext } >
775802 < View
@@ -793,49 +820,56 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
793820 ] }
794821 testID = 'message-wrapper'
795822 >
796- { messageOverlayVisible ? (
823+ { active ? (
797824 < View
798825 style = { {
799- width : messageOverlayVisible . w ,
800- height : messageOverlayVisible . h ,
826+ width : state . rect . w ,
827+ height : state . rect . h ,
801828 } }
802829 />
803830 ) : null }
804- < Portal hostName = { messageOverlayVisible ? 'overlay' : undefined } >
805- < View
806- style = {
807- messageOverlayVisible
808- ? [
809- {
810- flex : 1 ,
811- justifyContent : 'flex-end' ,
812- } ,
813- { backgroundColor : overlay } ,
814- ]
815- : null
816- }
817- >
818- { messageOverlayVisible ? (
819- < TouchableWithoutFeedback onPress = { dismissOverlay } style = { { flex : 1 } } >
820- < View style = { { flex : 1 } } />
821- </ TouchableWithoutFeedback >
822- ) : null }
823- < View
824- style = {
825- messageOverlayVisible
826- ? {
827- position : 'absolute' ,
828- top : messageOverlayVisible . y ,
829- ...( isMyMessage
830- ? { right : messageOverlayVisible . x }
831- : { left : messageOverlayVisible . x } ) ,
832- }
833- : null
834- }
831+ < Portal hostName = { active && ! closing ? 'top-item' : undefined } >
832+ { active && ! closing ? (
833+ < Pressable
834+ onLayout = { ( e ) => {
835+ const { x, y, width : w , height : h } = e . nativeEvent . layout ;
836+ console . log ( 'BLA' , x , y , w , h ) ;
837+ topH . value = { x, y, w, h } ;
838+ } }
839+ onPress = { ( ) => Alert . alert ( 'HIT TOP' ) }
840+ >
841+ < ReactionList />
842+ </ Pressable >
843+ ) : null }
844+ </ Portal >
845+ < Portal
846+ hostName = { active ? 'message-overlay' : undefined }
847+ style = { active ? { width : state . rect . w } : null }
848+ >
849+ { /* The message itself: NOT animated; it just rides along as a child */ }
850+ < MessageSimple ref = { messageWrapperRef } />
851+
852+ { /* Actions below; height measured */ }
853+ { active && ! closing ? (
854+ < Animated . View
855+ entering = { FadeIn . duration ( ANIMATED_DURATION ) . easing ( Easing . in ( Easing . cubic ) ) }
856+ exiting = { FadeOut . duration ( ANIMATED_DURATION ) . easing ( Easing . out ( Easing . cubic ) ) }
857+ onLayout = { ( e ) => {
858+ const { x, y, width : w , height : h } = e . nativeEvent . layout ;
859+ // eslint-disable-next-line sort-keys
860+ bottomH . value = { x, y, w, h } ;
861+ } }
862+ style = { {
863+ position : 'absolute' ,
864+ top : state . rect . h ,
865+ ...( isMyMessage ? { right : state . rect . x } : { left : state . rect . x } ) ,
866+ } }
835867 >
836- < MessageSimple ref = { messageWrapperRef } />
837- </ View >
838- </ View >
868+ < Pressable onPress = { ( ) => Alert . alert ( 'HIT BOTTOM' ) } >
869+ < MessageActions />
870+ </ Pressable >
871+ </ Animated . View >
872+ ) : null }
839873 </ Portal >
840874 { isBounceDialogOpen ? (
841875 < MessageBounce setIsBounceDialogOpen = { setIsBounceDialogOpen } />
@@ -1075,3 +1109,10 @@ export const Message = (props: MessageProps) => {
10751109 />
10761110 ) ;
10771111} ;
1112+
1113+ const ReactionList = ( ) => < View style = { { backgroundColor : 'blue' , width : 150 , height : 30 } } /> ;
1114+ const MessageActions = ( ) => (
1115+ < View style = { { backgroundColor : 'purple' , width : 150 , height : 200 } } />
1116+ ) ;
1117+
1118+ const ANIMATED_DURATION = 250 ;
0 commit comments