mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-10-25 04:03:05 +02:00
375 lines
13 KiB
TypeScript
375 lines
13 KiB
TypeScript
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';
|
|
import { createPortal } from 'react-dom';
|
|
import { GetRoomSession } from '../../api';
|
|
import { FriendEnteredRoomEvent, FriendListContentEvent, FriendRequestEvent, FriendsAcceptFriendRequestEvent, FriendsDeclineFriendRequestEvent, FriendsEvent, FriendsRequestCountEvent } from '../../events';
|
|
import { FriendsSendFriendRequestEvent } from '../../events/friends/FriendsSendFriendRequestEvent';
|
|
import { CreateMessageHook, useRoomEngineEvent } from '../../hooks';
|
|
import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event';
|
|
import { SendMessageHook } from '../../hooks/messages/message-event';
|
|
import { FriendsHelper } from './common/FriendsHelper';
|
|
import { MessengerFriend } from './common/MessengerFriend';
|
|
import { MessengerRequest } from './common/MessengerRequest';
|
|
import { MessengerSettings } from './common/MessengerSettings';
|
|
import { FriendsContextProvider } from './context/FriendsContext';
|
|
import { FriendBarView } from './views/friend-bar/FriendBarView';
|
|
import { FriendsListView } from './views/friends-list/FriendsListView';
|
|
import { FriendsMessengerView } from './views/messenger/FriendsMessengerView';
|
|
|
|
export const FriendsView: FC<{}> = props =>
|
|
{
|
|
const [ isReady, setIsReady ] = useState(false);
|
|
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[]>([]);
|
|
|
|
const getFriend = useCallback((userId: number) =>
|
|
{
|
|
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;
|
|
});
|
|
|
|
SendMessageHook(new RequestFriendComposer(userName));
|
|
}, [ sentRequests, canRequestFriend ]);
|
|
|
|
const acceptFriend = useCallback((userId: number) =>
|
|
{
|
|
setRequests(prevValue =>
|
|
{
|
|
const newRequests: MessengerRequest[] = [ ...prevValue ];
|
|
|
|
const index = newRequests.findIndex(request => (request.requesterUserId === userId));
|
|
|
|
if(index >= 0)
|
|
{
|
|
SendMessageHook(new AcceptFriendMessageComposer(newRequests[index].id));
|
|
|
|
dispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.ACCEPTED, userId));
|
|
|
|
newRequests.splice(index, 1);
|
|
}
|
|
|
|
return newRequests;
|
|
});
|
|
}, []);
|
|
|
|
const declineFriend = useCallback((userId: number, declineAll: boolean = false) =>
|
|
{
|
|
setRequests(prevValue =>
|
|
{
|
|
if(declineAll)
|
|
{
|
|
SendMessageHook(new DeclineFriendMessageComposer(true));
|
|
|
|
for(const request of prevValue) dispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, request.requesterUserId));
|
|
|
|
return [];
|
|
}
|
|
else
|
|
{
|
|
const newRequests: MessengerRequest[] = [ ...prevValue ];
|
|
|
|
const index = newRequests.findIndex(request => (request.requesterUserId === userId));
|
|
|
|
if(index >= 0)
|
|
{
|
|
SendMessageHook(new DeclineFriendMessageComposer(false, newRequests[index].id));
|
|
|
|
dispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, userId));
|
|
|
|
newRequests.splice(index, 1);
|
|
}
|
|
|
|
return newRequests;
|
|
}
|
|
});
|
|
}, []);
|
|
|
|
const onMessengerInitEvent = useCallback((event: MessengerInitEvent) =>
|
|
{
|
|
const parser = event.getParser();
|
|
|
|
setSettings(new MessengerSettings(
|
|
parser.userFriendLimit,
|
|
parser.normalFriendLimit,
|
|
parser.extendedFriendLimit,
|
|
parser.categories));
|
|
|
|
SendMessageHook(new GetFriendRequestsComposer());
|
|
}, []);
|
|
|
|
CreateMessageHook(MessengerInitEvent, onMessengerInitEvent);
|
|
|
|
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;
|
|
});
|
|
}, []);
|
|
|
|
CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent);
|
|
|
|
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;
|
|
});
|
|
}, []);
|
|
|
|
CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent);
|
|
|
|
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;
|
|
});
|
|
}, []);
|
|
|
|
CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent);
|
|
|
|
const onNewFriendRequestEvent = useCallback((event: NewFriendRequestEvent) =>
|
|
{
|
|
const parser = event.getParser();
|
|
const request = parser.request;
|
|
|
|
setRequests(prevValue =>
|
|
{
|
|
const newRequests = [ ...prevValue ];
|
|
|
|
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
|
|
|
if(index === -1)
|
|
{
|
|
const newRequest = new MessengerRequest();
|
|
newRequest.populate(request);
|
|
|
|
newRequests.push(newRequest);
|
|
}
|
|
|
|
return newRequests;
|
|
});
|
|
}, []);
|
|
|
|
CreateMessageHook(NewFriendRequestEvent, onNewFriendRequestEvent);
|
|
|
|
const onFriendsEvent = useCallback((event: FriendsEvent) =>
|
|
{
|
|
switch(event.type)
|
|
{
|
|
case FriendsEvent.SHOW_FRIEND_LIST:
|
|
setIsVisible(true);
|
|
return;
|
|
case FriendsEvent.TOGGLE_FRIEND_LIST:
|
|
setIsVisible(value => !value);
|
|
return;
|
|
case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST:
|
|
const requestEvent = (event as FriendsSendFriendRequestEvent);
|
|
requestFriend(requestEvent.userId, requestEvent.userName);
|
|
return;
|
|
case FriendsEvent.REQUEST_FRIEND_LIST:
|
|
dispatchUiEvent(new FriendListContentEvent(friends));
|
|
return;
|
|
}
|
|
}, [ friends, requestFriend ]);
|
|
|
|
useUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent);
|
|
useUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent);
|
|
useUiEvent(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendsEvent);
|
|
useUiEvent(FriendsEvent.REQUEST_FRIEND_LIST, onFriendsEvent);
|
|
|
|
const onFriendsAcceptFriendRequestEvent = useCallback((event: FriendsAcceptFriendRequestEvent) =>
|
|
{
|
|
acceptFriend(event.requestId);
|
|
}, [ acceptFriend ]);
|
|
|
|
useUiEvent(FriendsAcceptFriendRequestEvent.ACCEPT_FRIEND_REQUEST, onFriendsAcceptFriendRequestEvent);
|
|
|
|
const onFriendsDeclineFriendRequestEvent = useCallback((event: FriendsDeclineFriendRequestEvent) =>
|
|
{
|
|
declineFriend(event.requestId);
|
|
}, [ declineFriend ]);
|
|
|
|
useUiEvent(FriendsDeclineFriendRequestEvent.DECLINE_FRIEND_REQUEST, onFriendsDeclineFriendRequestEvent);
|
|
|
|
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) =>
|
|
{
|
|
const roomSession = GetRoomSession();
|
|
|
|
if(!roomSession) return;
|
|
|
|
if(event.category !== RoomObjectCategory.UNIT) return;
|
|
|
|
const userData = roomSession.userDataManager.getUserDataByIndex(event.objectId);
|
|
|
|
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
|
|
|
|
const friend = getFriend(userData.webID);
|
|
|
|
if(!friend) return;
|
|
|
|
dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type));
|
|
}, [ getFriend ]);
|
|
|
|
useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent);
|
|
|
|
const onlineFriends = useMemo(() =>
|
|
{
|
|
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;
|
|
}, [ friends ]);
|
|
|
|
const offlineFriends = useMemo(() =>
|
|
{
|
|
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;
|
|
}, [ friends ]);
|
|
|
|
useEffect(() =>
|
|
{
|
|
SendMessageHook(new MessengerInitComposer());
|
|
}, []);
|
|
|
|
useEffect(() =>
|
|
{
|
|
if(!settings) return;
|
|
|
|
setIsReady(true);
|
|
}, [ settings ]);
|
|
|
|
useEffect(() =>
|
|
{
|
|
dispatchUiEvent(new FriendsRequestCountEvent(requests.length));
|
|
}, [ requests ]);
|
|
|
|
return (
|
|
<FriendsContextProvider value={ { friends, requests, settings, canRequestFriend, requestFriend, acceptFriend, declineFriend } }>
|
|
{ isReady &&
|
|
createPortal(<FriendBarView onlineFriends={ onlineFriends } />, document.getElementById('toolbar-friend-bar-container')) }
|
|
{ isVisible &&
|
|
<FriendsListView onlineFriends={ onlineFriends } offlineFriends={ offlineFriends } friendRequests={ requests } onCloseClick={ () => setIsVisible(false) } /> }
|
|
<FriendsMessengerView />
|
|
</FriendsContextProvider>
|
|
);
|
|
}
|