nitro-react/src/components/friends/FriendsView.tsx

372 lines
13 KiB
TypeScript
Raw Normal View History

2021-11-17 09:46:34 +01:00
import { AcceptFriendMessageComposer, FriendListFragmentEvent, FriendListUpdateEvent, FriendParser, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitComposer, MessengerInitEvent, NewFriendRequestEvent, RequestFriendComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
import { DeclineFriendMessageComposer } from '@nitrots/nitro-renderer/src';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
2021-06-23 05:22:32 +02:00
import { createPortal } from 'react-dom';
2022-03-03 10:11:31 +01:00
import { GetRoomSession, SendMessageComposer } from '../../api';
import { FriendEnteredRoomEvent, FriendListContentEvent, FriendRequestEvent, FriendsAcceptFriendRequestEvent, FriendsDeclineFriendRequestEvent, FriendsEvent, FriendsRequestCountEvent, FriendsSendFriendRequestEvent } from '../../events';
import { DispatchUiEvent, UseMessageEventHook, UseRoomEngineEvent, UseUiEvent } from '../../hooks';
2021-11-17 09:46:34 +01:00
import { FriendsHelper } from './common/FriendsHelper';
import { MessengerFriend } from './common/MessengerFriend';
import { MessengerRequest } from './common/MessengerRequest';
import { MessengerSettings } from './common/MessengerSettings';
2022-03-01 17:32:50 +01:00
import { FriendsContextProvider } from './FriendsContext';
2021-06-23 05:22:32 +02:00
import { FriendBarView } from './views/friend-bar/FriendBarView';
2021-09-16 06:37:17 +02:00
import { FriendsListView } from './views/friends-list/FriendsListView';
import { FriendsMessengerView } from './views/messenger/FriendsMessengerView';
2021-04-22 08:54:49 +02:00
2021-09-15 18:26:51 +02:00
export const FriendsView: FC<{}> = props =>
2021-04-22 08:54:49 +02:00
{
2021-06-23 05:22:32 +02:00
const [ isReady, setIsReady ] = useState(false);
2021-11-17 09:46:34 +01:00
const [ isVisible, setIsVisible ] = useState(false);
const [ friends, setFriends ] = useState<MessengerFriend[]>([]);
const [ requests, setRequests ] = useState<MessengerRequest[]>([]);
const [ settings, setSettings ] = useState<MessengerSettings>(null);
const [ sentRequests, setSentRequests ] = useState<number[]>([]);
2021-09-16 06:37:17 +02:00
2021-11-17 09:46:34 +01:00
const getFriend = useCallback((userId: number) =>
2021-09-16 06:37:17 +02:00
{
2021-11-17 09:46:34 +01:00
for(const friend of friends)
{
if(friend.id === userId) return friend;
}
return null;
}, [ friends ]);
FriendsHelper.getFriend = getFriend;
const canRequestFriend = useCallback((userId: number) =>
{
if(getFriend(userId)) return false;
if(sentRequests.indexOf(userId) >= 0) return false;
return true;
}, [ sentRequests, getFriend ]);
FriendsHelper.canRequestFriend = canRequestFriend;
const requestFriend = useCallback((userId: number, userName: string) =>
{
if(sentRequests.indexOf(userId) >= 0) return true;
if(!canRequestFriend(userId)) return false;
setSentRequests(prevValue =>
{
const newSentRequests = [ ...prevValue ];
newSentRequests.push(userId);
return newSentRequests;
});
2022-03-03 10:11:31 +01:00
SendMessageComposer(new RequestFriendComposer(userName));
2021-11-17 09:46:34 +01:00
}, [ sentRequests, canRequestFriend ]);
const acceptFriend = useCallback((userId: number) =>
{
setRequests(prevValue =>
{
2021-11-19 18:31:43 +01:00
const newRequests: MessengerRequest[] = [ ...prevValue ];
2021-11-17 09:46:34 +01:00
2021-11-19 18:31:43 +01:00
const index = newRequests.findIndex(request => (request.requesterUserId === userId));
if(index >= 0)
2021-11-17 09:46:34 +01:00
{
2022-03-03 10:11:31 +01:00
SendMessageComposer(new AcceptFriendMessageComposer(newRequests[index].id));
2021-11-19 18:31:43 +01:00
2022-03-03 10:11:31 +01:00
DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.ACCEPTED, userId));
2021-11-19 18:31:43 +01:00
newRequests.splice(index, 1);
2021-11-17 09:46:34 +01:00
}
return newRequests;
});
2021-09-16 06:37:17 +02:00
}, []);
2021-04-22 08:54:49 +02:00
2021-11-17 09:46:34 +01:00
const declineFriend = useCallback((userId: number, declineAll: boolean = false) =>
2021-09-16 06:37:17 +02:00
{
2021-11-17 09:46:34 +01:00
setRequests(prevValue =>
{
if(declineAll)
{
2022-03-03 10:11:31 +01:00
SendMessageComposer(new DeclineFriendMessageComposer(true));
2021-09-16 06:37:17 +02:00
2022-03-03 10:11:31 +01:00
for(const request of prevValue) DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, request.requesterUserId));
2021-11-19 18:31:43 +01:00
2021-11-17 09:46:34 +01:00
return [];
}
else
{
2021-11-19 18:31:43 +01:00
const newRequests: MessengerRequest[] = [ ...prevValue ];
2021-11-17 09:46:34 +01:00
2021-11-19 18:31:43 +01:00
const index = newRequests.findIndex(request => (request.requesterUserId === userId));
if(index >= 0)
2021-11-17 09:46:34 +01:00
{
2022-03-03 10:11:31 +01:00
SendMessageComposer(new DeclineFriendMessageComposer(false, newRequests[index].id));
2021-11-19 18:31:43 +01:00
2022-03-03 10:11:31 +01:00
DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, userId));
2021-11-19 18:31:43 +01:00
newRequests.splice(index, 1);
2021-11-17 09:46:34 +01:00
}
return newRequests;
}
});
}, []);
const onMessengerInitEvent = useCallback((event: MessengerInitEvent) =>
{
const parser = event.getParser();
setSettings(new MessengerSettings(
parser.userFriendLimit,
parser.normalFriendLimit,
parser.extendedFriendLimit,
parser.categories));
2022-03-03 10:11:31 +01:00
SendMessageComposer(new GetFriendRequestsComposer());
2021-11-17 09:46:34 +01:00
}, []);
2022-03-03 10:11:31 +01:00
UseMessageEventHook(MessengerInitEvent, onMessengerInitEvent);
2021-11-17 09:46:34 +01:00
const onFriendsFragmentEvent = useCallback((event: FriendListFragmentEvent) =>
{
const parser = event.getParser();
setFriends(prevValue =>
{
const newFriends = [ ...prevValue ];
for(const friend of parser.fragment)
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
const newFriend = new MessengerFriend();
newFriend.populate(friend);
if(index > -1) newFriends[index] = newFriend;
else newFriends.push(newFriend);
}
return newFriends;
});
}, []);
2022-03-03 10:11:31 +01:00
UseMessageEventHook(FriendListFragmentEvent, onFriendsFragmentEvent);
2021-11-17 09:46:34 +01:00
const onFriendsUpdateEvent = useCallback((event: FriendListUpdateEvent) =>
{
const parser = event.getParser();
setFriends(prevValue =>
{
const newFriends = [ ...prevValue ];
const processUpdate = (friend: FriendParser) =>
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
if(index === -1)
{
const newFriend = new MessengerFriend();
newFriend.populate(friend);
newFriends.unshift(newFriend);
}
else
{
newFriends[index].populate(friend);
}
}
for(const friend of parser.addedFriends) processUpdate(friend);
for(const friend of parser.updatedFriends) processUpdate(friend);
for(const removedFriendId of parser.removedFriendIds)
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === removedFriendId));
if(index > -1) newFriends.splice(index);
}
return newFriends;
});
}, []);
2022-03-03 10:11:31 +01:00
UseMessageEventHook(FriendListUpdateEvent, onFriendsUpdateEvent);
2021-11-17 09:46:34 +01:00
const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) =>
{
const parser = event.getParser();
setRequests(prevValue =>
{
const newRequests = [ ...prevValue ];
for(const request of parser.requests)
{
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
if(index > 0) continue;
const newRequest = new MessengerRequest();
newRequest.populate(request);
newRequests.push(newRequest);
}
return newRequests;
});
}, []);
2022-03-03 10:11:31 +01:00
UseMessageEventHook(FriendRequestsEvent, onFriendRequestsEvent);
2021-11-17 09:46:34 +01:00
const onNewFriendRequestEvent = useCallback((event: NewFriendRequestEvent) =>
{
const parser = event.getParser();
const request = parser.request;
setRequests(prevValue =>
{
const newRequests = [ ...prevValue ];
2021-11-19 18:31:43 +01:00
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
2021-11-17 09:46:34 +01:00
2021-11-19 18:31:43 +01:00
if(index === -1)
{
const newRequest = new MessengerRequest();
newRequest.populate(request);
newRequests.push(newRequest);
}
2021-11-17 09:46:34 +01:00
return newRequests;
});
}, []);
2022-03-03 10:11:31 +01:00
UseMessageEventHook(NewFriendRequestEvent, onNewFriendRequestEvent);
2021-09-16 06:37:17 +02:00
const onFriendsEvent = useCallback((event: FriendsEvent) =>
2021-04-22 08:54:49 +02:00
{
switch(event.type)
{
2021-09-16 06:37:17 +02:00
case FriendsEvent.SHOW_FRIEND_LIST:
2021-11-17 09:46:34 +01:00
setIsVisible(true);
2021-09-16 06:37:17 +02:00
return;
case FriendsEvent.TOGGLE_FRIEND_LIST:
2021-11-17 09:46:34 +01:00
setIsVisible(value => !value);
2021-09-16 06:37:17 +02:00
return;
case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST:
const requestEvent = (event as FriendsSendFriendRequestEvent);
2021-11-17 09:46:34 +01:00
requestFriend(requestEvent.userId, requestEvent.userName);
2021-07-08 10:25:57 +02:00
return;
2021-09-16 06:37:17 +02:00
case FriendsEvent.REQUEST_FRIEND_LIST:
2022-03-03 10:11:31 +01:00
DispatchUiEvent(new FriendListContentEvent(friends));
2021-08-18 22:50:15 +02:00
return;
2021-04-22 08:54:49 +02:00
}
2021-11-17 09:46:34 +01:00
}, [ friends, requestFriend ]);
2021-04-22 08:54:49 +02:00
2022-03-03 10:11:31 +01:00
UseUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent);
UseUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent);
UseUiEvent(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendsEvent);
UseUiEvent(FriendsEvent.REQUEST_FRIEND_LIST, onFriendsEvent);
2021-04-22 08:54:49 +02:00
2021-11-19 18:31:43 +01:00
const onFriendsAcceptFriendRequestEvent = useCallback((event: FriendsAcceptFriendRequestEvent) =>
{
acceptFriend(event.requestId);
}, [ acceptFriend ]);
2022-03-03 10:11:31 +01:00
UseUiEvent(FriendsAcceptFriendRequestEvent.ACCEPT_FRIEND_REQUEST, onFriendsAcceptFriendRequestEvent);
2021-11-19 18:31:43 +01:00
const onFriendsDeclineFriendRequestEvent = useCallback((event: FriendsDeclineFriendRequestEvent) =>
{
declineFriend(event.requestId);
}, [ declineFriend ]);
2022-03-03 10:11:31 +01:00
UseUiEvent(FriendsDeclineFriendRequestEvent.DECLINE_FRIEND_REQUEST, onFriendsDeclineFriendRequestEvent);
2021-11-19 18:31:43 +01:00
2021-07-07 09:56:11 +02:00
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) =>
{
const roomSession = GetRoomSession();
if(!roomSession) return;
if(event.category !== RoomObjectCategory.UNIT) return;
const userData = roomSession.userDataManager.getUserDataByIndex(event.objectId);
2021-07-08 10:25:57 +02:00
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
2021-07-07 09:56:11 +02:00
2021-11-17 09:46:34 +01:00
const friend = getFriend(userData.webID);
2021-07-07 09:56:11 +02:00
if(!friend) return;
2022-03-03 10:11:31 +01:00
DispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type));
2021-11-17 09:46:34 +01:00
}, [ getFriend ]);
2021-07-07 09:56:11 +02:00
2022-03-03 10:11:31 +01:00
UseRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent);
2021-07-07 09:56:11 +02:00
2021-09-08 06:03:48 +02:00
const onlineFriends = useMemo(() =>
{
2021-11-17 09:46:34 +01:00
const onlineFriends = friends.filter(friend => friend.online);
onlineFriends.sort((a, b) =>
{
if( a.name < b.name ) return -1;
if( a.name > b.name ) return 1;
return 0;
});
return onlineFriends;
2021-09-08 06:03:48 +02:00
}, [ friends ]);
const offlineFriends = useMemo(() =>
{
2021-11-17 09:46:34 +01:00
const offlineFriends = friends.filter(friend => !friend.online);
offlineFriends.sort((a, b) =>
{
if( a.name < b.name ) return -1;
if( a.name > b.name ) return 1;
return 0;
});
return offlineFriends;
2021-09-08 06:03:48 +02:00
}, [ friends ]);
2021-11-17 09:46:34 +01:00
useEffect(() =>
{
2022-03-03 10:11:31 +01:00
SendMessageComposer(new MessengerInitComposer());
2021-11-17 09:46:34 +01:00
}, []);
useEffect(() =>
{
if(!settings) return;
setIsReady(true);
}, [ settings ]);
useEffect(() =>
{
2022-03-03 10:11:31 +01:00
DispatchUiEvent(new FriendsRequestCountEvent(requests.length));
2021-11-17 09:46:34 +01:00
}, [ requests ]);
2021-04-22 08:54:49 +02:00
return (
2021-11-18 09:40:51 +01:00
<FriendsContextProvider value={ { friends, requests, settings, canRequestFriend, requestFriend, acceptFriend, declineFriend } }>
2021-11-17 09:46:34 +01:00
{ isReady &&
createPortal(<FriendBarView onlineFriends={ onlineFriends } />, document.getElementById('toolbar-friend-bar-container')) }
{ isVisible &&
<FriendsListView onlineFriends={ onlineFriends } offlineFriends={ offlineFriends } friendRequests={ requests } onCloseClick={ () => setIsVisible(false) } /> }
2021-09-17 13:15:53 +02:00
<FriendsMessengerView />
2021-09-16 06:37:17 +02:00
</FriendsContextProvider>
2021-04-22 08:54:49 +02:00
);
}