瀏覽代碼

options/reactions menu fix

Viktoriia 2 月之前
父節點
當前提交
e152fbed67

+ 35 - 15
src/screens/InAppScreens/MessagesScreen/ChatScreen/index.tsx

@@ -177,6 +177,15 @@ const ChatScreen = ({ route }: { route: any }) => {
   const textInputRef = useRef<TextInput>(null);
 
   const socket = useRef<WebSocket | null>(null);
+  const scrollViewRef = useRef<ScrollView>(null);
+
+  useEffect(() => {
+    if (isModalVisible) {
+      setTimeout(() => {
+        scrollViewRef.current?.scrollToEnd({ animated: false });
+      }, 50);
+    }
+  }, [isModalVisible]);
 
   useEffect(() => {
     if (netInfo && netInfo.isConnected !== null) {
@@ -1160,8 +1169,8 @@ const ChatScreen = ({ route }: { route: any }) => {
           return;
         }
 
-        if (spaceBelow < 180) {
-          const extraShift = 180 - spaceBelow;
+        if (spaceBelow < 200) {
+          const extraShift = 200 - spaceBelow;
           finalY -= extraShift;
         }
 
@@ -1369,19 +1378,30 @@ const ChatScreen = ({ route }: { route: any }) => {
     selectedMessage && (
       <View
         style={{
-          maxHeight: '80%',
-          width: messagePosition?.width,
-          position: 'absolute',
-          top: messagePosition?.y,
-          left: messagePosition?.x
+          top: messagePosition?.y && messagePosition?.y > 120 ? messagePosition?.y : 0,
+          overflow: 'hidden'
         }}
       >
-        <ScrollView>
+        <ScrollView
+          ref={scrollViewRef}
+          contentContainerStyle={{
+            paddingBottom: 60
+          }}
+          showsVerticalScrollIndicator={false}
+        >
           <Bubble
             {...selectedMessage}
             wrapperStyle={{
-              right: { backgroundColor: Colors.DARK_BLUE },
-              left: { backgroundColor: Colors.FILL_LIGHT }
+              right: {
+                backgroundColor: Colors.DARK_BLUE,
+                marginTop: messagePosition?.y && messagePosition?.y > 120 ? 0 : 120,
+                marginRight: 8
+              },
+              left: {
+                backgroundColor: Colors.FILL_LIGHT,
+                marginTop: messagePosition?.y && messagePosition?.y > 120 ? 0 : 120,
+                marginLeft: 8
+              }
             }}
             textStyle={{
               right: { color: Colors.WHITE },
@@ -1399,6 +1419,11 @@ const ChatScreen = ({ route }: { route: any }) => {
                   : renderReplyMessageView(selectedMessage)
             }
           />
+          <OptionsMenu
+            selectedMessage={selectedMessage}
+            handleOptionPress={handleOptionPress}
+            messagePosition={messagePosition}
+          />
         </ScrollView>
       </View>
     );
@@ -2109,11 +2134,6 @@ const ChatScreen = ({ route }: { route: any }) => {
                 openEmojiSelector={openEmojiSelector}
               />
               {renderSelectedMessage()}
-              <OptionsMenu
-                selectedMessage={selectedMessage}
-                handleOptionPress={handleOptionPress}
-                messagePosition={messagePosition}
-              />
               <EmojiSelectorModal
                 visible={emojiSelectorVisible}
                 selectedMessage={selectedMessage}

+ 5 - 7
src/screens/InAppScreens/MessagesScreen/Components/OptionsMenu.tsx

@@ -36,10 +36,7 @@ const OptionsMenu: React.FC<OptionsMenuProps> = ({
       style={[
         styles.optionsMenu,
         {
-          top: messagePosition.y + messagePosition.height + 8,
-          left: messagePosition.isMine
-            ? Dimensions.get('window').width - Dimensions.get('window').width * 0.75 - 8
-            : messagePosition.x
+          alignSelf: messagePosition.isMine ? 'flex-end' : 'flex-start'
         }
       ]}
     >
@@ -93,16 +90,17 @@ const OptionsMenu: React.FC<OptionsMenuProps> = ({
 
 const styles = StyleSheet.create({
   optionsMenu: {
-    position: 'absolute',
+    marginHorizontal: 8,
     backgroundColor: 'rgba(255, 255, 255, 1)',
     borderRadius: 10,
     padding: 8,
+    marginTop: 8,
+    width: Dimensions.get('window').width * 0.75,
     shadowColor: '#000',
     shadowOpacity: 0.3,
     shadowOffset: { width: 0, height: 2 },
     shadowRadius: 5,
-    elevation: 5,
-    width: Dimensions.get('window').width * 0.75
+    elevation: 5
   },
   optionButton: {
     paddingVertical: 10,

+ 23 - 8
src/screens/InAppScreens/MessagesScreen/Components/ReactionBar.tsx

@@ -1,8 +1,9 @@
 import React from 'react';
-import { View, TouchableOpacity, Text, StyleSheet, Dimensions } from 'react-native';
+import { TouchableOpacity, Text, StyleSheet, Dimensions } from 'react-native';
 import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
 import { MaterialCommunityIcons } from '@expo/vector-icons';
 import { Colors } from 'src/theme';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
 
 interface MessagePosition {
   x: number;
@@ -26,19 +27,31 @@ const ReactionBar: React.FC<ReactionBarProps> = ({
   reactionEmojis,
   handleReactionPress,
   openEmojiSelector
-}) =>
-  selectedMessage &&
-  messagePosition && (
+}) => {
+  const insets = useSafeAreaInsets();
+
+  const getPosition = () => {
+    if (!messagePosition) return {};
+
+    const spaceAbove = messagePosition.y - insets.top;
+    const shouldFix = spaceAbove < 60;
+
+    return shouldFix ? { top: insets.top + 8 } : { top: messagePosition.y - 60 + 8 };
+  };
+
+  if (!selectedMessage || !messagePosition) return null;
+  return (
     <Animated.View
       entering={FadeIn}
       exiting={FadeOut}
       style={[
         styles.reactionBar,
+        getPosition(),
         {
-          top: messagePosition.y - 50, // - reaction bar height
-          left: messagePosition.isMine
-            ? Dimensions.get('window').width - Dimensions.get('window').width * 0.75 - 8 // reaction bar width
-            : messagePosition.x
+          left: messagePosition?.isMine
+            ? Dimensions.get('window').width * 0.25 - 8
+            : messagePosition?.x,
+          alignSelf: messagePosition.isMine ? 'flex-end' : 'flex-start'
         }
       ]}
     >
@@ -55,6 +68,7 @@ const ReactionBar: React.FC<ReactionBarProps> = ({
       </TouchableOpacity>
     </Animated.View>
   );
+};
 
 const styles = StyleSheet.create({
   reactionBar: {
@@ -67,6 +81,7 @@ const styles = StyleSheet.create({
     borderRadius: 20,
     padding: 5,
     paddingHorizontal: 12,
+    zIndex: 1000,
     shadowColor: '#000',
     shadowOpacity: 0.3,
     shadowOffset: { width: 0, height: 2 },

+ 78 - 28
src/screens/InAppScreens/MessagesScreen/GroupChatScreen/index.tsx

@@ -212,6 +212,15 @@ const GroupChatScreen = ({ route }: { route: any }) => {
   const textInputRef = useRef<TextInput>(null);
 
   const socket = useRef<WebSocket | null>(null);
+  const scrollViewRef = useRef<ScrollView>(null);
+
+  useEffect(() => {
+    if (isModalVisible) {
+      setTimeout(() => {
+        scrollViewRef.current?.scrollToEnd({ animated: false });
+      }, 50);
+    }
+  }, [isModalVisible]);
 
   useFocusEffect(
     useCallback(() => {
@@ -1224,8 +1233,9 @@ const GroupChatScreen = ({ route }: { route: any }) => {
           return;
         }
 
-        if (spaceBelow < 220) {
-          const extraShift = 220 - spaceBelow;
+        const maxSpaceBelow = isMine ? 280 : 200;
+        if (spaceBelow < maxSpaceBelow) {
+          const extraShift = maxSpaceBelow - spaceBelow;
           finalY -= extraShift;
         }
 
@@ -1465,23 +1475,46 @@ const GroupChatScreen = ({ route }: { route: any }) => {
     );
   };
 
-  const renderSelectedMessage = () =>
-    selectedMessage && (
+  const renderSelectedMessage = () => {
+    if (!selectedMessage) return;
+
+    const messageToCompare = selectedMessage.previousMessage;
+
+    const showUserName =
+      selectedMessage.position === 'left' &&
+      selectedMessage.currentMessage &&
+      messageToCompare &&
+      (!isSameUser(selectedMessage.currentMessage, messageToCompare) ||
+        !isSameDay(selectedMessage.currentMessage, messageToCompare));
+
+    return (
       <View
         style={{
-          maxHeight: '80%',
-          width: messagePosition?.width,
-          position: 'absolute',
-          top: messagePosition?.y,
-          left: messagePosition?.x
+          left: !messagePosition?.isMine && messagePosition?.x ? messagePosition?.x - 8 : undefined,
+          top: messagePosition?.y && messagePosition?.y > 120 ? messagePosition?.y : 0,
+          overflow: 'hidden'
         }}
       >
-        <ScrollView>
+        <ScrollView
+          ref={scrollViewRef}
+          contentContainerStyle={{
+            paddingBottom: 60
+          }}
+          showsVerticalScrollIndicator={false}
+        >
           <Bubble
             {...selectedMessage}
             wrapperStyle={{
-              right: { backgroundColor: Colors.DARK_BLUE },
-              left: { backgroundColor: Colors.FILL_LIGHT }
+              right: {
+                backgroundColor: Colors.DARK_BLUE,
+                marginTop: messagePosition?.y && messagePosition?.y > 120 ? 0 : 120,
+                marginRight: 8
+              },
+              left: {
+                backgroundColor: Colors.FILL_LIGHT,
+                marginTop: messagePosition?.y && messagePosition?.y > 120 ? 0 : 120,
+                marginLeft: 8
+              }
             }}
             textStyle={{
               right: { color: Colors.WHITE },
@@ -1489,19 +1522,43 @@ const GroupChatScreen = ({ route }: { route: any }) => {
             }}
             renderTicks={() => null}
             renderTime={renderTimeContainer}
-            renderCustomView={() =>
-              selectedMessage.currentMessage.attachment?.filetype === 'nomadmania/location'
-                ? renderMessageLocation(selectedMessage)
-                : selectedMessage.currentMessage.attachment &&
-                    !selectedMessage.currentMessage.image &&
-                    !selectedMessage.currentMessage.video
-                  ? renderMessageFile(selectedMessage)
-                  : renderReplyMessageView(selectedMessage)
-            }
+            renderCustomView={() => (
+              <View>
+                {showUserName ? (
+                  <Text
+                    style={{
+                      color: Colors.BLACK,
+                      fontWeight: '600',
+                      fontSize: 13,
+                      paddingHorizontal: 10,
+                      paddingTop: 8,
+                      paddingBottom: 2
+                    }}
+                  >
+                    {selectedMessage.currentMessage.user.name}
+                  </Text>
+                ) : null}
+                {selectedMessage.currentMessage.attachment?.filetype === 'nomadmania/location'
+                  ? renderMessageLocation(selectedMessage)
+                  : selectedMessage.currentMessage.attachment &&
+                      !selectedMessage.currentMessage.image &&
+                      !selectedMessage.currentMessage.video
+                    ? renderMessageFile(selectedMessage)
+                    : renderReplyMessageView(selectedMessage)}
+              </View>
+            )}
+          />
+          <OptionsMenu
+            selectedMessage={selectedMessage}
+            handleOptionPress={handleOptionPress}
+            messagePosition={messagePosition}
+            isGroup={true}
+            isAdmin={data?.settings?.admin == 1}
           />
         </ScrollView>
       </View>
     );
+  };
 
   const handleBackgroundPress = () => {
     setIsModalVisible(false);
@@ -2394,13 +2451,6 @@ const GroupChatScreen = ({ route }: { route: any }) => {
                 openEmojiSelector={openEmojiSelector}
               />
               {renderSelectedMessage()}
-              <OptionsMenu
-                selectedMessage={selectedMessage}
-                handleOptionPress={handleOptionPress}
-                messagePosition={messagePosition}
-                isGroup={true}
-                isAdmin={data?.settings?.admin == 1}
-              />
               <EmojiSelectorModal
                 visible={emojiSelectorVisible}
                 selectedMessage={selectedMessage}