Viktoriia 9 months ago
parent
commit
d5db43171b

+ 3 - 0
assets/icons/messages/unpin.svg

@@ -0,0 +1,3 @@
+<svg width="15" height="26" viewBox="0 0 15 26" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.33061 1.24179C5.282 0.830789 4.90635 0.539108 4.49534 0.587721C4.08433 0.636335 3.79265 1.01199 3.84127 1.42299L6.66969 24.7575C6.71831 25.1685 7.09396 25.4602 7.50496 25.4116C7.91597 25.363 8.20765 24.9873 8.15904 24.5763L7.4453 18.6874C7.67069 18.8952 7.98005 18.988 8.28278 18.9371C8.59877 18.8863 8.87498 18.6852 9.0164 18.398L9.0606 18.3096C9.67269 17.0876 9.7677 15.711 9.39647 14.4603L12.4194 10.9336L13.0712 11.5854C13.4623 11.9766 14.0943 11.9766 14.4854 11.5854C14.8766 11.1943 14.8766 10.5623 14.4854 10.1712L8.82858 4.51437C8.43746 4.12325 7.80548 4.12325 7.41436 4.51437C7.02325 4.90549 7.02325 5.53747 7.41436 5.92859L8.06623 6.58045L6.17472 8.20238L5.33061 1.24179ZM3.98711 15.2293L3.29326 9.3912C2.41379 9.34701 1.51444 9.52599 0.690221 9.93921L0.601833 9.9834C0.312361 10.127 0.113487 10.401 0.0626636 10.717C0.0118406 11.033 0.115697 11.3578 0.343297 11.5854L3.98711 15.2293ZM2.46462 15.121L0.343297 17.2423C-0.0478218 17.6334 -0.0478218 18.2654 0.343297 18.6565C0.734416 19.0476 1.36639 19.0476 1.75751 18.6565L3.87883 16.5352L2.46462 15.121Z" fill="#0F3F4F"/>
+</svg>

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

@@ -76,6 +76,11 @@ export interface PostDeleteMessage {
   conversation_with_user: number;
 }
 
+export interface PostSetSettings {
+  value: 0 | 1;
+  conversation_with_user: number;
+}
+
 export const chatApi = {
   searchUsers: (token: string, search: string) =>
     request.postForm<PostSearchUsersReturn>(API.SEARCH_USERS, { token, search }),
@@ -101,5 +106,9 @@ export const chatApi = {
   reactToMessage: (data: PostReactToMessage) =>
     request.postForm<ResponseType>(API.REACT_TO_MESSAGE, data),
   deleteMessage: (data: PostDeleteMessage) =>
-    request.postForm<ResponseType>(API.DELETE_MESSAGE, data)
+    request.postForm<ResponseType>(API.DELETE_MESSAGE, data),
+  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)
 };

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

@@ -11,5 +11,9 @@ export const chatQueryKeys = {
   messagesReceived: () => ['messagesReceived'] as const,
   messagesRead: () => ['messagesRead'] as const,
   reactToMessage: () => ['reactToMessage'] as const,
-  deleteMessage: () => ['deleteMessage'] as const
+  deleteMessage: () => ['deleteMessage'] as const,
+  setPin: () => ['setPin'] as const,
+  setArchive: () => ['setArchive'] as const,
+  setBlock: () => ['setBlock'] as const,
+  setMute: () => ['setMute'] as const
 };

+ 17 - 0
src/modules/api/chat/queries/use-post-set-archive.tsx

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

+ 17 - 0
src/modules/api/chat/queries/use-post-set-block.tsx

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

+ 17 - 0
src/modules/api/chat/queries/use-post-set-mute.tsx

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

+ 17 - 0
src/modules/api/chat/queries/use-post-set-pin.tsx

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

+ 4 - 5
src/screens/InAppScreens/MessagesScreen/ChatScreen/index.tsx

