diff --git a/src/api/nitro/room/widgets/events/RoomWidgetUpdateFriendRequestEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetUpdateFriendRequestEvent.ts new file mode 100644 index 00000000..b60ac2d4 --- /dev/null +++ b/src/api/nitro/room/widgets/events/RoomWidgetUpdateFriendRequestEvent.ts @@ -0,0 +1,35 @@ +import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent'; + +export class RoomWidgetUpdateFriendRequestEvent extends RoomWidgetUpdateEvent +{ + public static SHOW_FRIEND_REQUEST: string = 'RWFRUE_SHOW_FRIEND_REQUEST'; + public static HIDE_FRIEND_REQUEST: string = 'RWFRUE_HIDE_FRIEND_REQUEST'; + + private _requestId: number; + private _userId: number; + private _userName: string; + + constructor(type: string, requestId: number = -1, userId: number = -1, userName: string = null) + { + super(type); + + this._requestId = requestId; + this._userId = userId; + this._userName = userName; + } + + public get requestId(): number + { + return this._requestId; + } + + public get userId(): number + { + return this._userId; + } + + public get userName(): string + { + return this._userName; + } +} diff --git a/src/api/nitro/room/widgets/events/index.ts b/src/api/nitro/room/widgets/events/index.ts index f4415bb9..6f7406a0 100644 --- a/src/api/nitro/room/widgets/events/index.ts +++ b/src/api/nitro/room/widgets/events/index.ts @@ -17,6 +17,7 @@ export * from './RoomWidgetUpdateDimmerEvent'; export * from './RoomWidgetUpdateDimmerStateEvent'; export * from './RoomWidgetUpdateEvent'; export * from './RoomWidgetUpdateExternalImageEvent'; +export * from './RoomWidgetUpdateFriendRequestEvent'; export * from './RoomWidgetUpdateInfostandEvent'; export * from './RoomWidgetUpdateInfostandFurniEvent'; export * from './RoomWidgetUpdateInfostandPetEvent'; @@ -31,5 +32,6 @@ export * from './RoomWidgetUpdateRoomViewEvent'; export * from './RoomWidgetUpdateSongEvent'; export * from './RoomWidgetUpdateTrophyEvent'; export * from './RoomWidgetUpdateUserDataEvent'; +export * from './RoomWidgetUpdateYoutubeDisplayEvent'; export * from './RoomWidgetUseProductBubbleEvent'; export * from './UseProductItem'; diff --git a/src/api/nitro/room/widgets/handlers/FriendRequestHandler.ts b/src/api/nitro/room/widgets/handlers/FriendRequestHandler.ts new file mode 100644 index 00000000..123b31db --- /dev/null +++ b/src/api/nitro/room/widgets/handlers/FriendRequestHandler.ts @@ -0,0 +1,65 @@ +import { NitroEvent, RoomSessionFriendRequestEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer'; +import { FriendRequestEvent, FriendsAcceptFriendRequestEvent, FriendsDeclineFriendRequestEvent } from '../../../../../events'; +import { dispatchUiEvent } from '../../../../../hooks'; +import { RoomWidgetUpdateEvent, RoomWidgetUpdateFriendRequestEvent } from '../events'; +import { RoomWidgetFriendRequestMessage, RoomWidgetMessage } from '../messages'; +import { RoomWidgetHandler } from './RoomWidgetHandler'; + +export class FriendRequestHandler extends RoomWidgetHandler +{ + public processEvent(event: NitroEvent): void + { + const friendRequestEvent = (event as RoomSessionFriendRequestEvent); + + switch(event.type) + { + case RoomSessionFriendRequestEvent.RSFRE_FRIEND_REQUEST: + this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateFriendRequestEvent(RoomWidgetUpdateFriendRequestEvent.SHOW_FRIEND_REQUEST, friendRequestEvent.requestId, friendRequestEvent.userId, friendRequestEvent.userName)); + return; + case FriendRequestEvent.ACCEPTED: + case FriendRequestEvent.DECLINED: + this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateFriendRequestEvent(RoomWidgetUpdateFriendRequestEvent.HIDE_FRIEND_REQUEST, friendRequestEvent.requestId)); + return; + } + } + + public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent + { + const friendMessage = (message as RoomWidgetFriendRequestMessage); + + switch(message.type) + { + case RoomWidgetFriendRequestMessage.ACCEPT: + dispatchUiEvent(new FriendsAcceptFriendRequestEvent(friendMessage.requestId)); + break; + case RoomWidgetFriendRequestMessage.DECLINE: + dispatchUiEvent(new FriendsDeclineFriendRequestEvent(friendMessage.requestId)); + break; + + } + + return null; + } + + public get type(): string + { + return RoomWidgetEnum.FRIEND_REQUEST; + } + + public get eventTypes(): string[] + { + return [ + RoomSessionFriendRequestEvent.RSFRE_FRIEND_REQUEST, + FriendRequestEvent.ACCEPTED, + FriendRequestEvent.DECLINED + ]; + } + + public get messageTypes(): string[] + { + return [ + RoomWidgetFriendRequestMessage.ACCEPT, + RoomWidgetFriendRequestMessage.DECLINE + ]; + } +} diff --git a/src/api/nitro/room/widgets/handlers/FurnitureTrophyWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/FurnitureTrophyWidgetHandler.ts new file mode 100644 index 00000000..9b345109 --- /dev/null +++ b/src/api/nitro/room/widgets/handlers/FurnitureTrophyWidgetHandler.ts @@ -0,0 +1,61 @@ +import { NitroEvent, RoomObjectVariable, RoomWidgetEnum } from '@nitrots/nitro-renderer'; +import { RoomWidgetUpdateEvent } from '..'; +import { GetRoomEngine } from '../..'; +import { RoomWidgetFurniToWidgetMessage, RoomWidgetMessage } from '../messages'; +import { RoomWidgetHandler } from './RoomWidgetHandler'; + +export class FurnitureTrophyWidgetHandler extends RoomWidgetHandler +{ + public processEvent(event: NitroEvent): void + { + return; + } + + public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent + { + switch(message.type) + { + case RoomWidgetFurniToWidgetMessage.REQUEST_TROPHY: { + const widgetMessage = (message as RoomWidgetFurniToWidgetMessage); + const roomObject = GetRoomEngine().getRoomObject(widgetMessage.roomId, widgetMessage.objectId, widgetMessage.category); + + if(!roomObject) return; + + const color = roomObject.model.getValue(RoomObjectVariable.FURNITURE_COLOR); + const extra = parseInt(roomObject.model.getValue(RoomObjectVariable.FURNITURE_EXTRAS)); + + let data = roomObject.model.getValue(RoomObjectVariable.FURNITURE_DATA); + + const ownerName = data.substring(0, data.indexOf('\t')); + + data = data.substring((ownerName.length + 1), data.length); + + const date = data.substring(0, data.indexOf('\t')); + const text = data.substr((date.length + 1), data.length); + + + + break; + } + } + + return null; + } + + public get type(): string + { + return RoomWidgetEnum.FURNI_TROPHY_WIDGET; + } + + public get eventTypes(): string[] + { + return []; + } + + public get messageTypes(): string[] + { + return [ + RoomWidgetFurniToWidgetMessage.REQUEST_TROPHY + ]; + } +} diff --git a/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts b/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts index be1d8608..206af214 100644 --- a/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts +++ b/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts @@ -5,6 +5,7 @@ import { FriendsSendFriendRequestEvent } from '../../../../../events/friends/Fri import { HelpReportUserEvent } from '../../../../../events/help/HelpReportUserEvent'; import { dispatchUiEvent } from '../../../../../hooks/events'; import { SendMessageHook } from '../../../../../hooks/messages'; +import { FriendsHelper } from '../../../../../views/friends/common/FriendsHelper'; import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum'; import { LocalizeText } from '../../../../utils/LocalizeText'; import { RoomWidgetObjectNameEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent } from '../events'; @@ -77,7 +78,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO: return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage)); case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST: - dispatchUiEvent(new FriendsSendFriendRequestEvent(userId)); + dispatchUiEvent(new FriendsSendFriendRequestEvent(userData.webID, userData.name)); break; case RoomWidgetUserActionMessage.RESPECT_USER: GetSessionDataManager().giveRespect(userId); @@ -461,15 +462,18 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler if(eventType === RoomWidgetUpdateInfostandUserEvent.PEER) { - // userInfoData.canBeAskedAsFriend = this._container.friendService.canBeAskedForAFriend(userData.webID); + event.canBeAskedAsFriend = FriendsHelper.canRequestFriend(userData.webID); - // const friend = this._container.friendService.getFriend(userData.webID); + if(!event.canBeAskedAsFriend) + { + const friend = FriendsHelper.getFriend(userData.webID); - // if(friend) - // { - // userInfoData.realName = friend.realName; - // userInfoData.isFriend = true; - // } + if(friend) + { + event.realName = friend.realName; + event.isFriend = true; + } + } if(roomObject) { diff --git a/src/api/nitro/room/widgets/handlers/index.ts b/src/api/nitro/room/widgets/handlers/index.ts index 51f10e1a..463caaaa 100644 --- a/src/api/nitro/room/widgets/handlers/index.ts +++ b/src/api/nitro/room/widgets/handlers/index.ts @@ -1,4 +1,5 @@ export * from './DoorbellWidgetHandler'; +export * from './FriendRequestHandler'; export * from './FurniChooserWidgetHandler'; export * from './FurnitureContextMenuWidgetHandler'; export * from './FurnitureCreditWidgetHandler'; @@ -7,6 +8,8 @@ export * from './FurnitureDimmerWidgetHandler'; export * from './FurnitureExternalImageWidgetHandler'; export * from './FurnitureMannequinWidgetHandler'; export * from './FurniturePresentWidgetHandler'; +export * from './FurnitureTrophyWidgetHandler'; +export * from './FurnitureYoutubeDisplayWidgetHandler'; export * from './IRoomWidgetHandler'; export * from './IRoomWidgetHandlerManager'; export * from './RoomWidgetAvatarInfoHandler'; diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetFriendRequestMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetFriendRequestMessage.ts new file mode 100644 index 00000000..898a042d --- /dev/null +++ b/src/api/nitro/room/widgets/messages/RoomWidgetFriendRequestMessage.ts @@ -0,0 +1,21 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetFriendRequestMessage extends RoomWidgetMessage +{ + public static ACCEPT: string = 'RWFRM_ACCEPT'; + public static DECLINE: string = 'RMFRM_DECLINE'; + + private _requestId: number; + + constructor(type: string, requestId: number) + { + super(type); + + this._requestId = requestId; + } + + public get requestId(): number + { + return this._requestId; + } +} diff --git a/src/api/nitro/room/widgets/messages/index.ts b/src/api/nitro/room/widgets/messages/index.ts index 287a3aa6..c3d1bd48 100644 --- a/src/api/nitro/room/widgets/messages/index.ts +++ b/src/api/nitro/room/widgets/messages/index.ts @@ -9,6 +9,7 @@ export * from './RoomWidgetDanceMessage'; export * from './RoomWidgetDimmerChangeStateMessage'; export * from './RoomWidgetDimmerPreviewMessage'; export * from './RoomWidgetDimmerSavePresetMessage'; +export * from './RoomWidgetFriendRequestMessage'; export * from './RoomWidgetFurniActionMessage'; export * from './RoomWidgetFurniToWidgetMessage'; export * from './RoomWidgetLetUserInMessage'; diff --git a/src/events/friends/FriendListContentEvent.ts b/src/events/friends/FriendListContentEvent.ts index 80048267..5666c4f0 100644 --- a/src/events/friends/FriendListContentEvent.ts +++ b/src/events/friends/FriendListContentEvent.ts @@ -1,7 +1,7 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; import { MessengerFriend } from '../../views/friends/common/MessengerFriend'; -import { FriendsEvent } from './FriendsEvent'; -export class FriendListContentEvent extends FriendsEvent +export class FriendListContentEvent extends NitroEvent { public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT'; diff --git a/src/events/friends/FriendRequestEvent.ts b/src/events/friends/FriendRequestEvent.ts new file mode 100644 index 00000000..33c78132 --- /dev/null +++ b/src/events/friends/FriendRequestEvent.ts @@ -0,0 +1,21 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; + +export class FriendRequestEvent extends NitroEvent +{ + public static ACCEPTED: string = 'FRE_ACCEPTED'; + public static DECLINED: string = 'FRE_DECLINED'; + + private _requestId: number; + + constructor(type: string, requestId: number) + { + super(type); + + this._requestId = requestId; + } + + public get requestId(): number + { + return this._requestId; + } +} diff --git a/src/events/friends/FriendsAcceptFriendRequestEvent.ts b/src/events/friends/FriendsAcceptFriendRequestEvent.ts new file mode 100644 index 00000000..565cd5f0 --- /dev/null +++ b/src/events/friends/FriendsAcceptFriendRequestEvent.ts @@ -0,0 +1,20 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; + +export class FriendsAcceptFriendRequestEvent extends NitroEvent +{ + public static ACCEPT_FRIEND_REQUEST: string = 'FAFRE_ACCEPT_FRIEND_REQUEST'; + + private _requestId: number; + + constructor(requestId: number) + { + super(FriendsAcceptFriendRequestEvent.ACCEPT_FRIEND_REQUEST); + + this._requestId = requestId; + } + + public get requestId(): number + { + return this._requestId; + } +} diff --git a/src/events/friends/FriendsDeclineFriendRequestEvent.ts b/src/events/friends/FriendsDeclineFriendRequestEvent.ts new file mode 100644 index 00000000..3fa71ac6 --- /dev/null +++ b/src/events/friends/FriendsDeclineFriendRequestEvent.ts @@ -0,0 +1,20 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; + +export class FriendsDeclineFriendRequestEvent extends NitroEvent +{ + public static DECLINE_FRIEND_REQUEST: string = 'FAFRE_DECLINE_FRIEND_REQUEST'; + + private _requestId: number; + + constructor(requestId: number) + { + super(FriendsDeclineFriendRequestEvent.DECLINE_FRIEND_REQUEST); + + this._requestId = requestId; + } + + public get requestId(): number + { + return this._requestId; + } +} diff --git a/src/events/friends/FriendsRequestCountEvent.ts b/src/events/friends/FriendsRequestCountEvent.ts new file mode 100644 index 00000000..884819e0 --- /dev/null +++ b/src/events/friends/FriendsRequestCountEvent.ts @@ -0,0 +1,20 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; + +export class FriendsRequestCountEvent extends NitroEvent +{ + public static UPDATE_COUNT: string = 'FRCE_UPDATE_COUNT'; + + private _count: number; + + constructor(count: number) + { + super(FriendsRequestCountEvent.UPDATE_COUNT); + + this._count = count; + } + + public get count(): number + { + return this._count; + } +} diff --git a/src/events/friends/FriendsSendFriendRequestEvent.ts b/src/events/friends/FriendsSendFriendRequestEvent.ts index 9e42661b..177ce5b7 100644 --- a/src/events/friends/FriendsSendFriendRequestEvent.ts +++ b/src/events/friends/FriendsSendFriendRequestEvent.ts @@ -1,20 +1,27 @@ -import { FriendsEvent } from './FriendsEvent'; +import { NitroEvent } from '@nitrots/nitro-renderer'; -export class FriendsSendFriendRequestEvent extends FriendsEvent +export class FriendsSendFriendRequestEvent extends NitroEvent { public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST'; private _userId: number; + private _userName: string; - constructor(userId: number) + constructor(userId: number, userName: string) { super(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST); this._userId = userId; + this._userName = userName; } public get userId(): number { return this._userId; } + + public get userName(): string + { + return this._userName; + } } diff --git a/src/events/friends/index.ts b/src/events/friends/index.ts index 2f3699c3..21f764ef 100644 --- a/src/events/friends/index.ts +++ b/src/events/friends/index.ts @@ -1,5 +1,9 @@ export * from './FriendEnteredRoomEvent'; export * from './FriendListContentEvent'; +export * from './FriendRequestEvent'; +export * from './FriendsAcceptFriendRequestEvent'; +export * from './FriendsDeclineFriendRequestEvent'; export * from './FriendsEvent'; export * from './FriendsMessengerIconEvent'; +export * from './FriendsRequestCountEvent'; export * from './FriendsSendFriendRequestEvent'; diff --git a/src/views/friends/FriendsMessageHandler.tsx b/src/views/friends/FriendsMessageHandler.tsx deleted file mode 100644 index ce84725e..00000000 --- a/src/views/friends/FriendsMessageHandler.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent } from '@nitrots/nitro-renderer'; -import { FC, useCallback } from 'react'; -import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; -import { MessengerSettings } from './common/MessengerSettings'; -import { useFriendsContext } from './context/FriendsContext'; -import { FriendsActions } from './reducers/FriendsReducer'; - -export const FriendsMessageHandler: FC<{}> = props => -{ - const { friendsState = null, dispatchFriendsState = null } = useFriendsContext(); - - const onMessengerInitEvent = useCallback((event: MessengerInitEvent) => - { - const parser = event.getParser(); - - dispatchFriendsState({ - type: FriendsActions.UPDATE_SETTINGS, - payload: { - settings: new MessengerSettings( - parser.userFriendLimit, - parser.normalFriendLimit, - parser.extendedFriendLimit, - parser.categories) - } - }); - - SendMessageHook(new GetFriendRequestsComposer()); - }, [ dispatchFriendsState ]); - - const onFriendsFragmentEvent = useCallback((event: FriendListFragmentEvent) => - { - const parser = event.getParser(); - - dispatchFriendsState({ - type: FriendsActions.PROCESS_FRAGMENT, - payload: { - fragment: parser.fragment - } - }); - }, [ dispatchFriendsState ]); - - const onFriendsUpdateEvent = useCallback((event: FriendListUpdateEvent) => - { - const parser = event.getParser(); - - dispatchFriendsState({ - type: FriendsActions.PROCESS_UPDATE, - payload: { - update: parser - } - }); - }, [ dispatchFriendsState ]); - - const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) => - { - const parser = event.getParser(); - - dispatchFriendsState({ - type: FriendsActions.PROCESS_REQUESTS, - payload: { - requests: parser.requests - } - }); - }, [ dispatchFriendsState ]); - - CreateMessageHook(MessengerInitEvent, onMessengerInitEvent); - CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent); - CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent); - CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent); - - return null; -} diff --git a/src/views/friends/FriendsView.scss b/src/views/friends/FriendsView.scss index 3d55929f..35888832 100644 --- a/src/views/friends/FriendsView.scss +++ b/src/views/friends/FriendsView.scss @@ -1,6 +1,7 @@ .nitro-friends { - width: 250px; + width: $friends-list-width; + height: $friends-list-height; } -@import './views/friend-bar/FriendBarView'; -@import './views/messenger/FriendsMessengerView'; +@import "./views/friend-bar/FriendBarView"; +@import "./views/messenger/FriendsMessengerView"; diff --git a/src/views/friends/FriendsView.tsx b/src/views/friends/FriendsView.tsx index 0c9415f7..fedb706f 100644 --- a/src/views/friends/FriendsView.tsx +++ b/src/views/friends/FriendsView.tsx @@ -1,57 +1,272 @@ -import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer'; -import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react'; +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, FriendsEvent } from '../../events'; +import { FriendEnteredRoomEvent, FriendListContentEvent, FriendsEvent, FriendsRequestCountEvent } from '../../events'; import { FriendsSendFriendRequestEvent } from '../../events/friends/FriendsSendFriendRequestEvent'; -import { useRoomEngineEvent } from '../../hooks/events'; +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 { FriendsMessageHandler } from './FriendsMessageHandler'; -import { FriendsReducer, initialFriends } from './reducers/FriendsReducer'; 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 [ friendsState, dispatchFriendsState ] = useReducer(FriendsReducer, initialFriends); - const { friends = [], requests = [], settings = null } = friendsState; - const [ isReady, setIsReady ] = useState(false); - const [ isListVisible, setIsListVisible ] = useState(false); + const [ isVisible, setIsVisible ] = useState(false); + const [ friends, setFriends ] = useState([]); + const [ requests, setRequests ] = useState([]); + const [ settings, setSettings ] = useState(null); + const [ sentRequests, setSentRequests ] = useState([]); - useEffect(() => + const getFriend = useCallback((userId: number) => { - SendMessageHook(new MessengerInitComposer()); + 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[] = []; + + for(const request of prevValue) + { + if(request.requesterUserId !== userId) + { + newRequests.push(request); + } + else + { + SendMessageHook(new AcceptFriendMessageComposer(request.id)); + } + } + + return newRequests; + }); }, []); - useEffect(() => + const declineFriend = useCallback((userId: number, declineAll: boolean = false) => { - if(!settings) return; + setRequests(prevValue => + { + if(declineAll) + { + SendMessageHook(new DeclineFriendMessageComposer(true)); - setIsReady(true); - }, [ settings ]); + return []; + } + else + { + const newRequests: MessengerRequest[] = []; + + for(const request of prevValue) + { + if(request.requesterUserId !== userId) + { + newRequests.push(request); + } + else + { + SendMessageHook(new DeclineFriendMessageComposer(false, request.id)); + } + } + + 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 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: - setIsListVisible(true); + setIsVisible(true); return; case FriendsEvent.TOGGLE_FRIEND_LIST: - setIsListVisible(value => !value); + 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(friendsState.friends)); + dispatchUiEvent(new FriendListContentEvent(friends)); return; } - }, [ friendsState.friends ]); + }, [ friends, requestFriend ]); useUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent); useUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent); @@ -70,33 +285,70 @@ export const FriendsView: FC<{}> = props => if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return; - const friend = friendsState.friends.find(friend => - { - return (friend.id === userData.webID); - }); + const friend = getFriend(userData.webID); if(!friend) return; dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type)); - }, [ friendsState.friends ]); + }, [ getFriend ]); useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent); const onlineFriends = useMemo(() => { - return friends.filter(f => f.online); + 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(() => { - return friends.filter(f => !f.online); + 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 ( - - - { isReady && createPortal(, document.getElementById('toolbar-friend-bar-container')) } - { isListVisible && setIsListVisible(false) } /> } + + { isReady && + createPortal(, document.getElementById('toolbar-friend-bar-container')) } + { isVisible && + setIsVisible(false) } /> } ); diff --git a/src/views/friends/common/FriendsHelper.ts b/src/views/friends/common/FriendsHelper.ts new file mode 100644 index 00000000..2e80f50c --- /dev/null +++ b/src/views/friends/common/FriendsHelper.ts @@ -0,0 +1,14 @@ +import { MessengerFriend } from './MessengerFriend'; + +export class FriendsHelper +{ + public static getFriend(userId: number): MessengerFriend + { + return null; + } + + public static canRequestFriend(userId: number): boolean + { + return false; + } +} diff --git a/src/views/friends/context/FriendsContext.tsx b/src/views/friends/context/FriendsContext.tsx index 5b551102..a93a2f43 100644 --- a/src/views/friends/context/FriendsContext.tsx +++ b/src/views/friends/context/FriendsContext.tsx @@ -2,8 +2,11 @@ import { createContext, FC, useContext } from 'react'; import { FriendsContextProps, IFriendsContext } from './FriendsContext.type'; const FriendsContext = createContext({ - friendsState: null, - dispatchFriendsState: null + friends: null, + requests: null, + settings: null, + acceptFriend: null, + declineFriend: null }); export const FriendsContextProvider: FC = props => diff --git a/src/views/friends/context/FriendsContext.type.ts b/src/views/friends/context/FriendsContext.type.ts index a61ef776..2eaf79a9 100644 --- a/src/views/friends/context/FriendsContext.type.ts +++ b/src/views/friends/context/FriendsContext.type.ts @@ -1,10 +1,15 @@ -import { Dispatch, ProviderProps } from 'react'; -import { IFriendsAction, IFriendsState } from '../reducers/FriendsReducer'; +import { ProviderProps } from 'react'; +import { MessengerFriend } from '../common/MessengerFriend'; +import { MessengerRequest } from '../common/MessengerRequest'; +import { MessengerSettings } from '../common/MessengerSettings'; export interface IFriendsContext { - friendsState: IFriendsState; - dispatchFriendsState: Dispatch; + friends: MessengerFriend[]; + requests: MessengerRequest[]; + settings: MessengerSettings; + acceptFriend: (userId: number) => void; + declineFriend: (userId: number, declineAll?: boolean) => void; } export interface FriendsContextProps extends ProviderProps diff --git a/src/views/friends/reducers/FriendsReducer.tsx b/src/views/friends/reducers/FriendsReducer.tsx deleted file mode 100644 index 1901bb49..00000000 --- a/src/views/friends/reducers/FriendsReducer.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer'; -import { Reducer } from 'react'; -import { MessengerFriend } from '../common/MessengerFriend'; -import { MessengerRequest } from '../common/MessengerRequest'; -import { MessengerSettings } from '../common/MessengerSettings'; - -function compareName(a, b) -{ - if( a.name < b.name ) return -1; - if( a.name > b.name ) return 1; - return 0; -} - -export interface IFriendsState -{ - settings: MessengerSettings; - friends: MessengerFriend[]; - requests: MessengerRequest[]; -} - -export interface IFriendsAction -{ - type: string; - payload: { - settings?: MessengerSettings; - fragment?: FriendParser[]; - update?: FriendListUpdateParser; - requests?: FriendRequestData[]; - numberValue?: number; - boolValue?: boolean; - } -} - -export class FriendsActions -{ - public static RESET_STATE: string = 'FA_RESET_STATE'; - public static UPDATE_SETTINGS: string = 'FA_UPDATE_SETTINGS'; - public static PROCESS_FRAGMENT: string = 'FA_PROCESS_FRAGMENT'; - public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE'; - public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS'; -} - -export const initialFriends: IFriendsState = { - settings: null, - friends: [], - requests: [] -} - -export const FriendsReducer: Reducer = (state, action) => -{ - switch(action.type) - { - case FriendsActions.UPDATE_SETTINGS: { - const settings = (action.payload.settings || state.settings || null); - - return { ...state, settings }; - } - case FriendsActions.PROCESS_FRAGMENT: { - const fragment = (action.payload.fragment || null); - let friends = [ ...state.friends ]; - - for(const friend of fragment) - { - const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id)); - const newFriend = new MessengerFriend(); - - newFriend.id = friend.id; - newFriend.name = friend.name; - newFriend.gender = friend.gender; - newFriend.online = friend.online; - newFriend.followingAllowed = friend.followingAllowed; - newFriend.figure = friend.figure; - newFriend.categoryId = friend.categoryId; - newFriend.motto = friend.motto; - newFriend.realName = friend.realName; - newFriend.lastAccess = friend.lastAccess; - newFriend.persistedMessageUser = friend.persistedMessageUser; - newFriend.vipMember = friend.vipMember; - newFriend.pocketHabboUser = friend.pocketHabboUser; - newFriend.relationshipStatus = friend.relationshipStatus; - - if(index > -1) friends[index] = newFriend; - else friends.push(newFriend); - } - - friends.sort(compareName); - - return { ...state, friends }; - } - case FriendsActions.PROCESS_UPDATE: { - const update = (action.payload.update || null); - let friends = [ ...state.friends ]; - - if(update) - { - const processUpdate = (friend: FriendParser) => - { - const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id)); - - if(index === -1) - { - const newFriend = new MessengerFriend(); - newFriend.populate(friend); - - friends.unshift(newFriend); - } - else - { - friends[index].populate(friend); - } - } - - for(const friend of update.addedFriends) processUpdate(friend); - - for(const friend of update.updatedFriends) processUpdate(friend); - - for(const removedFriendId of update.removedFriendIds) - { - const index = friends.findIndex(existingFriend => (existingFriend.id === removedFriendId)); - - if(index > -1) friends.splice(index); - } - } - - friends.sort(compareName); - - return { ...state, friends }; - } - case FriendsActions.PROCESS_REQUESTS: { - const newRequests = (action.payload.requests || null); - let requests = [ ...state.requests ]; - - for(const request of newRequests) - { - const newRequest = new MessengerRequest(); - newRequest.populate(request); - requests.push(newRequest); - } - - requests.sort(compareName); - - return { ...state, requests }; - } - default: - return state; - } -} diff --git a/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx b/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx index 40873386..c077ab43 100644 --- a/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx +++ b/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx @@ -1,6 +1,6 @@ -import { FollowFriendMessageComposer, MouseEventType, UserProfileComposer } from '@nitrots/nitro-renderer'; +import { FollowFriendMessageComposer, MouseEventType } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useRef, useState } from 'react'; -import { LocalizeText, OpenMessengerChat } from '../../../../api'; +import { GetUserProfile, LocalizeText, OpenMessengerChat } from '../../../../api'; import { SendMessageHook } from '../../../../hooks/messages'; import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; import { FriendBarItemViewProps } from './FriendBarItemView.types'; @@ -23,11 +23,6 @@ export const FriendBarItemView: FC = props => OpenMessengerChat(friend.id); }, [ friend ]); - const openProfile = useCallback(() => - { - SendMessageHook(new UserProfileComposer(friend.id)); - }, [ friend ]); - const onClick = useCallback((event: MouseEvent) => { const element = elementRef.current; @@ -68,7 +63,7 @@ export const FriendBarItemView: FC = props =>
{ friend.followingAllowed && } - + GetUserProfile(friend.id) } className="icon icon-fb-profile cursor-pointer" />
} ); diff --git a/src/views/friends/views/friends-group/FriendsGroupView.tsx b/src/views/friends/views/friends-group/FriendsGroupView.tsx index c5eb989b..55b82fca 100644 --- a/src/views/friends/views/friends-group/FriendsGroupView.tsx +++ b/src/views/friends/views/friends-group/FriendsGroupView.tsx @@ -1,25 +1,19 @@ import React, { FC } from 'react'; -import { MessengerFriend } from '../../common/MessengerFriend'; -import { MessengerRequest } from '../../common/MessengerRequest'; import { FriendsGroupItemView } from '../friends-group-item/FriendsGroupItemView'; -import { FriendsRequestItemView } from '../friends-request-item/FriendsRequestItemView'; import { FriendsGroupViewProps } from './FriendsGroupView.types'; export const FriendsGroupView: FC = props => { - const { list = null } = props; + const { list = null } = props; if(!list) return null; - return (<> - { list.map((item, index) => - { - if(item instanceof MessengerFriend) - return - else if(item instanceof MessengerRequest) - return - else - return null; - }) } - ); + return ( + <> + { list.map((item, index) => + { + return ; + }) } + + ); } diff --git a/src/views/friends/views/friends-group/FriendsGroupView.types.ts b/src/views/friends/views/friends-group/FriendsGroupView.types.ts index 48bc5ee6..5ce24421 100644 --- a/src/views/friends/views/friends-group/FriendsGroupView.types.ts +++ b/src/views/friends/views/friends-group/FriendsGroupView.types.ts @@ -1,7 +1,6 @@ import { MessengerFriend } from '../../common/MessengerFriend'; -import { MessengerRequest } from '../../common/MessengerRequest'; export interface FriendsGroupViewProps { - list: MessengerFriend[] | MessengerRequest[]; + list: MessengerFriend[]; } diff --git a/src/views/friends/views/friends-list/FriendsListView.tsx b/src/views/friends/views/friends-list/FriendsListView.tsx index fd796044..f706d334 100644 --- a/src/views/friends/views/friends-list/FriendsListView.tsx +++ b/src/views/friends/views/friends-list/FriendsListView.tsx @@ -1,43 +1,47 @@ import { FC, useState } from 'react'; import { LocalizeText } from '../../../../api'; -import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout'; +import { NitroCardAccordionSetView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout'; import { FriendsGroupView } from '../friends-group/FriendsGroupView'; +import { FriendsRequestView } from '../friends-request/FriendsRequestView'; import { FriendsListViewProps } from './FriendsListView.types'; -const TABS: string[] = ['friendlist.friends', 'generic.search']; +const MODE_FRIENDS: number = 0; +const MODE_SEARCH: number = 1; export const FriendsListView: FC = props => { - const { onlineFriends = [], offlineFriends = [], friendRequests = [], onCloseClick = null } = props; - const [ currentTab, setCurrentTab ] = useState(0); + const { onlineFriends = [], offlineFriends = [], friendRequests = [], onCloseClick = null } = props; + const [ mode, setMode ] = useState(0); return ( - - - - { TABS.map((tab, index) => - { - return ( setCurrentTab(index) }> - { LocalizeText(tab) } - ); - }) } - -
- { currentTab === 0 && - - - - - - - { friendRequests.length > 0 && - - } - } -
-
-
+ + + setMode(MODE_FRIENDS) }> + { LocalizeText('friendlist.friends') } + + setMode(MODE_SEARCH) }> + { LocalizeText('generic.search') } + + + + { (mode === MODE_FRIENDS) && + + + + + + + + + + + } + { (mode === MODE_SEARCH) && + <> + } + + ); }; diff --git a/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx b/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx index f25c42f9..e0929968 100644 --- a/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx +++ b/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx @@ -1,37 +1,24 @@ -import { AcceptFriendMessageComposer, DeclineFriendMessageComposer } from '@nitrots/nitro-renderer'; -import { FC, useCallback } from 'react'; -import { SendMessageHook } from '../../../../hooks/messages/message-event'; +import { FC } from 'react'; +import { NitroCardAccordionItemView } from '../../../../layout'; import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView'; +import { useFriendsContext } from '../../context/FriendsContext'; import { FriendsRequestItemViewProps } from './FriendsRequestItemView.types'; export const FriendsRequestItemView: FC = props => { const { request = null } = props; - - const accept = useCallback(() => - { - if(!request) return; - - SendMessageHook(new AcceptFriendMessageComposer(request.id)); - }, [ request ]); - - const decline = useCallback(() => - { - if(!request) return; - - SendMessageHook(new DeclineFriendMessageComposer(false, request.id)); - }, [ request ]); + const { acceptFriend = null, declineFriend = null } = useFriendsContext(); if(!request) return null; return ( -
+
{ request.name }
- - + acceptFriend(request.requesterUserId) } /> + declineFriend(request.requesterUserId) } />
-
+ ); }; diff --git a/src/views/friends/views/friends-request/FriendsRequestView.tsx b/src/views/friends/views/friends-request/FriendsRequestView.tsx new file mode 100644 index 00000000..d2ac8bc7 --- /dev/null +++ b/src/views/friends/views/friends-request/FriendsRequestView.tsx @@ -0,0 +1,28 @@ +import { FC } from 'react'; +import { LocalizeText } from '../../../../api'; +import { NitroCardAccordionSetView, NitroLayoutButton, NitroLayoutFlex } from '../../../../layout'; +import { useFriendsContext } from '../../context/FriendsContext'; +import { FriendsRequestItemView } from '../friends-request-item/FriendsRequestItemView'; +import { FriendsRequestViewProps } from './FriendsRequestView.types'; + +export const FriendsRequestView: FC = props => +{ + const { requests = [] } = props; + const { declineFriend = null } = useFriendsContext(); + + if(!requests.length) return null; + + return ( + + { requests.map(request => + { + return + }) } + + declineFriend(-1, true) }> + { LocalizeText('friendlist.requests.dismissall') } + + + + ); +} diff --git a/src/views/friends/views/friends-request/FriendsRequestView.types.ts b/src/views/friends/views/friends-request/FriendsRequestView.types.ts new file mode 100644 index 00000000..adf39c13 --- /dev/null +++ b/src/views/friends/views/friends-request/FriendsRequestView.types.ts @@ -0,0 +1,6 @@ +import { MessengerRequest } from '../../common/MessengerRequest'; + +export interface FriendsRequestViewProps +{ + requests: MessengerRequest[]; +} diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index dac6a7a5..517280f6 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -1,6 +1,6 @@ -import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer, UserProfileComposer } from '@nitrots/nitro-renderer'; +import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer } from '@nitrots/nitro-renderer'; import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; +import { AddEventLinkTracker, GetUserProfile, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; import { FriendsMessengerIconEvent } from '../../../../events'; import { BatchUpdates, CreateMessageHook, dispatchUiEvent, SendMessageHook } from '../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; @@ -17,10 +17,9 @@ export const FriendsMessengerView: FC<{}> = props => const [ activeThreadIndex, setActiveThreadIndex ] = useState(-1); const [ hiddenThreadIndexes, setHiddenThreadIndexes ] = useState([]); const [ messageText, setMessageText ] = useState(''); - const { friendsState = null } = useFriendsContext(); - const { friends = [] } = friendsState; const messagesBox = useRef(); const [ updateValue, setUpdateValue ] = useState({}); + const { friends = [] } = useFriendsContext(); const followFriend = useCallback(() => { @@ -29,7 +28,7 @@ export const FriendsMessengerView: FC<{}> = props => const openProfile = useCallback(() => { - SendMessageHook(new UserProfileComposer(messageThreads[activeThreadIndex].participant.id)); + GetUserProfile(messageThreads[activeThreadIndex].participant.id); }, [ messageThreads, activeThreadIndex ]); const getFriend = useCallback((userId: number) =>