Browse Source

message status modal

Viktoriia 4 months ago
parent
commit
9abacbfe8a

+ 0 - 1
package.json

@@ -72,7 +72,6 @@
     "react-native-haptic-feedback": "^2.3.2",
     "react-native-image-viewing": "^0.2.2",
     "react-native-keyboard-aware-scroll-view": "^0.9.5",
-    "react-native-keyboard-controller": "^1.16.4",
     "react-native-linear-gradient": "^2.8.3",
     "react-native-map-clustering": "^3.4.2",
     "react-native-maps": "1.14.0",

+ 211 - 0
src/screens/InAppScreens/MessagesScreen/Components/GroupStatusModal.tsx

@@ -0,0 +1,211 @@
+import { usePostGetGroupMessageStatusQuery } from '@api/chat';
+import React, { useEffect, useState } from 'react';
+import {
+  StyleSheet,
+  View,
+  Text,
+  Image,
+  TouchableOpacity,
+  ScrollView,
+  Platform
+} from 'react-native';
+import ActionSheet, { SheetManager } from 'react-native-actions-sheet';
+import { AvatarWithInitials } from 'src/components';
+import { API_HOST } from 'src/constants';
+import { storage, StoreType } from 'src/storage';
+import { FlashList } from '@shopify/flash-list';
+import { Colors } from 'src/theme';
+import { getFontSize } from 'src/utils';
+import moment from 'moment';
+import { NAVIGATION_PAGES } from 'src/types';
+import { useNavigation } from '@react-navigation/native';
+
+const GroupStatusModal = () => {
+  const navigation = useNavigation();
+  const uid = (storage.get('uid', StoreType.STRING) as number) ?? 0;
+  const token = storage.get('token', StoreType.STRING) as string;
+  const [groupToken, setGroupToken] = useState<string | null>(null);
+  const [messageId, setMessageId] = useState<number | null>(null);
+  const [payloadData, setPayloadData] = useState<any>(null);
+  const { data } = usePostGetGroupMessageStatusQuery(
+    token,
+    groupToken as string,
+    messageId as number,
+    groupToken && messageId ? true : false
+  );
+  const [read, setRead] = useState<any[]>([]);
+  const [received, setReceived] = useState<any[]>([]);
+
+  const handleSheetOpen = (payload: any) => {
+    setGroupToken(payload.groupToken);
+    setMessageId(payload.messageId);
+    setPayloadData(payload);
+  };
+
+  useEffect(() => {
+    if (data && data.status) {
+      setRead(data.status?.filter((status) => status.status === 3 && status.uid !== +uid) ?? []);
+      setReceived(
+        data.status?.filter((status) => status.status === 2 && status.uid !== +uid) ?? []
+      );
+    }
+  }, [data]);
+
+  const formatDate = (utcDateString: string): string => {
+    const date = moment.utc(utcDateString).local();
+
+    if (date.isSame(moment(), 'day')) {
+      return `today ${date.format('HH:mm')}`;
+    } else if (date.isSame(moment().subtract(1, 'day'), 'day')) {
+      return `yesterday ${date.format('HH:mm')}`;
+    } else {
+      return date.format('DD.MM HH:mm');
+    }
+  };
+
+  const renderUserItem = ({ item }: { item: any }) => {
+    return (
+      <TouchableOpacity
+        style={styles.userItem}
+        onPress={() => {
+          SheetManager.hide('group-status');
+          navigation.navigate(
+            ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.uid }] as never)
+          );
+        }}
+      >
+        {item.avatar ? (
+          <Image source={{ uri: API_HOST + item.avatar }} style={styles.avatar} />
+        ) : (
+          <AvatarWithInitials
+            text={item.name?.split(' ')[0][0] + item.name?.split(' ')[1][0]}
+            flag={API_HOST + item?.flag1}
+            size={36}
+            fontSize={16}
+            borderColor={Colors.LIGHT_GRAY}
+            borderWidth={1}
+          />
+        )}
+        <View style={styles.userDetails}>
+          <Text style={styles.userName}>{item.name}</Text>
+        </View>
+        <Text style={[styles.text, { fontSize: getFontSize(12) }]}>
+          {formatDate(item.datetime)}
+        </Text>
+      </TouchableOpacity>
+    );
+  };
+
+  return (
+    <ActionSheet
+      id="group-status"
+      gestureEnabled={Platform.OS === 'ios'}
+      containerStyle={{
+        borderTopLeftRadius: 15,
+        borderTopRightRadius: 15,
+        height: '70%',
+        padding: 10,
+        paddingBottom: 0
+      }}
+      isModal={false}
+      defaultOverlayOpacity={0.5}
+      onBeforeShow={(sheetRef) => {
+        const payload = sheetRef || null;
+        handleSheetOpen(payload);
+      }}
+      onBeforeClose={() => {
+        payloadData?.setInsetsColor(Colors.FILL_LIGHT);
+      }}
+      onClose={() => {
+        setGroupToken(null);
+        setMessageId(null);
+      }}
+    >
+      <ScrollView
+        style={{ height: '100%', width: '100%', paddingTop: 8 }}
+        contentContainerStyle={{ gap: 8 }}
+        showsVerticalScrollIndicator={false}
+      >
+        {read.length > 0 ? (
+          <>
+            <Text style={styles.text}>Read by:</Text>
+            <FlashList
+              viewabilityConfig={{
+                waitForInteraction: true,
+                itemVisiblePercentThreshold: 50,
+                minimumViewTime: 1000
+              }}
+              data={read || []}
+              renderItem={renderUserItem}
+              keyExtractor={(item) => item.uid.toString()}
+              estimatedItemSize={100}
+              showsVerticalScrollIndicator={false}
+              contentContainerStyle={{ paddingBottom: 8 }}
+              scrollEnabled={false}
+            />
+          </>
+        ) : null}
+
+        {received.length > 0 ? (
+          <>
+            <Text style={styles.text}>Delivered to:</Text>
+            <FlashList
+              viewabilityConfig={{
+                waitForInteraction: true,
+                itemVisiblePercentThreshold: 50,
+                minimumViewTime: 1000
+              }}
+              data={received || []}
+              renderItem={renderUserItem}
+              keyExtractor={(item) => item.uid.toString()}
+              estimatedItemSize={100}
+              showsVerticalScrollIndicator={false}
+              contentContainerStyle={{ paddingBottom: 16 }}
+              scrollEnabled={false}
+            />
+          </>
+        ) : null}
+      </ScrollView>
+    </ActionSheet>
+  );
+};
+
+const styles = StyleSheet.create({
+  userDetails: {
+    flex: 1
+  },
+  userName: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(14),
+    fontFamily: 'montserrat-700'
+  },
+  userSubtitle: {
+    color: Colors.DARK_BLUE,
+    fontSize: 14,
+    fontFamily: 'montserrat-500'
+  },
+  userItem: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    paddingVertical: 8,
+    paddingHorizontal: 12,
+    backgroundColor: Colors.FILL_LIGHT,
+    gap: 8,
+    borderRadius: 8,
+    marginBottom: 6
+  },
+  avatar: {
+    width: 36,
+    height: 36,
+    borderRadius: 18,
+    borderWidth: 1,
+    borderColor: Colors.LIGHT_GRAY
+  },
+  text: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(13),
+    fontWeight: '600'
+  }
+});
+
+export default GroupStatusModal;

