import React, { useState, useEffect, useRef, useCallback } from 'react';
import {
View,
Text,
TouchableOpacity,
Image,
Platform,
TouchableHighlight,
} from 'react-native';
import {
AvatarWithInitials,
HorizontalTabView,
Input,
PageWrapper,
WarningModal
} from 'src/components';
import { NAVIGATION_PAGES } from 'src/types';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
import AddChatIcon from 'assets/icons/messages/chat-plus.svg';
import { API_HOST, WEBSOCKET_URL } from 'src/constants';
import { Colors } from 'src/theme';
import SwipeableRow from './Components/SwipeableRow';
import { FlashList } from '@shopify/flash-list';
import ReadIcon from 'assets/icons/messages/check-read.svg';
import UnreadIcon from 'assets/icons/messages/check-unread.svg';
import SearchModal from './Components/SearchUsersModal';
import { SheetManager } from 'react-native-actions-sheet';
import MoreModal from './Components/MoreModal';
import SearchIcon from 'assets/icons/search.svg';
import { storage, StoreType } from 'src/storage';
import { usePostGetBlockedQuery, usePostGetChatsListQuery } from '@api/chat';
import { Blocked, Chat } from './types';
import PinIcon from 'assets/icons/messages/pin.svg';
import { formatDate } from './utils';
import { routes } from './constants';
import { styles } from './styles';
import { useChatStore } from 'src/stores/chatStore';
import BellSlashIcon from 'assets/icons/messages/bell-slash.svg';
import BanIcon from 'assets/icons/messages/ban.svg';
import SwipeableBlockedRow from './Components/SwipeableBlockedRow';
import { useMessagesStore } from 'src/stores/unreadMessagesStore';
const TypingIndicator = () => {
const [dots, setDots] = useState('');
useEffect(() => {
const interval = setInterval(() => {
setDots((prevDots) => {
if (prevDots.length >= 3) {
return '';
}
return prevDots + '.';
});
}, 500);
return () => clearInterval(interval);
}, []);
return Typing{dots};
};
const MessagesScreen = () => {
const navigation = useNavigation();
const token = storage.get('token', StoreType.STRING) as string;
const [chats, setChats] = useState([]);
const [index, setIndex] = useState(0);
const { data: chatsData, refetch } = usePostGetChatsListQuery(token, index === 2 ? 1 : 0, true);
const { data: blockedData, refetch: refetchBlocked } = usePostGetBlockedQuery(token, true);
const [blocked, setBlocked] = useState([]);
const updateUnreadMessagesCount = useMessagesStore((state) => state.updateUnreadMessagesCount);
const [filteredChats, setFilteredChats] = useState<{
all: Chat[];
unread: Chat[];
archived: Chat[];
blocked: Blocked[];
}>({ all: [], unread: [], archived: [], blocked: [] });
const [search, setSearch] = useState('');
const openRowRef = useRef(null);
const { isWarningModalVisible, setIsWarningModalVisible } = useChatStore();
const [typingUsers, setTypingUsers] = useState<{ [key: string]: boolean }>({});
const socket = useRef(null);
const initializeSocket = () => {
if (socket.current) {
socket.current.close();
}
setTimeout(() => {
socket.current = new WebSocket(WEBSOCKET_URL);
socket.current.onopen = () => {
socket.current?.send(JSON.stringify({ token }));
};
socket.current.onmessage = (event) => {
const data = JSON.parse(event.data);
handleWebSocketMessage(data);
};
socket.current.onclose = () => {
console.log('WebSocket connection closed');
};
}, 500);
};
const handleWebSocketMessage = (data: any) => {
switch (data.action) {
case 'new_message':
refetch();
break;
case 'is_typing':
if (data.conversation_with) {
setTypingUsers((prev) => ({
...prev,
[data.conversation_with]: true
}));
}
break;
case 'stopped_typing':
if (data.conversation_with) {
setTypingUsers((prev) => ({
...prev,
[data.conversation_with]: false
}));
}
break;
default:
break;
}
};
const handleRowOpen = (ref: any) => {
if (openRowRef.current && openRowRef.current !== ref) {
openRowRef.current.close();
}
openRowRef.current = ref;
};
useFocusEffect(() => {
navigation.getParent()?.setOptions({
tabBarStyle: {
display: 'flex',
...Platform.select({
android: {
height: 58
}
})
}
});
});
useEffect(() => {
if (chatsData && chatsData.conversations) {
setChats(chatsData.conversations);
}
}, [chatsData]);
useEffect(() => {
if (blockedData && blockedData.blocked) {
setBlocked(blockedData.blocked);
}
}, [blockedData]);
useFocusEffect(
useCallback(() => {
refetch();
initializeSocket();
updateUnreadMessagesCount();
return () => {
if (socket.current) {
socket.current.close();
socket.current = null;
}
};
}, [token])
);
const filterChatsByTab = () => {
let filteredList = chats;
if (index === 3) {
setFilteredChats((prev) => ({ ...prev, blocked }));
return;
}
if (index === 1) {
filteredList = chats.filter((chat) => chat.unread_count > 0);
}
filteredList.sort((a, b) => {
if (b.pin - a.pin !== 0) {
return b.pin - a.pin;
}
if (b.pin_order - a.pin_order !== 0) {
return b.pin_order - a.pin_order;
}
return new Date(b.updated).getTime() - new Date(a.updated).getTime();
});
setFilteredChats((prev) => ({ ...prev, [routes[index].key]: filteredList }));
};
useEffect(() => {
filterChatsByTab();
}, [chats, index, blocked]);
const searchFilter = (text: string) => {
if (text) {
const newData =
chats?.filter((item: Chat) => {
const itemData = item.short ? item.short.toLowerCase() : ''.toLowerCase();
const textData = text.toLowerCase();
return itemData.indexOf(textData) > -1;
}) ?? [];
setFilteredChats((prev) => ({ ...prev, [routes[index].key]: newData }));
setSearch(text);
} else {
filterChatsByTab();
setSearch(text);
}
};
const renderChatItem = ({ item }: { item: Chat }) => {
return (
navigation.navigate(
...([
NAVIGATION_PAGES.CHAT,
{
id: item.uid,
name: item.name,
avatar: item.avatar
}
] as never)
)
}
underlayColor={Colors.FILL_LIGHT}
>
{item.avatar ? (
) : (
n[0])
.join('') ?? ''
}
flag={API_HOST + item?.flag}
size={54}
/>
)}
{item.name}
{item.pin === 1 ? : null}
{item.muted === 1 ? : null}
{item.sent_by !== item.uid && item.status === 3 ? (
) : item.sent_by !== item.uid && (item.status === 2 || item.status === 1) ? (
) : null}
{formatDate(item.updated)}
{typingUsers[item.uid] ? (
) : (
{item.short}
)}
{item.unread_count > 0 ? (
{item.unread_count > 99 ? '99+' : item.unread_count}
) : null}
);
};
const renderBlockedItem = ({ item }: { item: Blocked }) => {
return (
navigation.navigate(
...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.id }] as never)
)
}
underlayColor={Colors.FILL_LIGHT}
>
{item.avatar ? (
) : (
)}
{item.first_name + ' ' + item.last_name}
);
};
return (
Messages
SheetManager.show('search-modal')}
style={{ width: 30, alignItems: 'flex-end' }}
>
{/*
searchFilter(text)}
value={search}
icon={}
height={38}
/>
*/}
route.key === 'blocked' ? (
`${item.id}-${index}`}
estimatedItemSize={50}
/>
) : (
`${item.uid}-${index}`}
estimatedItemSize={78}
extraData={typingUsers}
/>
)
}
/>
setIsWarningModalVisible(null)}
title={isWarningModalVisible?.title}
message={isWarningModalVisible?.message}
action={isWarningModalVisible?.action}
/>
);
};
export default MessagesScreen;