mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 15:36:18 +00:00
🆙 Init V3
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
export * from './useFriends';
|
||||
export * from './useMessenger';
|
||||
@@ -0,0 +1,252 @@
|
||||
import { AcceptFriendMessageComposer, DeclineFriendMessageComposer, FollowFriendMessageComposer, FriendListFragmentEvent, FriendListUpdateComposer, FriendListUpdateEvent, FriendParser, FriendRequestsEvent, GetFriendRequestsComposer, GetSessionDataManager, MessengerInitComposer, MessengerInitEvent, NewFriendRequestEvent, RequestFriendComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { CloneObject, MessengerFriend, MessengerRequest, MessengerSettings, SendMessageComposer } from '../../api';
|
||||
import { useMessageEvent } from '../events';
|
||||
|
||||
const useFriendsState = () =>
|
||||
{
|
||||
const [ friends, setFriends ] = useState<MessengerFriend[]>([]);
|
||||
const [ requests, setRequests ] = useState<MessengerRequest[]>([]);
|
||||
const [ sentRequests, setSentRequests ] = useState<number[]>([]);
|
||||
const [ dismissedRequestIds, setDismissedRequestIds ] = useState<number[]>([]);
|
||||
const [ settings, setSettings ] = useState<MessengerSettings>(null);
|
||||
|
||||
const onlineFriends = useMemo(() =>
|
||||
{
|
||||
const onlineFriends = friends.filter(friend => friend.online);
|
||||
|
||||
onlineFriends.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
|
||||
|
||||
return onlineFriends;
|
||||
}, [ friends ]);
|
||||
|
||||
const offlineFriends = useMemo(() =>
|
||||
{
|
||||
const offlineFriends = friends.filter(friend => !friend.online);
|
||||
|
||||
offlineFriends.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
|
||||
|
||||
return offlineFriends;
|
||||
}, [ friends ]);
|
||||
|
||||
const followFriend = (friend: MessengerFriend) => SendMessageComposer(new FollowFriendMessageComposer(friend.id));
|
||||
|
||||
const updateRelationship = (friend: MessengerFriend, type: number) => ((type !== friend.relationshipStatus) && SendMessageComposer(new SetRelationshipStatusComposer(friend.id, type)));
|
||||
|
||||
const getFriend = (userId: number) =>
|
||||
{
|
||||
for(const friend of friends)
|
||||
{
|
||||
if(friend.id === userId) return friend;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const canRequestFriend = (userId: number) =>
|
||||
{
|
||||
if(userId === GetSessionDataManager().userId) return false;
|
||||
|
||||
if(getFriend(userId)) return false;
|
||||
|
||||
if(requests.find(request => (request.requesterUserId === userId))) return false;
|
||||
|
||||
if(sentRequests.indexOf(userId) >= 0) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const requestFriend = (userId: number, userName: string) =>
|
||||
{
|
||||
if(!canRequestFriend(userId)) return false;
|
||||
|
||||
setSentRequests(prevValue =>
|
||||
{
|
||||
const newSentRequests = [ ...prevValue ];
|
||||
|
||||
newSentRequests.push(userId);
|
||||
|
||||
return newSentRequests;
|
||||
});
|
||||
|
||||
SendMessageComposer(new RequestFriendComposer(userName));
|
||||
};
|
||||
|
||||
const requestResponse = (requestId: number, flag: boolean) =>
|
||||
{
|
||||
if(requestId === -1 && !flag)
|
||||
{
|
||||
SendMessageComposer(new DeclineFriendMessageComposer(true));
|
||||
|
||||
setRequests([]);
|
||||
}
|
||||
else
|
||||
{
|
||||
setRequests(prevValue =>
|
||||
{
|
||||
const newRequests = [ ...prevValue ];
|
||||
const index = newRequests.findIndex(request => (request.id === requestId));
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
|
||||
if(flag)
|
||||
{
|
||||
SendMessageComposer(new AcceptFriendMessageComposer(newRequests[index].id));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageComposer(new DeclineFriendMessageComposer(false, newRequests[index].id));
|
||||
}
|
||||
|
||||
newRequests.splice(index, 1);
|
||||
|
||||
return newRequests;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useMessageEvent<MessengerInitEvent>(MessengerInitEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setSettings(new MessengerSettings(
|
||||
parser.userFriendLimit,
|
||||
parser.normalFriendLimit,
|
||||
parser.extendedFriendLimit,
|
||||
parser.categories));
|
||||
|
||||
SendMessageComposer(new GetFriendRequestsComposer());
|
||||
});
|
||||
|
||||
useMessageEvent<FriendListFragmentEvent>(FriendListFragmentEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setFriends(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(const friend of parser.fragment)
|
||||
{
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||
const newFriend = new MessengerFriend();
|
||||
newFriend.populate(friend);
|
||||
|
||||
if(index > -1) newValue[index] = newFriend;
|
||||
else newValue.push(newFriend);
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
|
||||
useMessageEvent<FriendListUpdateEvent>(FriendListUpdateEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setFriends(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
const processUpdate = (friend: FriendParser) =>
|
||||
{
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||
|
||||
if(index === -1)
|
||||
{
|
||||
const newFriend = new MessengerFriend();
|
||||
newFriend.populate(friend);
|
||||
|
||||
newValue.unshift(newFriend);
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue[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 = newValue.findIndex(existingFriend => (existingFriend.id === removedFriendId));
|
||||
|
||||
if(index > -1) newValue.splice(index, 1);
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
|
||||
useMessageEvent<FriendRequestsEvent>(FriendRequestsEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setRequests(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(const request of parser.requests)
|
||||
{
|
||||
const index = newValue.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
||||
|
||||
if(index > 0)
|
||||
{
|
||||
newValue[index] = CloneObject(newValue[index]);
|
||||
newValue[index].populate(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
const newRequest = new MessengerRequest();
|
||||
newRequest.populate(request);
|
||||
|
||||
newValue.push(newRequest);
|
||||
}
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
|
||||
useMessageEvent<NewFriendRequestEvent>(NewFriendRequestEvent, event =>
|
||||
{
|
||||
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;
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
SendMessageComposer(new MessengerInitComposer());
|
||||
|
||||
const interval = setInterval(() => SendMessageComposer(new FriendListUpdateComposer()), 120000);
|
||||
|
||||
return () =>
|
||||
{
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { friends, requests, sentRequests, dismissedRequestIds, setDismissedRequestIds, settings, onlineFriends, offlineFriends, getFriend, canRequestFriend, requestFriend, requestResponse, followFriend, updateRelationship };
|
||||
};
|
||||
|
||||
export const useFriends = () => useBetween(useFriendsState);
|
||||
@@ -0,0 +1,187 @@
|
||||
import { GetSessionDataManager, NewConsoleMessageEvent, RoomInviteErrorEvent, RoomInviteEvent, SendMessageComposer as SendMessageComposerPacket } from '@nitrots/nitro-renderer';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { CloneObject, LocalizeText, MessengerIconState, MessengerThread, MessengerThreadChat, NotificationAlertType, PlaySound, SendMessageComposer, SoundNames } from '../../api';
|
||||
import { useMessageEvent } from '../events';
|
||||
import { useNotification } from '../notification';
|
||||
import { useFriends } from './useFriends';
|
||||
|
||||
const useMessengerState = () =>
|
||||
{
|
||||
const [messageThreads, setMessageThreads] = useState<MessengerThread[]>([]);
|
||||
const [activeThreadId, setActiveThreadId] = useState<number>(-1);
|
||||
const [hiddenThreadIds, setHiddenThreadIds] = useState<number[]>([]);
|
||||
const [iconState, setIconState] = useState<number>(MessengerIconState.HIDDEN);
|
||||
const { getFriend = null } = useFriends();
|
||||
const { simpleAlert = null } = useNotification();
|
||||
|
||||
const visibleThreads = useMemo(() => messageThreads.filter(thread => (hiddenThreadIds.indexOf(thread.threadId) === -1)), [messageThreads, hiddenThreadIds]);
|
||||
const activeThread = useMemo(() => ((activeThreadId > 0) && visibleThreads.find(thread => (thread.threadId === activeThreadId) || null)), [activeThreadId, visibleThreads]);
|
||||
|
||||
const getMessageThread = (userId: number) =>
|
||||
{
|
||||
let thread = messageThreads.find(thread => (thread.participant && (thread.participant.id === userId)));
|
||||
|
||||
if (!thread)
|
||||
{
|
||||
const friend = getFriend(userId);
|
||||
|
||||
if (!friend) return null;
|
||||
|
||||
thread = new MessengerThread(friend);
|
||||
|
||||
thread.addMessage(null, LocalizeText('messenger.moderationinfo'), 0, null, MessengerThreadChat.SECURITY_NOTIFICATION);
|
||||
|
||||
thread.setRead();
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [...prevValue];
|
||||
|
||||
newValue.push(thread);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
const hiddenIndex = hiddenThreadIds.indexOf(thread.threadId);
|
||||
|
||||
if (hiddenIndex >= 0)
|
||||
{
|
||||
setHiddenThreadIds(prevValue =>
|
||||
{
|
||||
const newValue = [...prevValue];
|
||||
|
||||
newValue.splice(hiddenIndex, 1);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return thread;
|
||||
};
|
||||
|
||||
const closeThread = (threadId: number) =>
|
||||
{
|
||||
setHiddenThreadIds(prevValue =>
|
||||
{
|
||||
const newValue = [...prevValue];
|
||||
|
||||
if (newValue.indexOf(threadId) >= 0) return prevValue;
|
||||
|
||||
newValue.push(threadId);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
|
||||
if (activeThreadId === threadId) setActiveThreadId(-1);
|
||||
};
|
||||
|
||||
const sendMessage = (thread: MessengerThread, senderId: number, messageText: string, secondsSinceSent: number = 0, extraData: string = null, messageType: number = MessengerThreadChat.CHAT) =>
|
||||
{
|
||||
if (!thread || !messageText || !messageText.length) return;
|
||||
|
||||
const ownMessage = (senderId === GetSessionDataManager().userId);
|
||||
|
||||
if (ownMessage && (messageText.length <= 255)) SendMessageComposer(new SendMessageComposerPacket(thread.participant.id, messageText));
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [...prevValue];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === thread.threadId));
|
||||
|
||||
if (index === -1) return prevValue;
|
||||
|
||||
thread = CloneObject(newValue[index]);
|
||||
|
||||
if (ownMessage && (thread.groups.length === 1)) PlaySound(SoundNames.MESSENGER_NEW_THREAD);
|
||||
|
||||
thread.addMessage(((messageType === MessengerThreadChat.ROOM_INVITE) ? null : senderId), messageText, secondsSinceSent, extraData, messageType);
|
||||
|
||||
if (activeThreadId === thread.threadId) thread.setRead();
|
||||
|
||||
newValue[index] = thread;
|
||||
|
||||
if (!ownMessage && thread.unread) PlaySound(SoundNames.MESSENGER_MESSAGE_RECEIVED);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
};
|
||||
|
||||
useMessageEvent<NewConsoleMessageEvent>(NewConsoleMessageEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const thread = getMessageThread(parser.senderId);
|
||||
|
||||
if (!thread) return;
|
||||
|
||||
sendMessage(thread, parser.senderId, parser.messageText, parser.secondsSinceSent, parser.extraData);
|
||||
});
|
||||
|
||||
useMessageEvent<RoomInviteEvent>(RoomInviteEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const thread = getMessageThread(parser.senderId);
|
||||
|
||||
if (!thread) return;
|
||||
|
||||
sendMessage(thread, parser.senderId, parser.messageText, 0, null, MessengerThreadChat.ROOM_INVITE);
|
||||
});
|
||||
|
||||
useMessageEvent<RoomInviteErrorEvent>(RoomInviteErrorEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
simpleAlert(`Received room invite error: ${ parser.errorCode },recipients: ${ parser.failedRecipients.join(',') }`, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title'));
|
||||
});
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if (activeThreadId <= 0) return;
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [...prevValue];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === activeThreadId));
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
newValue[index] = CloneObject(newValue[index]);
|
||||
|
||||
newValue[index].setRead();
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, [activeThreadId]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setIconState(prevValue =>
|
||||
{
|
||||
if (!visibleThreads.length) return MessengerIconState.HIDDEN;
|
||||
|
||||
let isUnread = false;
|
||||
|
||||
for (const thread of visibleThreads)
|
||||
{
|
||||
if (thread.unreadCount > 0)
|
||||
{
|
||||
isUnread = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isUnread) return MessengerIconState.UNREAD;
|
||||
|
||||
return MessengerIconState.SHOW;
|
||||
});
|
||||
}, [visibleThreads]);
|
||||
|
||||
return { messageThreads, activeThread, iconState, visibleThreads, getMessageThread, setActiveThreadId, closeThread, sendMessage };
|
||||
};
|
||||
|
||||
export const useMessenger = () => useBetween(useMessengerState);
|
||||
Reference in New Issue
Block a user