+ 9 - 1
src/screens/InAppScreens/MessagesScreen/Components/OptionsMenu.tsx

@@ -16,12 +16,14 @@ interface OptionsMenuProps {
   messagePosition: MessagePosition | null;
   selectedMessage: any;
   handleOptionPress: (option: string) => void;
+  isGroup?: boolean;
 }
 
 const OptionsMenu: React.FC<OptionsMenuProps> = ({
   messagePosition,
   selectedMessage,
-  handleOptionPress
+  handleOptionPress,
+  isGroup
 }) =>
   selectedMessage &&
   messagePosition && (
@@ -61,6 +63,12 @@ const OptionsMenu: React.FC<OptionsMenuProps> = ({
         <Text style={styles.optionText}>Delete</Text>
         <MaterialCommunityIcons name="delete" size={20} color={Colors.DARK_BLUE} />
       </TouchableOpacity>
+      {isGroup && (
+        <TouchableOpacity style={styles.optionButton} onPress={() => handleOptionPress('info')}>
+          <Text style={styles.optionText}>Info</Text>
+          <MaterialCommunityIcons name="information-outline" size={20} color={Colors.DARK_BLUE} />
+        </TouchableOpacity>
+      )}
       {/* <TouchableOpacity style={styles.optionButton} onPress={() => handleOptionPress('pin')}>
         <Text style={styles.optionText}>Pin message</Text>
         <MaterialCommunityIcons name="pin" size={20} color={Colors.DARK_BLUE} />

+ 16 - 1
src/screens/InAppScreens/MessagesScreen/GroupChatScreen/index.tsx

@@ -76,6 +76,7 @@ import RenderMessageVideo from '../Components/renderMessageVideo';
 import MessageLocation from '../Components/MessageLocation';
 import GroupIcon from 'assets/icons/messages/group-chat.svg';
 import { CACHED_ATTACHMENTS_DIR } from 'src/constants/constants';
+import GroupStatusModal from '../Components/GroupStatusModal';
 
 const options = {
   enableVibrateFallback: true,
@@ -158,6 +159,7 @@ const GroupChatScreen = ({ route }: { route: any }) => {
   const [isLoadingEarlier, setIsLoadingEarlier] = useState(false);
   const [hasMoreMessages, setHasMoreMessages] = useState(true);
   const updateUnreadMessagesCount = useMessagesStore((state) => state.updateUnreadMessagesCount);
+  const [insetsColor, setInsetsColor] = useState(Colors.FILL_LIGHT);
 
   const appState = useRef(AppState.currentState);
   const textInputRef = useRef<TextInput>(null);
@@ -1184,6 +1186,17 @@ const GroupChatScreen = ({ route }: { route: any }) => {
         downloadFileToDevice(selectedMessage.currentMessage);
         setIsModalVisible(false);
         break;
+      case 'info':
+        SheetManager.show('group-status', {
+          payload: {
+            messageId: selectedMessage.currentMessage._id,
+            groupToken: group_token,
+            setInsetsColor
+          } as any
+        });
+        setIsModalVisible(false);
+        setInsetsColor(Colors.WHITE);
+        break;
       default:
         break;
     }
@@ -1994,6 +2007,7 @@ const GroupChatScreen = ({ route }: { route: any }) => {
                 selectedMessage={selectedMessage}
                 handleOptionPress={handleOptionPress}
                 messagePosition={messagePosition}
+                isGroup={selectedMessage?.currentMessage?.user._id === +currentUserId}
               />
               <EmojiSelectorModal
                 visible={emojiSelectorVisible}
@@ -2019,11 +2033,12 @@ const GroupChatScreen = ({ route }: { route: any }) => {
         />
         <AttachmentsModal />
         <ReactionsListModal />
+        <GroupStatusModal />
       </GestureHandlerRootView>
       <View
         style={{
           height: insets.bottom,
-          backgroundColor: Colors.FILL_LIGHT
+          backgroundColor: insetsColor
         }}
       />
     </SafeAreaView>