import { AddLinkEventTracker, ILinkEventTracker, RemoveFriendComposer, RemoveLinkEventTracker, SendRoomInviteComposer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { LocalizeText, MessengerFriend, SendMessageComposer, filterFriendsByCategory } from '../../../../api'; import { Button, Flex, NitroCardAccordionSetView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common'; import { useFriends } from '../../../../hooks'; import { FriendsCategoryManagerView } from './FriendsCategoryManagerView'; import { FriendsRemoveConfirmationView } from './FriendsListRemoveConfirmationView'; import { FriendsRoomInviteView } from './FriendsListRoomInviteView'; import { FriendsSearchView } from './FriendsListSearchView'; import { FriendsListGroupChipsView } from './FriendsListGroupChipsView'; import { FriendsListGroupView } from './friends-list-group/FriendsListGroupView'; import { FriendsListRequestView } from './friends-list-request/FriendsListRequestView'; export const FriendsListView: FC<{}> = props => { const [ isVisible, setIsVisible ] = useState(false); const [ selectedFriendsIds, setSelectedFriendsIds ] = useState([]); const [ showRoomInvite, setShowRoomInvite ] = useState(false); const [ showRemoveFriendsConfirmation, setShowRemoveFriendsConfirmation ] = useState(false); const [ selectedCategoryId, setSelectedCategoryId ] = useState(0); const [ showCategoryManager, setShowCategoryManager ] = useState(false); const { friends = [], onlineFriends = [], offlineFriends = [], requests = [], requestFriend = null, settings = null } = useFriends(); const categories = settings?.categories ?? []; const filteredOnlineFriends = filterFriendsByCategory(onlineFriends, selectedCategoryId); const filteredOfflineFriends = filterFriendsByCategory(offlineFriends, selectedCategoryId); const removeFriendsText = useMemo(() => { if(!selectedFriendsIds || !selectedFriendsIds.length) return ''; const userNames: string[] = []; for(const userId of selectedFriendsIds) { let existingFriend: MessengerFriend = onlineFriends.find(f => f.id === userId); if(!existingFriend) existingFriend = offlineFriends.find(f => f.id === userId); if(!existingFriend) continue; userNames.push(existingFriend.name); } return LocalizeText('friendlist.removefriendconfirm.userlist', [ 'user_names' ], [ userNames.join('\n') ]); }, [ offlineFriends, onlineFriends, selectedFriendsIds ]); const selectFriend = useCallback((userId: number) => { if(userId < 0) return; setSelectedFriendsIds(prevValue => { const newValue = [ ...prevValue ]; const existingUserIdIndex: number = newValue.indexOf(userId); if(existingUserIdIndex > -1) { newValue.splice(existingUserIdIndex, 1); } else { newValue.push(userId); } return newValue; }); }, [ setSelectedFriendsIds ]); const toggleSelectFriends = useCallback((friendIds: number[]) => { if(!friendIds.length) return; setSelectedFriendsIds(prevValue => { const allSelected = friendIds.every(friendId => (prevValue.indexOf(friendId) >= 0)); if(allSelected) return prevValue.filter(friendId => (friendIds.indexOf(friendId) === -1)); const nextValue = [ ...prevValue ]; for(const friendId of friendIds) { if(nextValue.indexOf(friendId) === -1) nextValue.push(friendId); } return nextValue; }); }, []); const sendRoomInvite = (message: string) => { if(!selectedFriendsIds.length || !message || !message.length || (message.length > 255)) return; SendMessageComposer(new SendRoomInviteComposer(message, selectedFriendsIds)); setShowRoomInvite(false); }; const removeSelectedFriends = () => { if(selectedFriendsIds.length === 0) return; setSelectedFriendsIds(prevValue => { SendMessageComposer(new RemoveFriendComposer(...prevValue)); return []; }); setShowRemoveFriendsConfirmation(false); }; useEffect(() => { const linkTracker: ILinkEventTracker = { linkReceived: (url: string) => { const parts = url.split('/'); if(parts.length < 2) return; switch(parts[1]) { case 'show': setIsVisible(true); return; case 'hide': setIsVisible(false); return; case 'toggle': setIsVisible(prevValue => !prevValue); return; case 'request': if(parts.length < 4) return; requestFriend(parseInt(parts[2]), parts[3]); } }, eventUrlPrefix: 'friends/' }; AddLinkEventTracker(linkTracker); return () => RemoveLinkEventTracker(linkTracker); }, [ requestFriend ]); if(!isVisible) return null; return ( <> setIsVisible(false) } /> setShowCategoryManager(true) } /> { event.stopPropagation(); toggleSelectFriends(filteredOnlineFriends.map(friend => friend.id)); } }> { filteredOnlineFriends.length && filteredOnlineFriends.every(friend => (selectedFriendsIds.indexOf(friend.id) >= 0)) ? LocalizeText('friendlist.unselect_all') : LocalizeText('friendlist.select_all') } { event.stopPropagation(); toggleSelectFriends(filteredOfflineFriends.map(friend => friend.id)); } }> { filteredOfflineFriends.length && filteredOfflineFriends.every(friend => (selectedFriendsIds.indexOf(friend.id) >= 0)) ? LocalizeText('friendlist.unselect_all') : LocalizeText('friendlist.select_all') } { selectedFriendsIds && selectedFriendsIds.length > 0 && } { showRoomInvite && setShowRoomInvite(false) } /> } { showRemoveFriendsConfirmation && setShowRemoveFriendsConfirmation(false) } /> } { showCategoryManager && setShowCategoryManager(false) } /> } ); };