import React, { useState, useCallback, useEffect, useRef } from 'react'; import { View, TouchableOpacity, Image, Modal, Text, FlatList, Dimensions, Alert, ScrollView, Linking, ActivityIndicator, AppState, AppStateStatus, TextInput, Animated } from 'react-native'; import { GiftedChat, Bubble, InputToolbar, IMessage, Send, BubbleProps, Composer, TimeProps, MessageProps, Actions } from 'react-native-gifted-chat'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { GestureHandlerRootView, Swipeable } from 'react-native-gesture-handler'; import { AvatarWithInitials, Header, WarningModal } from 'src/components'; import { Colors } from 'src/theme'; import { useFocusEffect, useNavigation } from '@react-navigation/native'; import { ResizeMode, Video, Audio, AVPlaybackStatus } from 'expo-av'; import ChatMessageBox from '../Components/ChatMessageBox'; import ReplyMessageBar from '../Components/ReplyMessageBar'; import { useSharedValue, withTiming } from 'react-native-reanimated'; import { BlurView } from 'expo-blur'; 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'; import { storage, StoreType } from 'src/storage'; import { usePostDeleteMessageMutation, usePostGetChatWithQuery, usePostMessagesReadMutation, usePostReactToMessageMutation, usePostSendMessageMutation } from '@api/chat'; import { CustomMessage, Message, Reaction } from '../types'; import { API_HOST, WEBSOCKET_URL } from 'src/constants'; import ReactionBar from '../Components/ReactionBar'; import OptionsMenu from '../Components/OptionsMenu'; import EmojiSelectorModal from '../Components/EmojiSelectorModal'; import { styles } from './styles'; import SendIcon from 'assets/icons/messages/send.svg'; import { SheetManager } from 'react-native-actions-sheet'; import { NAVIGATION_PAGES } from 'src/types'; import { usePushNotification } from 'src/contexts/PushNotificationContext'; import ReactionsListModal from '../Components/ReactionsListModal'; import { dismissChatNotifications } from '../utils'; import { useMessagesStore } from 'src/stores/unreadMessagesStore'; import * as Location from 'expo-location'; import FileViewer from 'react-native-file-viewer'; import * as FileSystem from 'expo-file-system'; import ImageView from 'better-react-native-image-viewing'; import BanIcon from 'assets/icons/messages/ban.svg'; import AttachmentsModal from '../Components/AttachmentsModal'; import ChatOptionsBlock from '../Components/ChatOptionsBlock'; const options = { enableVibrateFallback: true, ignoreAndroidSystemSettings: false }; const reactionEmojis = ['👍', '❤️', '😂', '😮', '😭']; const ChatScreen = ({ route }: { route: any }) => { const token = storage.get('token', StoreType.STRING) as string; const { id, name, avatar, userType }: { id: number; name: string; avatar: string | null; userType: 'normal' | 'not_exist' | 'blocked'; } = route.params; const userName = userType === 'blocked' ? 'Account is blocked' : userType === 'not_exist' ? 'Account does not exist' : name; const currentUserId = storage.get('uid', StoreType.STRING) as number; const insets = useSafeAreaInsets(); const [messages, setMessages] = useState(); const navigation = useNavigation(); const [prevThenMessageId, setPrevThenMessageId] = useState(-1); const { data: chatData, refetch, isFetching } = usePostGetChatWithQuery(token, id, 50, prevThenMessageId, true); const { mutateAsync: sendMessage } = usePostSendMessageMutation(); const swipeableRowRef = useRef(null); const messageContainerRef = useRef | null>(null); const [selectedMedia, setSelectedMedia] = useState(null); const [replyMessage, setReplyMessage] = useState(null); const [modalInfo, setModalInfo] = useState({ visible: false, type: 'confirm', message: '', action: () => {}, buttonTitle: '', title: '' }); const [selectedMessage, setSelectedMessage] = useState | null>(null); const [emojiSelectorVisible, setEmojiSelectorVisible] = useState(false); const [messagePosition, setMessagePosition] = useState<{ x: number; y: number; width: number; height: number; isMine: boolean; } | null>(null); const [isModalVisible, setIsModalVisible] = useState(false); const [unreadMessageIndex, setUnreadMessageIndex] = useState(null); const { mutateAsync: markMessagesAsRead } = usePostMessagesReadMutation(); const { mutateAsync: deleteMessage } = usePostDeleteMessageMutation(); const { mutateAsync: reactToMessage } = usePostReactToMessageMutation(); const [highlightedMessageId, setHighlightedMessageId] = useState(null); const [isRerendering, setIsRerendering] = useState(false); const [isTyping, setIsTyping] = useState(false); const messageRefs = useRef<{ [key: string]: any }>({}); const flatList = useRef(null); const scrollY = useSharedValue(0); const { isSubscribed } = usePushNotification(); const [isLoadingEarlier, setIsLoadingEarlier] = useState(false); const [hasMoreMessages, setHasMoreMessages] = useState(true); const updateUnreadMessagesCount = useMessagesStore((state) => state.updateUnreadMessagesCount); const [isPlaying, setIsPlaying] = useState(false); const [isBuffering, setIsBuffering] = useState(false); const videoRef = useRef