Ver Fonte

reply/delete api/types/android toolbar fix/toolbar ui

Viktoriia há 8 meses atrás
pai
commit
e5eb70ddd4

+ 1 - 2
src/components/PageWrapper/styles.ts

@@ -1,10 +1,9 @@
-import { Platform, StatusBar, StyleSheet } from 'react-native';
+import { StyleSheet } from 'react-native';
 
 export const styles = StyleSheet.create({
   wrapper: {
     marginLeft: '5%',
     marginRight: '5%',
     height: '100%',
-    paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0
   }
 });

+ 11 - 1
src/modules/api/chat/chat-api.ts

@@ -55,6 +55,7 @@ export interface PostGetChatWithReturn extends ResponseType {
 }
 
 export interface PostSendMessage {
+  token: string;
   to_uid: number;
   text: string;
   reply_to_id?: number;
@@ -67,17 +68,25 @@ export interface PostMessagesReceivedOrRead {
 }
 
 export interface PostReactToMessage {
+  token: string;
   message_id: number;
   reaction: string;
   conversation_with_user: number;
 }
 
 export interface PostDeleteMessage {
+  token: string;
   message_id: number;
   conversation_with_user: number;
 }
 
+export interface PostDeleteChat {
+  token: string;
+  conversation_with_user: number;
+}
+
 export interface PostSetSettings {
+  token: string;
   value: 0 | 1;
   conversation_with_user: number;
 }
@@ -111,5 +120,6 @@ export const chatApi = {
   setPin: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_PIN, data),
   setArchive: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_ARCHIVE, data),
   setBlock: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_BLOCK, data),
-  setMute: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_MUTE, data)
+  setMute: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_MUTE, data),
+  deleteChat: (data: PostDeleteChat) => request.postForm<ResponseType>(API.DELETE_CHAT, data)
 };

+ 2 - 1
src/modules/api/chat/chat-query-keys.tsx

@@ -15,5 +15,6 @@ export const chatQueryKeys = {
   setPin: () => ['setPin'] as const,
   setArchive: () => ['setArchive'] as const,
   setBlock: () => ['setBlock'] as const,
-  setMute: () => ['setMute'] as const
+  setMute: () => ['setMute'] as const,
+  deleteChat: () => ['deleteChat'] as const
 };

+ 1 - 0
src/modules/api/chat/queries/index.ts

@@ -10,3 +10,4 @@ export * from './use-post-set-pin';
 export * from './use-post-set-archive';
 export * from './use-post-set-mute';
 export * from './use-post-set-block';
+export * from './use-post-delete-conversation';

+ 17 - 0
src/modules/api/chat/queries/use-post-delete-conversation.tsx

@@ -0,0 +1,17 @@
+import { useMutation } from '@tanstack/react-query';
+
+import { chatQueryKeys } from '../chat-query-keys';
+import { chatApi, type PostDeleteChat } from '../chat-api';
+
+import type { BaseAxiosError } from '../../../../types';
+import { ResponseType } from '@api/response-type';
+
+export const usePostDeleteChatMutation = () => {
+  return useMutation<ResponseType, BaseAxiosError, PostDeleteChat, ResponseType>({
+    mutationKey: chatQueryKeys.deleteChat(),
+    mutationFn: async (data) => {
+      const response = await chatApi.deleteChat(data);
+      return response.data;
+    }
+  });
+};

+ 216 - 305
src/screens/InAppScreens/MessagesScreen/ChatScreen/index.tsx