@@ -372,9 +372,10 @@ const ChatScreen = ({ route }: { route: any }) => {
 
   const renderSelectedMessage = () =>
     selectedMessage && (
-      <Animated.View
+      <View
         style={{
           maxHeight: '80%',
+          width: messagePosition?.width,
           position: 'absolute',
           top: messagePosition?.y,
           left: messagePosition?.x
@@ -383,7 +384,6 @@ const ChatScreen = ({ route }: { route: any }) => {
         <ScrollView>
           <Bubble
             {...selectedMessage}
-            currentMessage={selectedMessage?.currentMessage}
             wrapperStyle={{
               right: { backgroundColor: Colors.DARK_BLUE },
               left: { backgroundColor: Colors.FILL_LIGHT }
@@ -409,7 +409,7 @@ const ChatScreen = ({ route }: { route: any }) => {
             }}
           />
         </ScrollView>
-      </Animated.View>
+      </View>
     );
 
   const handleBackgroundPress = () => {
@@ -657,7 +657,6 @@ const ChatScreen = ({ route }: { route: any }) => {
         collapsable={false}
       >
         <Bubble
-          key={`${currentMessage._id}`}
           {...props}
           wrapperStyle={{
             right: {
@@ -691,7 +690,7 @@ const ChatScreen = ({ route }: { route: any }) => {
               </View>
             ) : null;
           }}
-          renderQuickReplies={(quickReplies: QuickRepliesProps<IMessage>) => null}
+          // renderQuickReplies={(quickReplies: QuickRepliesProps<IMessage>) => null}
           // renderQuickReplies={(quickReplies: QuickRepliesProps<IMessage>) => (
           //   <View style={{height: 20, width: 20, backgroundColor: 'green', bottom: 0, right: 0}}>
           //     <Text>{currentMessage.quickReplies.values[0].title}</Text>

+ 21 - 5
src/screens/InAppScreens/MessagesScreen/Components/SwipeableRow.tsx

@@ -8,16 +8,26 @@ import { SheetManager } from 'react-native-actions-sheet';
 import PinIcon from 'assets/icons/messages/pin.svg';
 import ArchiveIcon from 'assets/icons/messages/archive.svg';
 import DotsIcon from 'assets/icons/messages/dots.svg';
+import UnpinIcon from 'assets/icons/messages/unpin.svg';
 import { ChatProps } from '../types';
+import { usePostSetPinMutation } from '@api/chat/queries/use-post-set-pin';
 
 interface AppleStyleSwipeableRowProps extends PropsWithChildren<unknown> {
   chat: ChatProps;
   onRowOpen: (ref: any) => void;
+  refetch: () => void;
 }
 
-const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({ children, chat, onRowOpen }) => {
+const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({
+  children,
+  chat,
+  onRowOpen,
+  refetch
+}) => {
   const swipeableRow = useRef<Swipeable>(null);
 
+  const { mutateAsync: pinChat } = usePostSetPinMutation();
+
   const close = () => {
     swipeableRow.current?.close();
   };
@@ -71,15 +81,21 @@ const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({ children, chat, o
       outputRange: [-x, 0]
     });
 
-    const pressHandler = () => {
+    const pressHandler = async () => {
       close();
-      alert(text);
+      await pinChat(
+        {
+          value: chat.pin === 1 ? 0 : 1,
+          conversation_with_user: chat.id
+        }
+      );
+      refetch();
     };
 
     return (
       <Animated.View style={{ flex: 1, transform: [{ translateX: trans }] }}>
         <RectButton style={[styles.rightAction, { backgroundColor: color }]} onPress={pressHandler}>
-          <PinIcon height={18} width={18} />
+          {chat.pin === 1 ? <UnpinIcon width={18} /> : <PinIcon width={18} />}
           <Text style={styles.actionText}>{text}</Text>
         </RectButton>
       </Animated.View>
@@ -105,7 +121,7 @@ const SwipeableRow: React.FC<AppleStyleSwipeableRowProps> = ({ children, chat, o
         flexDirection: 'row'
       }}
     >
-      {renderLeftAction('Pin', Colors.FILL_LIGHT, 84, progress)}
+      {renderLeftAction(chat.pin === 1 ? 'Unpin' : 'Pin', Colors.FILL_LIGHT, 84, progress)}
     </View>
   );
 

+ 9 - 10
src/screens/InAppScreens/MessagesScreen/index.tsx

@@ -30,6 +30,8 @@ import { usePostGetChatsListQuery } from '@api/chat';
 import moment from 'moment';
 import { Chat } from './types';
 
+import PinIcon from 'assets/icons/messages/pin.svg';
+
 type Routes = {
   key: 'all' | 'unread' | 'archived';
   title: string;
@@ -88,12 +90,14 @@ const MessagesScreen = () => {
       setFilteredChats(
         chats
           .filter((chat: Chat) => chat.unread_count > 0)
-          .sort((a: Chat, b: Chat) => (b.pin === 1 ? 1 : -1))
+          .sort((a: Chat, b: Chat) => b.pin - a.pin || b.pin_order - a.pin_order)
       );
     } else if (index === 2) {
       setFilteredChats([]);
     } else {
-      setFilteredChats(chats.sort((a: Chat, b: Chat) => (b.pin === 1 ? 1 : -1)));
+      setFilteredChats(
+        chats.sort((a: Chat, b: Chat) => b.pin - a.pin || b.pin_order - a.pin_order)
+      );
     }
   };
 
@@ -101,13 +105,6 @@ const MessagesScreen = () => {
     filterChatsByTab();
   }, [index, chats]);
 
-  const handlePinChat = (id: number) => {
-    const updatedChats = chats.map((chat: Chat) =>
-      chat.uid === id ? { ...chat, pin: !chat.pin } : chat
-    );
-    setChats(updatedChats as any);
-  };
-
   const handleDeleteChat = (id: number) => {
     const updatedChats = chats.filter((chat: Chat) => chat.uid !== id);
     setChats(updatedChats);
@@ -153,8 +150,9 @@ const MessagesScreen = () => {
   const renderChatItem = ({ item }: { item: Chat }) => {
     return (
       <SwipeableRow
-        chat={{ id: item.uid, name: item.name, avatar: item.avatar }}
+        chat={{ id: item.uid, name: item.name, avatar: item.avatar, pin: item.pin }}
         onRowOpen={handleRowOpen}
+        refetch={refetch}
       >
         <TouchableHighlight
           activeOpacity={0.8}
@@ -180,6 +178,7 @@ const MessagesScreen = () => {
                 <Text style={styles.chatName}>{item.name}</Text>
 
                 <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
+                  {item.pin === 1 ? <PinIcon height={12} fill={Colors.DARK_BLUE} /> : null}
                   {item.sent_by !== item.uid && item.status === 3 ? (
                     <ReadIcon fill={Colors.DARK_BLUE} />
                   ) : item.sent_by !== item.uid && (item.status === 2 || item.status === 1) ? (

+ 2 - 1
src/screens/InAppScreens/MessagesScreen/types.ts

@@ -5,7 +5,7 @@ export type Chat = {
   short: string;
   sent_by: number;
   updated: Date;
-  status: 1 | 2 | 3;
+  status: 1 | 2 | 3 | 4;
   unread_count: number;
   last_message_id: number;
   pin: 0 | 1;
@@ -20,6 +20,7 @@ export type ChatProps = {
   id: number;
   name: string;
   avatar: string | null;
+  pin: 0 | 1;
 };
 
 export type MessageSimple = {

+ 10 - 2
src/types/api.ts

@@ -132,7 +132,11 @@ export enum API_ENDPOINT {
   MESSAGES_RECEIVED = 'messages-received',
   MESSAGES_READ = 'messages-read',
   REACT_TO_MESSAGE = 'react-to-message',
-  DELETE_MESSAGE = 'delete-message'
+  DELETE_MESSAGE = 'delete-message',
+  SET_PIN = 'set-pin',
+  SET_ARCHIVE = 'set-archive',
+  SET_BLOCK = 'set-block',
+  SET_MUTE = 'set-mute'
 }
 
 export enum API {
@@ -241,7 +245,11 @@ export enum API {
   MESSAGES_RECEIVED = `${API_ROUTE.CHAT}/${API_ENDPOINT.MESSAGES_RECEIVED}`,
   MESSAGES_READ = `${API_ROUTE.CHAT}/${API_ENDPOINT.MESSAGES_READ}`,
   REACT_TO_MESSAGE = `${API_ROUTE.CHAT}/${API_ENDPOINT.REACT_TO_MESSAGE}`,
-  DELETE_MESSAGE = `${API_ROUTE.CHAT}/${API_ENDPOINT.DELETE_MESSAGE}`
+  DELETE_MESSAGE = `${API_ROUTE.CHAT}/${API_ENDPOINT.DELETE_MESSAGE}`,
+  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}`
 }
 
 export type BaseAxiosError = AxiosError;