@@ -4,7 +4,6 @@ import {
   TouchableOpacity,
   Image,
   Modal,
-  StyleSheet,
   Text,
   FlatList,
   Dimensions,
@@ -19,7 +18,9 @@ import {
   IMessage,
   Send,
   BubbleProps,
-  Composer
+  Composer,
+  TimeProps,
+  MessageProps
 } from 'react-native-gifted-chat';
 import { MaterialCommunityIcons } from '@expo/vector-icons';
 import * as ImagePicker from 'expo-image-picker';
@@ -29,7 +30,7 @@ import {
   LongPressGestureHandler,
   Swipeable
 } from 'react-native-gesture-handler';
-import { Header, PageWrapper } from 'src/components';
+import { Header } from 'src/components';
 import { Colors } from 'src/theme';
 import { useFocusEffect, useNavigation } from '@react-navigation/native';
 import { Video } from 'expo-av';
@@ -37,7 +38,7 @@ import ChatMessageBox from '../Components/ChatMessageBox';
 import ReplyMessageBar from '../Components/ReplyMessageBar';
 import { useSharedValue, withTiming } from 'react-native-reanimated';
 import { BlurView } from 'expo-blur';
-import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
 import Clipboard from '@react-native-clipboard/clipboard';
 import { trigger } from 'react-native-haptic-feedback';
 import ReactModal from 'react-native-modal';
@@ -49,12 +50,13 @@ import {
   usePostReactToMessageMutation,
   usePostSendMessageMutation
 } from '@api/chat';
-import { Message } from '../types';
+import { CustomMessage, Message, Reaction } from '../types';
 import { API_HOST } from 'src/constants';
 import { getFontSize } from 'src/utils';
 import ReactionBar from '../Components/ReactionBar';
 import OptionsMenu from '../Components/OptionsMenu';
 import EmojiSelectorModal from '../Components/EmojiSelectorModal';
+import { styles } from './styles';
 
 const options = {
   enableVibrateFallback: true,
@@ -68,7 +70,7 @@ const ChatScreen = ({ route }: { route: any }) => {
   const currentUserId = storage.get('uid', StoreType.STRING) as number;
   const token = storage.get('token', StoreType.STRING) as string;
   const insets = useSafeAreaInsets();
-  const [messages, setMessages] = useState<IMessage[]>([]);
+  const [messages, setMessages] = useState<CustomMessage[]>([]);
   const { showActionSheetWithOptions } = useActionSheet();
   const navigation = useNavigation();
   const { data: chatData, isFetching, refetch } = usePostGetChatWithQuery(token, id, -1, -1, true);
@@ -76,11 +78,11 @@ const ChatScreen = ({ route }: { route: any }) => {
 
   const swipeableRowRef = useRef<Swipeable | null>(null);
   const messageContainerRef = useRef<FlatList<IMessage> | null>(null);
-  const [selectedMedia, setSelectedMedia] = useState(null);
+  const [selectedMedia, setSelectedMedia] = useState<any>(null);
 
-  const [replyMessage, setReplyMessage] = useState<IMessage | null>(null);
+  const [replyMessage, setReplyMessage] = useState<CustomMessage | null>(null);
 
-  const [selectedMessage, setSelectedMessage] = useState<IMessage | null>(null);
+  const [selectedMessage, setSelectedMessage] = useState<BubbleProps<CustomMessage> | null>(null);
   const [emojiSelectorVisible, setEmojiSelectorVisible] = useState(false);
   const [messagePosition, setMessagePosition] = useState<{
     x: number;
@@ -102,7 +104,7 @@ const ChatScreen = ({ route }: { route: any }) => {
   const flatList = useRef<FlatList | null>(null);
   const scrollY = useSharedValue(0);
 
-  const mapApiMessageToGiftedMessage = (message: Message): IMessage => {
+  const mapApiMessageToGiftedMessage = (message: Message): CustomMessage => {
     return {
       _id: message.id,
       text: message.text,
@@ -115,7 +117,8 @@ const ChatScreen = ({ route }: { route: any }) => {
         message.reply_to_id !== -1
           ? {
               text: message.reply_to.text,
-              id: message.reply_to.id
+              id: message.reply_to.id,
+              name: message.reply_to.sender === id ? name : 'Me'
             }
           : null,
       reactions: JSON.parse(message.reactions || '{}'),
@@ -194,7 +197,7 @@ const ChatScreen = ({ route }: { route: any }) => {
 
   const clearReplyMessage = () => setReplyMessage(null);
 
-  const handleLongPress = (message: IMessage, props) => {
+  const handleLongPress = (message: CustomMessage, props: BubbleProps<CustomMessage>) => {
     const messageRef = messageRefs.current[message._id];
 
     setSelectedMessage(props);
@@ -216,8 +219,8 @@ const ChatScreen = ({ route }: { route: any }) => {
           return;
         }
 
-        if (spaceBelow < 150) {
-          const extraShift = 150 - spaceBelow;
+        if (spaceBelow < 210) {
+          const extraShift = 210 - spaceBelow;
           finalY -= extraShift;
         }
 
@@ -226,7 +229,7 @@ const ChatScreen = ({ route }: { route: any }) => {
           finalY += extraShift;
         }
 
-        if (spaceBelow < 150 || spaceAbove < 50) {
+        if (spaceBelow < 210 || spaceAbove < 50) {
           const targetY = screenHeight / 2 - height / 2;
           scrollY.value = withTiming(finalY - finalY);
         }
@@ -253,21 +256,18 @@ const ChatScreen = ({ route }: { route: any }) => {
   };
 
   const handleReactionPress = (emoji: string, messageId: number) => {
-    if (emoji === '+') {
-      openEmojiSelector();
-    } else {
-      addReaction(messageId, emoji);
-    }
+    addReaction(messageId, emoji);
   };
 
   const handleDeleteMessage = (messageId: number) => {
     deleteMessage(
       {
+        token,
         message_id: messageId,
         conversation_with_user: id
       },
       {
-        onSuccess: (res) => {
+        onSuccess: () => {
           setMessages((prevMessages) => prevMessages.filter((msg) => msg._id !== messageId));
         }
       }
@@ -275,9 +275,11 @@ const ChatScreen = ({ route }: { route: any }) => {
   };
 
   const handleOptionPress = (option: string) => {
+    if (!selectedMessage) return;
+
     switch (option) {
       case 'reply':
-        setReplyMessage(selectedMessage?.currentMessage);
+        setReplyMessage(selectedMessage.currentMessage);
         setIsModalVisible(false);
         break;
       case 'copy':
@@ -286,7 +288,7 @@ const ChatScreen = ({ route }: { route: any }) => {
         Alert.alert('copied');
         break;
       case 'delete':
-        handleDeleteMessage(selectedMessage?.currentMessage?._id);
+        handleDeleteMessage(selectedMessage.currentMessage?._id);
         setIsModalVisible(false);
         break;
       case 'pin':
@@ -299,6 +301,90 @@ const ChatScreen = ({ route }: { route: any }) => {
     closeEmojiSelector();
   };
 
+  const renderTimeContainer = (time: TimeProps<CustomMessage>) => {
+    const createdAt = new Date(time.currentMessage.createdAt);
+
+    const formattedTime = createdAt.toLocaleTimeString([], {
+      hour: '2-digit',
+      minute: '2-digit',
+      hour12: true
+    });
+
+    const hasReactions =
+      time.currentMessage.reactions &&
+      Array.isArray(time.currentMessage.reactions) &&
+      time.currentMessage.reactions.length > 0;
+
+    return (
+      <View
+        style={{
+          flexDirection: 'row',
+          justifyContent: hasReactions ? 'space-between' : 'flex-end',
+          alignItems: 'center',
+          paddingHorizontal: 8,
+          paddingBottom: 6,
+          flexShrink: 1,
+          flexGrow: 1,
+          gap: 12
+        }}
+      >
+        {hasReactions && (
+          <View
+            style={[
+              {
+                flexDirection: 'row',
+                alignItems: 'center',
+                flexShrink: 0,
+                backgroundColor:
+                  time.position === 'left' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)',
+                borderRadius: 12,
+                paddingHorizontal: 6,
+                paddingVertical: 4,
+                gap: 6
+              }
+            ]}
+          >
+            {Object.entries(
+              (Array.isArray(time.currentMessage.reactions)
+                ? time.currentMessage.reactions
+                : []
+              ).reduce((acc: Record<string, number>, { reaction }: { reaction: string }) => {
+                acc[reaction] = (acc[reaction] || 0) + 1;
+                return acc;
+              }, {})
+            ).map(([emoji, count]) => (
+              <Text key={emoji} style={{}}>
+                {emoji}
+                {(count as number) > 1 ? ` ${count}` : ''}
+              </Text>
+            ))}
+          </View>
+        )}
+        <View
+          style={{
+            flexDirection: 'row',
+            gap: 4,
+            alignItems: 'center',
+            alignSelf: 'flex-end'
+          }}
+        >
+          <Text
+            style={{
+              color: Colors.LIGHT_GRAY,
+              fontSize: getFontSize(10),
+              fontWeight: '600',
+              paddingLeft: 8,
+              flexShrink: 0
+            }}
+          >
+            {formattedTime}
+          </Text>
+          {renderTicks(time.currentMessage)}
+        </View>
+      </View>
+    );
+  };
+
   const renderSelectedMessage = () =>
     selectedMessage && (
       <View
@@ -318,24 +404,11 @@ const ChatScreen = ({ route }: { route: any }) => {
               left: { backgroundColor: Colors.FILL_LIGHT }
             }}
             textStyle={{
-              right: { color: Colors.FILL_LIGHT },
+              right: { color: Colors.WHITE },
               left: { color: Colors.DARK_BLUE }
             }}
-            renderTicks={(message: IMessage) => {
-              return message.user._id === +currentUserId && message.received ? (
-                <View style={{ paddingRight: 8, bottom: 2 }}>
-                  <MaterialCommunityIcons name="check-all" size={16} color={Colors.WHITE} />
-                </View>
-              ) : message.user._id === +currentUserId && message.sent ? (
-                <View style={{ paddingRight: 8, bottom: 2 }}>
-                  <MaterialCommunityIcons name="check" size={16} color={Colors.WHITE} />
-                </View>
-              ) : message.user._id === +currentUserId && message.pending ? (
-                <View style={{ paddingRight: 8, bottom: 2 }}>
-                  <MaterialCommunityIcons name="check" size={16} color={Colors.WHITE} />
-                </View>
-              ) : null;
-            }}
+            renderTicks={() => null}
+            renderTime={renderTimeContainer}
           />
         </ScrollView>
       </View>
@@ -364,17 +437,19 @@ const ChatScreen = ({ route }: { route: any }) => {
   }, [refetch]);
 
   const onSend = useCallback(
-    (newMessages: IMessage[] = []) => {
+    (newMessages: CustomMessage[] = []) => {
       if (replyMessage) {
         newMessages[0].replyMessage = {
           text: replyMessage.text,
-          id: replyMessage._id
+          id: replyMessage._id,
+          name: replyMessage.user._id === id ? name : 'Me'
         };
       }
       const message = { ...newMessages[0], pending: true };
 
       sendMessage(
         {
+          token,
           to_uid: id,
           text: message.text,
           reply_to_id: replyMessage ? (replyMessage._id as number) : -1
@@ -460,17 +535,19 @@ const ChatScreen = ({ route }: { route: any }) => {
       }));
 
       setMessages((previousMessages) =>
-        GiftedChat.append(previousMessages, imageMessages as IMessage[])
+        GiftedChat.append(previousMessages, imageMessages as any[])
       );
     }
   };
 
-  const renderMessageVideo = (props: any) => {
+  const renderMessageVideo = (props: BubbleProps<CustomMessage>) => {
     const { currentMessage } = props;
 
     if (currentMessage.video) {
       return (
-        <LongPressGestureHandler onHandlerStateChange={(event) => handleLongPress(currentMessage)}>
+        <LongPressGestureHandler
+          onHandlerStateChange={(event) => handleLongPress(currentMessage, props)}
+        >
           <TouchableOpacity
             onPress={() => setSelectedMedia(currentMessage.video)}
             style={styles.mediaContainer}
@@ -489,10 +566,12 @@ const ChatScreen = ({ route }: { route: any }) => {
   };
 
   const addReaction = (messageId: number, reaction: string) => {
-    const updatedMessages = messages.map((msg) => {
+    const updatedMessages = messages.map((msg: any) => {
       if (msg._id === messageId) {
-        const updatedReactions = [
-          ...(Array.isArray(msg.reactions) ? msg.reactions : []),
+        const updatedReactions: Reaction[] = [
+          ...(Array.isArray(msg.reactions)
+            ? msg.reactions?.filter((r: Reaction) => r.uid !== +currentUserId)
+            : []),
           { datetime: new Date().toISOString(), reaction: reaction, uid: +currentUserId }
         ];
 
@@ -507,7 +586,7 @@ const ChatScreen = ({ route }: { route: any }) => {
     setMessages(updatedMessages);
 
     reactToMessage(
-      { message_id: messageId, reaction: reaction, conversation_with_user: id },
+      { token, message_id: messageId, reaction: reaction, conversation_with_user: id },
       {
         onSuccess: (res) => console.log('res', res),
         onError: (err) => console.log('err', err)
@@ -530,7 +609,7 @@ const ChatScreen = ({ route }: { route: any }) => {
     [replyMessage]
   );
 
-  const renderReplyMessageView = (props: BubbleProps<IMessage>) => {
+  const renderReplyMessageView = (props: BubbleProps<CustomMessage>) => {
     if (!props.currentMessage) {
       return null;
     }
@@ -542,15 +621,40 @@ const ChatScreen = ({ route }: { route: any }) => {
 
     return (
       <TouchableOpacity
-        style={styles.replyMessageContainer}
+        style={[
+          styles.replyMessageContainer,
+          {
+            backgroundColor:
+              currentMessage.user._id === id ? 'rgba(255, 255, 255, 0.7)' : 'rgba(0, 0, 0, 0.2)',
+            borderColor: currentMessage.user._id === id ? Colors.DARK_BLUE : Colors.WHITE
+          }
+        ]}
         onPress={() => {
           if (currentMessage?.replyMessage?.id) {
             scrollToMessage(currentMessage.replyMessage.id);
           }
         }}
       >
-        <Text>{currentMessage.replyMessage.text}</Text>
-        <View style={styles.replyMessageDivider} />
+        <View style={styles.replyContent}>
+          <Text
+            style={[
+              styles.replyAuthorName,
+              { color: currentMessage.user._id === id ? Colors.DARK_BLUE : Colors.WHITE }
+            ]}
+          >
+            {currentMessage.replyMessage.name}
+          </Text>
+
+          <Text
+            numberOfLines={1}
+            style={[
+              styles.replyMessageText,
+              { color: currentMessage.user._id === id ? Colors.DARK_BLUE : Colors.WHITE }
+            ]}
+          >
+            {currentMessage.replyMessage.text}
+          </Text>
+        </View>
       </TouchableOpacity>
     );
   };
@@ -592,12 +696,11 @@ const ChatScreen = ({ route }: { route: any }) => {
     );
   };
 
-  const renderTicks = (message: IMessage) => {
+  const renderTicks = (message: CustomMessage) => {
     if (message.user._id === id) return null;
 
     return message.received ? (
-      <View
-      >
+      <View>
         <MaterialCommunityIcons name="check-all" size={16} color={Colors.WHITE} />
       </View>
     ) : message.sent ? (
@@ -611,20 +714,27 @@ const ChatScreen = ({ route }: { route: any }) => {
     ) : null;
   };
 
-  const renderBubble = (props: any) => {
+  const renderBubble = (props: BubbleProps<CustomMessage>) => {
     const { currentMessage } = props;
 
     if (currentMessage.deleted) {
+      const text = currentMessage.text.length
+        ? props.currentMessage.text
+        : 'This message was deleted';
+
       return (
         <View>
           <Bubble
             {...props}
             renderTime={() => null}
-            currentMessage={{ ...props.currentMessage, text: 'This message was deleted' }}
+            currentMessage={{
+              ...props.currentMessage,
+              text: text
+            }}
             renderMessageText={() => (
               <View style={{ paddingHorizontal: 12, paddingVertical: 6 }}>
                 <Text style={{ color: Colors.LIGHT_GRAY, fontStyle: 'italic', fontSize: 12 }}>
-                  This message was deleted
+                  {text}
                 </Text>
               </View>
             )}
@@ -641,7 +751,7 @@ const ChatScreen = ({ route }: { route: any }) => {
                 color: Colors.DARK_BLUE
               },
               right: {
-                color: Colors.FILL_LIGHT
+                color: Colors.WHITE
               }
             }}
           />
@@ -694,88 +804,7 @@ const ChatScreen = ({ route }: { route: any }) => {
             }}
             onLongPress={() => handleLongPress(currentMessage, props)}
             renderTicks={() => null}
-            renderTime={(time) => {
-              const createdAt = new Date(time.currentMessage.createdAt);
-
-              const formattedTime = createdAt.toLocaleTimeString([], {
-                hour: '2-digit',
-                minute: '2-digit',
-                hour12: true
-              });
-
-              const hasReactions =
-                currentMessage.reactions &&
-                Array.isArray(currentMessage.reactions) &&
-                currentMessage.reactions.length > 0;
-
-              return (
-                <View
-                  style={{
-                    flexDirection: 'row',
-                    justifyContent: hasReactions ? 'space-between' : 'flex-end',
-                    alignItems: 'center',
-                    paddingHorizontal: 8,
-                    paddingBottom: 6,
-                    flexShrink: 1,
-                    flexGrow: 1,
-                    gap: 12
-                  }}
-                >
-                  {hasReactions && (
-                    <View
-                      style={[
-                        {
-                          flexDirection: 'row',
-                          alignItems: 'center',
-                          flexShrink: 0,
-                          backgroundColor:
-                            time.position === 'left'
-                              ? 'rgba(0, 0, 0, 0.2)'
-                              : 'rgba(255, 255, 255, 0.2)',
-                          borderRadius: 12,
-                          paddingHorizontal: 6,
-                          paddingVertical: 4,
-                          gap: 6
-                        }
-                      ]}
-                    >
-                      {Object.entries(
-                        currentMessage.reactions.reduce((acc, { reaction }) => {
-                          acc[reaction] = (acc[reaction] || 0) + 1;
-                          return acc;
-                        }, {})
-                      ).map(([emoji, count]) => (
-                        <Text key={emoji} style={{}}>
-                          {emoji}
-                          {(count as number) > 1 ? ` ${count}` : ''}
-                        </Text>
-                      ))}
-                    </View>
-                  )}
-                  <View
-                    style={{
-                      flexDirection: 'row',
-                      gap: 4,
-                      alignItems: 'center',
-                      alignSelf: 'flex-end'
-                    }}
-                  >
-                    <Text
-                      style={{
-                        color: Colors.LIGHT_GRAY,
-                        fontSize: getFontSize(10),
-                        fontWeight: '600',
-                        paddingLeft: 8,
-                        flexShrink: 0
-                      }}
-                    >
-                      {formattedTime}
-                    </Text>
-                    {renderTicks(currentMessage)}
-                  </View>
-                </View>
-              );
-            }}
+            renderTime={renderTimeContainer}
           />
         </View>
       </View>
@@ -791,11 +820,41 @@ const ChatScreen = ({ route }: { route: any }) => {
           // onPressActionButton={openActionSheet}
         />
       )}
+      containerStyle={{
+        backgroundColor: Colors.FILL_LIGHT
+      }}
     />
   );
 
+  const renderScrollToBottom = () => {
+    return (
+      <TouchableOpacity
+        style={{
+          position: 'absolute',
+          bottom: -20,
+          right: -20,
+          backgroundColor: Colors.DARK_BLUE,
+          borderRadius: 20,
+          padding: 8
+        }}
+        onPress={() => {
+          if (flatList.current) {
+            flatList.current.scrollToIndex({ index: 0, animated: true });
+          }
+        }}
+      >
+        <MaterialCommunityIcons name="chevron-down" size={24} color={Colors.WHITE} />
+      </TouchableOpacity>
+    );
+  };
+
   return (
-    <PageWrapper style={{ marginLeft: 0, marginRight: 0 }}>
+    <SafeAreaView
+      edges={['top']}
+      style={{
+        height: '100%'
+      }}
+    >
       <View style={{ paddingHorizontal: '5%' }}>
         <Header
           label={name}
@@ -836,7 +895,7 @@ const ChatScreen = ({ route }: { route: any }) => {
             }
           }}
           renderSystemMessage={renderSystemMessage}
-          onSend={(newMessages: IMessage[]) => onSend(newMessages)}
+          onSend={(newMessages: CustomMessage[]) => onSend(newMessages)}
           user={{ _id: +currentUserId, name: 'Me' }}
           renderBubble={renderBubble}
           renderMessageImage={renderMessageImage}
@@ -844,6 +903,7 @@ const ChatScreen = ({ route }: { route: any }) => {
           renderCustomView={renderReplyMessageView}
           isCustomViewBottom={false}
           messageContainerRef={messageContainerRef}
+          minComposerHeight={34}
           renderSend={(props) => (
             <View
               style={{
@@ -883,11 +943,11 @@ const ChatScreen = ({ route }: { route: any }) => {
               )}
             </View>
           )}
-          textInputProps={styles.composer}
+          textInputProps={{ ...styles.composer, selectionColor: Colors.LIGHT_GRAY }}
           placeholder=""
           renderMessage={(props) => (
             <ChatMessageBox
-              {...props}
+              {...(props as MessageProps<CustomMessage>)}
               updateRowRef={updateRowRef}
               setReplyOnSwipeOpen={setReplyMessage}
             />
@@ -895,7 +955,7 @@ const ChatScreen = ({ route }: { route: any }) => {
           renderChatFooter={() => (
             <ReplyMessageBar clearReply={clearReplyMessage} message={replyMessage} />
           )}
-          renderMessageVideo={renderMessageVideo}
+          // renderMessageVideo={renderMessageVideo}
           renderAvatar={null}
           maxComposerHeight={100}
           renderComposer={(props) => <Composer {...props} />}
@@ -903,6 +963,9 @@ const ChatScreen = ({ route }: { route: any }) => {
           shouldUpdateMessage={(props, nextProps) =>
             highlightedMessageId === nextProps.currentMessage._id
           }
+          scrollToBottom={true}
+          scrollToBottomComponent={renderScrollToBottom}
+          scrollToBottomStyle={{ backgroundColor: 'transparent' }}
           // inverted={true}
           // isTyping={true}
         />
@@ -966,166 +1029,14 @@ const ChatScreen = ({ route }: { route: any }) => {
           </BlurView>
         </ReactModal>
       </GestureHandlerRootView>
-    </PageWrapper>
+      <View
+        style={{
+          height: insets.bottom,
+          backgroundColor: Colors.FILL_LIGHT
+        }}
+      />
+    </SafeAreaView>
   );
 };
 
-const styles = StyleSheet.create({
-  unreadMessagesContainer: {
-    padding: 8,
-    backgroundColor: Colors.FILL_LIGHT,
-    alignItems: 'center'
-  },
-  unreadMessagesText: {
-    color: Colors.DARK_BLUE,
-    fontWeight: '700',
-    fontSize: getFontSize(12)
-  },
-  modalBackground: {
-    flex: 1
-  },
-  modalContent: {
-    backgroundColor: 'transparent'
-  },
-  mediaContainer: {
-    borderRadius: 10,
-    overflow: 'hidden',
-    margin: 5
-  },
-  chatMedia: {
-    width: 200,
-    height: 200,
-    borderRadius: 10
-  },
-  fullScreenMedia: {
-    width: '90%',
-    height: '80%'
-  },
-  audioContainer: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    justifyContent: 'space-between',
-    padding: 10,
-    backgroundColor: '#f1f1f1',
-    borderRadius: 10,
-    margin: 5
-  },
-  progressBar: {
-    flexDirection: 'row',
-    justifyContent: 'center',
-    alignItems: 'center'
-  },
-  bar: {
-    width: 5,
-    backgroundColor: 'gray',
-    marginHorizontal: 1
-  },
-  replyMessageContainer: {
-    padding: 8,
-    paddingBottom: 0
-  },
-  replyMessageDivider: {
-    borderBottomWidth: 1,
-    borderBottomColor: 'lightgrey',
-    paddingTop: 6
-  },
-  composer: {
-    backgroundColor: Colors.FILL_LIGHT,
-    borderRadius: 15,
-    borderWidth: 1,
-    borderColor: Colors.LIGHT_GRAY,
-    paddingHorizontal: 10,
-    fontSize: 16,
-    marginVertical: 4
-  },
-  container: {
-    flex: 1,
-    backgroundColor: 'white'
-  },
-  imageContainer: {
-    borderRadius: 10,
-    overflow: 'hidden',
-    margin: 5
-  },
-  chatImage: {
-    width: 200,
-    height: 200,
-    borderRadius: 10
-  },
-  replyContainer: {
-    backgroundColor: '#f1f1f1',
-    padding: 5,
-    marginBottom: 5,
-    borderRadius: 5
-  },
-  replyText: {
-    color: '#333',
-    fontStyle: 'italic'
-  },
-  reactionsContainer: {
-    height: 25,
-    paddingHorizontal: 6,
-    backgroundColor: Colors.FILL_LIGHT,
-    bottom: -30,
-    position: 'absolute',
-    alignItems: 'center',
-    justifyContent: 'center',
-    flexDirection: 'row',
-    gap: 6,
-    borderRadius: 15,
-    shadowColor: Colors.DARK_BLUE,
-    shadowOpacity: 0.2,
-    shadowOffset: { width: 0, height: 1 },
-    shadowRadius: 2,
-    elevation: 1
-  },
-  reactionText: {
-    fontSize: 16,
-    marginHorizontal: 5
-  },
-  reactionsBubble: {
-    backgroundColor: '#fff',
-    borderRadius: 20,
-    padding: 5,
-    flexDirection: 'row',
-    shadowColor: '#000',
-    shadowOpacity: 0.3,
-    shadowOffset: { width: 0, height: 2 },
-    shadowRadius: 5,
-    elevation: 5,
-    marginBottom: 10
-  },
-  replyInputContainer: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    backgroundColor: '#f1f1f1',
-    paddingHorizontal: 10,
-    paddingVertical: 5,
-    borderRadius: 10
-  },
-  replyInputText: {
-    flex: 1,
-    color: 'gray'
-  },
-  modalContainer: {
-    flex: 1,
-    backgroundColor: 'rgba(0, 0, 0, 0.9)',
-    justifyContent: 'center',
-    alignItems: 'center'
-  },
-  reactModalContainer: {
-    justifyContent: 'flex-end',
-    margin: 0
-  },
-  fullScreenImage: {
-    width: '90%',
-    height: '80%'
-  },
-  closeButton: {
-    position: 'absolute',
-    top: 40,
-    right: 20
-  }
-});
-
 export default ChatScreen;

+ 89 - 0
src/screens/InAppScreens/MessagesScreen/ChatScreen/styles.tsx

@@ -0,0 +1,89 @@
+import { StyleSheet } from 'react-native';
+import { Colors } from 'src/theme';
+import { getFontSize } from 'src/utils';
+
+export const styles = StyleSheet.create({
+  replyContent: {},
+  replyAuthorName: {
+    fontWeight: '600',
+    fontSize: getFontSize(13)
+  },
+  replyMessageText: {
+    fontWeight: '400',
+    fontSize: getFontSize(13)
+  },
+  unreadMessagesContainer: {
+    padding: 8,
+    backgroundColor: Colors.FILL_LIGHT,
+    alignItems: 'center'
+  },
+  unreadMessagesText: {
+    color: Colors.DARK_BLUE,
+    fontWeight: '700',
+    fontSize: getFontSize(12)
+  },
+  modalBackground: {
+    flex: 1
+  },
+  mediaContainer: {
+    borderRadius: 10,
+    overflow: 'hidden',
+    margin: 5
+  },
+  chatMedia: {
+    width: 200,
+    height: 200,
+    borderRadius: 10
+  },
+  fullScreenMedia: {
+    width: '90%',
+    height: '80%'
+  },
+  replyMessageContainer: {
+    borderLeftWidth: 2,
+    borderRadius: 2,
+    margin: 8,
+    marginBottom: 0,
+    padding: 4,
+    paddingLeft: 6,
+    gap: 2
+  },
+  composer: {
+    backgroundColor: Colors.WHITE,
+    borderRadius: 12,
+    borderWidth: 1,
+    borderColor: Colors.LIGHT_GRAY,
+    paddingHorizontal: 10,
+    fontSize: 16,
+    marginBottom: 5
+  },
+  container: {
+    flex: 1,
+    backgroundColor: 'white'
+  },
+  imageContainer: {
+    borderRadius: 10,
+    overflow: 'hidden',
+    margin: 5
+  },
+  chatImage: {
+    width: 200,
+    height: 200,
+    borderRadius: 10
+  },
+  modalContainer: {
+    flex: 1,
+    backgroundColor: 'rgba(0, 0, 0, 0.9)',
+    justifyContent: 'center',
+    alignItems: 'center'
+  },
+  reactModalContainer: {
+    justifyContent: 'flex-end',
+    margin: 0
+  },
+  closeButton: {
+    position: 'absolute',
+    top: 40,
+    right: 20
+  }
+});

+ 4 - 3
src/screens/InAppScreens/MessagesScreen/Components/ChatMessageBox.tsx

@@ -1,16 +1,17 @@
 import React from 'react';
 import { View, StyleSheet, Animated } from 'react-native';
 import { GestureHandlerRootView, Swipeable } from 'react-native-gesture-handler';
-import { IMessage, Message, MessageProps } from 'react-native-gifted-chat';
+import { Message, MessageProps } from 'react-native-gifted-chat';
 import { isSameDay, isSameUser } from 'react-native-gifted-chat/lib/utils';
 import { MaterialCommunityIcons } from '@expo/vector-icons';
 import { Colors } from 'src/theme';
 import { trigger } from 'react-native-haptic-feedback';
+import { CustomMessage } from '../types';
 
 type ChatMessageBoxProps = {
-  setReplyOnSwipeOpen: (message: IMessage) => void;
+  setReplyOnSwipeOpen: (message: CustomMessage) => void;
   updateRowRef: (ref: any) => void;
-} & MessageProps<IMessage>;
+} & MessageProps<CustomMessage>;
 
 const options = {
   enableVibrateFallback: true,

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

@@ -31,7 +31,7 @@ const OptionsMenu: React.FC<OptionsMenuProps> = ({
       style={[
         styles.optionsMenu,
         {
-          top: messagePosition.y + messagePosition.height + 10,
+          top: messagePosition.y + messagePosition.height + 8,
           left: messagePosition.isMine
             ? Dimensions.get('window').width - Dimensions.get('window').width * 0.75 - 8
             : messagePosition.x

+ 2 - 2
src/screens/InAppScreens/MessagesScreen/Components/ReactionBar.tsx

@@ -51,7 +51,7 @@ const ReactionBar: React.FC<ReactionBarProps> = ({
         </TouchableOpacity>
       ))}
       <TouchableOpacity onPress={() => openEmojiSelector()} style={styles.addReactionButton}>
-        <MaterialCommunityIcons name="plus" size={28} color={Colors.DARK_BLUE} />
+        <MaterialCommunityIcons name="plus" size={28} color={Colors.LIGHT_GRAY} />
       </TouchableOpacity>
     </Animated.View>
   );
@@ -82,7 +82,7 @@ const styles = StyleSheet.create({
     backgroundColor: Colors.FILL_LIGHT,
     borderRadius: 15,
     borderWidth: 1,
-    borderColor: Colors.BORDER_LIGHT,
+    borderColor: Colors.LIGHT_GRAY,
     width: 30,
     height: 30
   }

+ 2 - 2
src/screens/InAppScreens/MessagesScreen/Components/ReplyMessageBar.tsx

@@ -48,8 +48,8 @@ const ReplyMessageBar = ({ clearReply, message }: ReplyMessageBarProps) => {
         >
           {message.user.name}
         </Text>
-        <Text style={{ color: Colors.DARK_BLUE, paddingLeft: 10, paddingTop: 5 }}>
-          {message.text.length > 40 ? `${message.text.substring(0, 40)}...` : message.text}
+        <Text style={{ color: Colors.DARK_BLUE, paddingLeft: 10, paddingTop: 5 }} numberOfLines={1}>
+          {message.text}
         </Text>
       </View>
 

+ 4 - 0
src/screens/InAppScreens/MessagesScreen/Components/SwipeableRow.tsx

@@ -14,6 +14,7 @@ import { usePostSetArchiveMutation, usePostSetPinMutation } from '@api/chat';
 
 interface AppleStyleSwipeableRowProps extends PropsWithChildren<unknown> {
   chat: ChatProps;
+  token: string;
   onRowOpen: (ref: any) => void;
   refetch: () => void;
 }
@@ -21,6 +22,7 @@ interface AppleStyleSwipeableRowProps extends PropsWithChildren<unknown> {
 const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({
   children,
   chat,
+  token,
   onRowOpen,
   refetch
 }) => {
@@ -56,6 +58,7 @@ const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({
         });
       } else {
         await archiveChat({
+          token,
           value: chat.archive === 1 ? 0 : 1,
           conversation_with_user: chat.id
         });
@@ -91,6 +94,7 @@ const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({
     const pressHandler = async () => {
       close();
       await pinChat({
+        token,
         value: chat.pin === 1 ? 0 : 1,
         conversation_with_user: chat.id
       });

+ 1 - 0
src/screens/InAppScreens/MessagesScreen/index.tsx

@@ -157,6 +157,7 @@ const MessagesScreen = () => {
           pin: item.pin,
           archive: item.archive
         }}
+        token={token}
         onRowOpen={handleRowOpen}
         refetch={refetch}
       >

+ 20 - 0
src/screens/InAppScreens/MessagesScreen/types.ts

@@ -1,3 +1,5 @@
+import { IMessage } from 'react-native-gifted-chat';
+
 export type Chat = {
   uid: number;
   name: string;
@@ -43,3 +45,21 @@ export type MessageSimple = {
 export type Message = MessageSimple & {
   reply_to: MessageSimple;
 };
+
+export interface CustomMessage extends IMessage {
+  _id: number;
+  replyMessage?: {
+    text: string;
+    id: number;
+    name: string;
+  } | null;
+  deleted: boolean;
+  attachment: string | null;
+  reactions: Reaction[] | {};
+}
+
+export type Reaction = {
+  datetime: Date;
+  reaction: string;
+  uid: number;
+};

+ 1 - 4
src/screens/InAppScreens/TravelsScreen/SuggestSeriesScreen/index.tsx

@@ -3,9 +3,7 @@ import {
   SafeAreaView,
   View,
   Text,
-  Platform,
   TouchableOpacity,
-  StatusBar,
   KeyboardAvoidingView,
   TouchableWithoutFeedback,
   Keyboard,
@@ -185,8 +183,7 @@ const SuggestSeriesScreen = ({ navigation }: { navigation: any }) => {
   return (
     <SafeAreaView
       style={{
-        height: '100%',
-        paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0
+        height: '100%'
       }}
     >
       <View style={styles.wrapper}>

+ 4 - 2
src/types/api.ts

@@ -136,7 +136,8 @@ export enum API_ENDPOINT {
   SET_PIN = 'set-pin',
   SET_ARCHIVE = 'set-archive',
   SET_BLOCK = 'set-block',
-  SET_MUTE = 'set-mute'
+  SET_MUTE = 'set-mute',
+  DELETE_CHAT = 'delete-chat'
 }
 
 export enum API {
@@ -249,7 +250,8 @@ export enum API {
   SET_PIN = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_PIN}`,
   SET_ARCHIVE = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_ARCHIVE}`,
   SET_BLOCK = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_BLOCK}`,
-  SET_MUTE = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_MUTE}`
+  SET_MUTE = `${API_ROUTE.CHAT}/${API_ENDPOINT.SET_MUTE}`,
+  DELETE_CHAT = `${API_ROUTE.CHAT}/${API_ENDPOINT.DELETE_CHAT}`
 }
 
 export type BaseAxiosError = AxiosError;