Updates DONT TOUCH IT

This commit is contained in:
MyNameIsBatman 2021-09-16 01:37:17 -03:00
parent 8ad3c84dd6
commit 7926bb7469
34 changed files with 450 additions and 226 deletions

View File

@ -1,7 +1,7 @@
import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer'; import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer';
import { GetNitroInstance, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..'; import { GetNitroInstance, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..';
import { InventoryTradeRequestEvent, WiredSelectObjectEvent } from '../../../../../events'; import { InventoryTradeRequestEvent, WiredSelectObjectEvent } from '../../../../../events';
import { FriendListSendFriendRequestEvent } from '../../../../../events/friend-list/FriendListSendFriendRequestEvent'; import { FriendsSendFriendRequestEvent } from '../../../../../events/friends/FriendsSendFriendRequestEvent';
import { dispatchUiEvent } from '../../../../../hooks/events'; import { dispatchUiEvent } from '../../../../../hooks/events';
import { SendMessageHook } from '../../../../../hooks/messages'; import { SendMessageHook } from '../../../../../hooks/messages';
import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum'; import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum';
@ -76,7 +76,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO: case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO:
return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage)); return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage));
case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST: case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST:
dispatchUiEvent(new FriendListSendFriendRequestEvent(userId)); dispatchUiEvent(new FriendsSendFriendRequestEvent(userId));
break; break;
case RoomWidgetUserActionMessage.RESPECT_USER: case RoomWidgetUserActionMessage.RESPECT_USER:
GetSessionDataManager().giveRespect(userId); GetSessionDataManager().giveRespect(userId);

View File

@ -1,2 +0,0 @@
export * from './FriendEnteredRoomEvent';
export * from './FriendListEvent';

View File

@ -1,7 +1,7 @@
import { MessengerFriend } from '../../views/friends/common/MessengerFriend'; import { MessengerFriend } from '../../views/friends/common/MessengerFriend';
import { FriendListEvent } from './FriendListEvent'; import { FriendsEvent } from './FriendsEvent';
export class FriendListContentEvent extends FriendListEvent export class FriendListContentEvent extends FriendsEvent
{ {
public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT'; public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT';

View File

@ -1,8 +1,10 @@
import { NitroEvent } from '@nitrots/nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class FriendListEvent extends NitroEvent export class FriendsEvent extends NitroEvent
{ {
public static SHOW_FRIEND_LIST: string = 'IE_SHOW_FRIEND_LIST'; public static SHOW_FRIEND_LIST: string = 'IE_SHOW_FRIEND_LIST';
public static TOGGLE_FRIEND_LIST: string = 'IE_TOGGLE_FRIEND_LIST'; public static TOGGLE_FRIEND_LIST: string = 'IE_TOGGLE_FRIEND_LIST';
public static SHOW_FRIEND_MESSENGER: string = 'IE_SHOW_FRIEND_MESSENGER';
public static TOGGLE_FRIEND_MESSENGER: string = 'IE_TOGGLE_FRIEND_MESSENGER';
public static REQUEST_FRIEND_LIST: string = 'FLSFRE_REQUEST_FRIEND_LIST'; public static REQUEST_FRIEND_LIST: string = 'FLSFRE_REQUEST_FRIEND_LIST';
} }

View File

@ -1,6 +1,6 @@
import { FriendListEvent } from './FriendListEvent'; import { FriendsEvent } from './FriendsEvent';
export class FriendListSendFriendRequestEvent extends FriendListEvent export class FriendsSendFriendRequestEvent extends FriendsEvent
{ {
public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST'; public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST';
@ -8,7 +8,7 @@ export class FriendListSendFriendRequestEvent extends FriendListEvent
constructor(userId: number) constructor(userId: number)
{ {
super(FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST); super(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST);
this._userId = userId; this._userId = userId;
} }

View File

@ -0,0 +1,4 @@
export * from './FriendEnteredRoomEvent';
export * from './FriendListContentEvent';
export * from './FriendsEvent';
export * from './FriendsSendFriendRequestEvent';

View File

@ -1,7 +1,7 @@
export * from './avatar-editor'; export * from './avatar-editor';
export * from './camera'; export * from './camera';
export * from './catalog'; export * from './catalog';
export * from './friend-list'; export * from './friends';
export * from './inventory'; export * from './inventory';
export * from './navigator'; export * from './navigator';
export * from './notification-center'; export * from './notification-center';

View File

@ -1,73 +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 { useFriendListContext } from './context/FriendListContext';
import { FriendListMessageHandlerProps } from './FriendListMessageHandler.types';
import { FriendListActions } from './reducers/FriendListReducer';
export const FriendListMessageHandler: FC<FriendListMessageHandlerProps> = props =>
{
const { friendListState = null, dispatchFriendListState = null } = useFriendListContext();
const onMessengerInitEvent = useCallback((event: MessengerInitEvent) =>
{
const parser = event.getParser();
dispatchFriendListState({
type: FriendListActions.UPDATE_SETTINGS,
payload: {
settings: new MessengerSettings(
parser.userFriendLimit,
parser.normalFriendLimit,
parser.extendedFriendLimit,
parser.categories)
}
});
SendMessageHook(new GetFriendRequestsComposer());
}, [ dispatchFriendListState ]);
const onFriendListFragmentEvent = useCallback((event: FriendListFragmentEvent) =>
{
const parser = event.getParser();
dispatchFriendListState({
type: FriendListActions.PROCESS_FRAGMENT,
payload: {
fragment: parser.fragment
}
});
}, [ dispatchFriendListState ]);
const onFriendListUpdateEvent = useCallback((event: FriendListUpdateEvent) =>
{
const parser = event.getParser();
dispatchFriendListState({
type: FriendListActions.PROCESS_UPDATE,
payload: {
update: parser
}
});
}, [ dispatchFriendListState ]);
const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) =>
{
const parser = event.getParser();
dispatchFriendListState({
type: FriendListActions.PROCESS_REQUESTS,
payload: {
requests: parser.requests
}
});
}, [ dispatchFriendListState ]);
CreateMessageHook(MessengerInitEvent, onMessengerInitEvent);
CreateMessageHook(FriendListFragmentEvent, onFriendListFragmentEvent);
CreateMessageHook(FriendListUpdateEvent, onFriendListUpdateEvent);
CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent);
return null;
}

View File

@ -1,5 +0,0 @@
export interface FriendListMessageHandlerProps
{
}

View File

@ -0,0 +1,90 @@
import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent, NewConsoleMessageEvent } 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 { activeChats = [] } = friendsState;
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 ]);
const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) =>
{
const parser = event.getParser();
const activeChat = activeChats.find(c => c.friendId === parser.senderId);
if(activeChat)
{
}
else
{
}
}, [ friendsState, dispatchFriendsState ]);
CreateMessageHook(MessengerInitEvent, onMessengerInitEvent);
CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent);
CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent);
CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent);
CreateMessageHook(NewConsoleMessageEvent, onNewConsoleMessageEvent);
return null;
}

View File

@ -1,4 +1,4 @@
.nitro-friend-list { .nitro-friends {
width: 250px; width: 250px;
} }

View File

@ -1,54 +1,69 @@
import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer'; import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { GetRoomSession, LocalizeText } from '../../api'; import { GetRoomSession } from '../../api';
import { FriendEnteredRoomEvent, FriendListEvent } from '../../events'; import { FriendEnteredRoomEvent, FriendListContentEvent, FriendsEvent } from '../../events';
import { FriendListContentEvent } from '../../events/friend-list/FriendListContentEvent'; import { FriendsSendFriendRequestEvent } from '../../events/friends/FriendsSendFriendRequestEvent';
import { FriendListSendFriendRequestEvent } from '../../events/friend-list/FriendListSendFriendRequestEvent';
import { useRoomEngineEvent } from '../../hooks/events'; import { useRoomEngineEvent } from '../../hooks/events';
import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event'; import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event';
import { SendMessageHook } from '../../hooks/messages/message-event'; import { SendMessageHook } from '../../hooks/messages/message-event';
import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout'; import { FriendsContextProvider } from './context/FriendsContext';
import { FriendListContextProvider } from './context/FriendListContext'; import { FriendsMessageHandler } from './FriendsMessageHandler';
import { FriendListMessageHandler } from './FriendListMessageHandler'; import { FriendsReducer, initialFriends } from './reducers/FriendsReducer';
import { FriendListReducer, initialFriendList } from './reducers/FriendListReducer';
import { FriendBarView } from './views/friend-bar/FriendBarView'; import { FriendBarView } from './views/friend-bar/FriendBarView';
import { FriendsListView } from './views/list/FriendsListView'; import { FriendsListView } from './views/friends-list/FriendsListView';
import { FriendsMessengerView } from './views/messenger/FriendsMessengerView';
const TABS: string[] = ['friendlist.friends', 'generic.search'];
export const FriendsView: FC<{}> = props => export const FriendsView: FC<{}> = props =>
{ {
const [ friendListState, dispatchFriendListState ] = useReducer(FriendListReducer, initialFriendList); const [ friendsState, dispatchFriendsState ] = useReducer(FriendsReducer, initialFriends);
const { friends = null, requests = null, settings = null } = friendListState; const { friends = [], requests = [], settings = null } = friendsState;
const [ isVisible, setIsVisible ] = useState(false);
const [ isReady, setIsReady ] = useState(false); const [ isReady, setIsReady ] = useState(false);
const [ currentTab, setCurrentTab ] = useState<number>(0); const [ isListVisible, setIsListVisible ] = useState(false);
const [ isMessengerVisible, setIsMessengerVisible ] = useState(false);
const onFriendListEvent = useCallback((event: FriendListEvent) => useEffect(() =>
{
SendMessageHook(new MessengerInitComposer());
}, []);
useEffect(() =>
{
if(!settings) return;
setIsReady(true);
}, [ settings ]);
const onFriendsEvent = useCallback((event: FriendsEvent) =>
{ {
switch(event.type) switch(event.type)
{ {
case FriendListEvent.SHOW_FRIEND_LIST: case FriendsEvent.SHOW_FRIEND_LIST:
setIsVisible(true); setIsListVisible(true);
return; return;
case FriendListEvent.TOGGLE_FRIEND_LIST: case FriendsEvent.TOGGLE_FRIEND_LIST:
setIsVisible(value => !value); setIsListVisible(value => !value);
return; return;
case FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST: case FriendsEvent.SHOW_FRIEND_MESSENGER:
const requestEvent = (event as FriendListSendFriendRequestEvent); setIsMessengerVisible(true);
return; return;
case FriendListEvent.REQUEST_FRIEND_LIST: case FriendsEvent.TOGGLE_FRIEND_MESSENGER:
dispatchUiEvent(new FriendListContentEvent(friendListState.friends)); setIsMessengerVisible(value => !value);
return;
case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST:
const requestEvent = (event as FriendsSendFriendRequestEvent);
return;
case FriendsEvent.REQUEST_FRIEND_LIST:
dispatchUiEvent(new FriendListContentEvent(friendsState.friends));
return; return;
} }
}, [friendListState.friends]); }, [ friendsState.friends ]);
useUiEvent(FriendListEvent.SHOW_FRIEND_LIST, onFriendListEvent); useUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent);
useUiEvent(FriendListEvent.TOGGLE_FRIEND_LIST, onFriendListEvent); useUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent);
useUiEvent(FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendListEvent); useUiEvent(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendsEvent);
useUiEvent(FriendListEvent.REQUEST_FRIEND_LIST, onFriendListEvent); useUiEvent(FriendsEvent.REQUEST_FRIEND_LIST, onFriendsEvent);
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) => const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) =>
{ {
@ -62,7 +77,7 @@ export const FriendsView: FC<{}> = props =>
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return; if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
const friend = friendListState.friends.find(friend => const friend = friendsState.friends.find(friend =>
{ {
return (friend.id === userData.webID); return (friend.id === userData.webID);
}); });
@ -70,67 +85,26 @@ export const FriendsView: FC<{}> = props =>
if(!friend) return; if(!friend) return;
dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type)); dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type));
}, [ friendListState.friends ]); }, [ friendsState.friends ]);
useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent); useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent);
useEffect(() =>
{
if(!settings) return;
setIsReady(true);
}, [ settings ]);
useEffect(() =>
{
SendMessageHook(new MessengerInitComposer());
}, []);
const onlineFriends = useMemo(() => const onlineFriends = useMemo(() =>
{ {
if(!friends) return [];
return friends.filter(f => f.online); return friends.filter(f => f.online);
}, [ friends ]); }, [ friends ]);
const offlineFriends = useMemo(() => const offlineFriends = useMemo(() =>
{ {
if(!friends) return [];
return friends.filter(f => !f.online); return friends.filter(f => !f.online);
}, [ friends ]); }, [ friends ]);
return ( return (
<FriendListContextProvider value={ { friendListState, dispatchFriendListState } }> <FriendsContextProvider value={ { friendsState, dispatchFriendsState } }>
<FriendListMessageHandler /> <FriendsMessageHandler />
{ isReady && createPortal(<FriendBarView />, document.getElementById('toolbar-friend-bar-container')) } { isReady && createPortal(<FriendBarView />, document.getElementById('toolbar-friend-bar-container')) }
{ isVisible && { isListVisible && <FriendsListView onlineFriends={ onlineFriends } offlineFriends={ offlineFriends } friendRequests={ requests } onCloseClick={ () => setIsListVisible(false) } /> }
<NitroCardView className="nitro-friend-list"> { isMessengerVisible && <FriendsMessengerView /> }
<NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ () => setIsVisible(false) } /> </FriendsContextProvider>
<NitroCardContentView className="p-0">
<NitroCardTabsView>
{ TABS.map((tab, index) =>
{
return (<NitroCardTabsItemView key={ index } isActive={ currentTab === index } onClick={ () => setCurrentTab(index) }>
{ LocalizeText(tab) }
</NitroCardTabsItemView>);
}) }
</NitroCardTabsView>
<div className="text-black">
{ currentTab === 0 && <NitroCardAccordionView>
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends') + ` (${onlineFriends.length})` } defaultState={ true }>
<FriendsListView list={ onlineFriends } />
</NitroCardAccordionItemView>
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends.offlinecaption') + ` (${offlineFriends.length})` }>
<FriendsListView list={ offlineFriends } />
</NitroCardAccordionItemView>
{ requests.length > 0 && <NitroCardAccordionItemView headerText={ LocalizeText('friendlist.tab.friendrequests') + ` (${requests.length})` }>
<FriendsListView list={ requests } />
</NitroCardAccordionItemView> }
</NitroCardAccordionView> }
</div>
</NitroCardContentView>
</NitroCardView> }
</FriendListContextProvider>
); );
} }

View File

@ -0,0 +1,34 @@
import { MessengerChatMessage } from './MessengerChatMessage';
export class MessengerChat
{
private _friendId: number;
private _isRead: boolean;
private _messages: MessengerChatMessage[];
constructor(friendId: number, isRead: boolean = true)
{
this._friendId = friendId;
this._isRead = isRead;
this._messages = [];
}
public addMessage(): void
{
this._messages.push();
}
public get friendId(): number
{
return this._friendId;
}
public get isRead(): boolean
{
return this._isRead;
}
public get messages(): MessengerChatMessage[]
{
return this._messages;
}
}

View File

@ -0,0 +1,13 @@
export class MessengerChatMessage
{
private _type: number;
private _senderId: number;
private _message: string;
private _extraData: string;
private _sentAt: number;
constructor(type: number, senderId: number, message: string, extraData: string, sentAt: number)
{
}
}

View File

@ -1,14 +0,0 @@
import { createContext, FC, useContext } from 'react';
import { FriendListContextProps, IFriendListContext } from './FriendListContext.type';
const FriendListContext = createContext<IFriendListContext>({
friendListState: null,
dispatchFriendListState: null
});
export const FriendListContextProvider: FC<FriendListContextProps> = props =>
{
return <FriendListContext.Provider value={ props.value }>{ props.children }</FriendListContext.Provider>
}
export const useFriendListContext = () => useContext(FriendListContext);

View File

@ -1,13 +0,0 @@
import { Dispatch, ProviderProps } from 'react';
import { IFriendListAction, IFriendListState } from '../reducers/FriendListReducer';
export interface IFriendListContext
{
friendListState: IFriendListState;
dispatchFriendListState: Dispatch<IFriendListAction>;
}
export interface FriendListContextProps extends ProviderProps<IFriendListContext>
{
}

View File

@ -0,0 +1,14 @@
import { createContext, FC, useContext } from 'react';
import { FriendsContextProps, IFriendsContext } from './FriendsContext.type';
const FriendsContext = createContext<IFriendsContext>({
friendsState: null,
dispatchFriendsState: null
});
export const FriendsContextProvider: FC<FriendsContextProps> = props =>
{
return <FriendsContext.Provider value={ props.value }>{ props.children }</FriendsContext.Provider>
}
export const useFriendsContext = () => useContext(FriendsContext);

View File

@ -0,0 +1,13 @@
import { Dispatch, ProviderProps } from 'react';
import { IFriendsAction, IFriendsState } from '../reducers/FriendsReducer';
export interface IFriendsContext
{
friendsState: IFriendsState;
dispatchFriendsState: Dispatch<IFriendsAction>;
}
export interface FriendsContextProps extends ProviderProps<IFriendsContext>
{
}

View File

@ -1,5 +1,6 @@
import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer'; import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer';
import { Reducer } from 'react'; import { Reducer } from 'react';
import { MessengerChat } from '../common/MessengerChat';
import { MessengerFriend } from '../common/MessengerFriend'; import { MessengerFriend } from '../common/MessengerFriend';
import { MessengerRequest } from '../common/MessengerRequest'; import { MessengerRequest } from '../common/MessengerRequest';
import { MessengerSettings } from '../common/MessengerSettings'; import { MessengerSettings } from '../common/MessengerSettings';
@ -11,14 +12,15 @@ function compareName(a, b)
return 0; return 0;
} }
export interface IFriendListState export interface IFriendsState
{ {
settings: MessengerSettings; settings: MessengerSettings;
friends: MessengerFriend[]; friends: MessengerFriend[];
requests: MessengerRequest[]; requests: MessengerRequest[];
activeChats: MessengerChat[];
} }
export interface IFriendListAction export interface IFriendsAction
{ {
type: string; type: string;
payload: { payload: {
@ -26,34 +28,37 @@ export interface IFriendListAction
fragment?: FriendParser[]; fragment?: FriendParser[];
update?: FriendListUpdateParser; update?: FriendListUpdateParser;
requests?: FriendRequestData[]; requests?: FriendRequestData[];
chats?: MessengerChat[];
} }
} }
export class FriendListActions export class FriendsActions
{ {
public static RESET_STATE: string = 'FLA_RESET_STATE'; public static RESET_STATE: string = 'FA_RESET_STATE';
public static UPDATE_SETTINGS: string = 'FLA_UPDATE_SETTINGS'; public static UPDATE_SETTINGS: string = 'FA_UPDATE_SETTINGS';
public static PROCESS_FRAGMENT: string = 'FLA_PROCESS_FRAGMENT'; public static PROCESS_FRAGMENT: string = 'FA_PROCESS_FRAGMENT';
public static PROCESS_UPDATE: string = 'FLA_PROCESS_UPDATE'; public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE';
public static PROCESS_REQUESTS: string = 'FLA_PROCESS_REQUESTS'; public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS';
public static SET_ACTIVE_CHATS: string = 'FA_SET_ACTIVE_CHATS';
} }
export const initialFriendList: IFriendListState = { export const initialFriends: IFriendsState = {
settings: null, settings: null,
friends: [], friends: [],
requests: [] requests: [],
activeChats: []
} }
export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (state, action) => export const FriendsReducer: Reducer<IFriendsState, IFriendsAction> = (state, action) =>
{ {
switch(action.type) switch(action.type)
{ {
case FriendListActions.UPDATE_SETTINGS: { case FriendsActions.UPDATE_SETTINGS: {
const settings = (action.payload.settings || state.settings || null); const settings = (action.payload.settings || state.settings || null);
return { ...state, settings }; return { ...state, settings };
} }
case FriendListActions.PROCESS_FRAGMENT: { case FriendsActions.PROCESS_FRAGMENT: {
const fragment = (action.payload.fragment || null); const fragment = (action.payload.fragment || null);
let friends = [ ...state.friends ]; let friends = [ ...state.friends ];
@ -85,7 +90,7 @@ export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (
return { ...state, friends }; return { ...state, friends };
} }
case FriendListActions.PROCESS_UPDATE: { case FriendsActions.PROCESS_UPDATE: {
const update = (action.payload.update || null); const update = (action.payload.update || null);
let friends = [ ...state.friends ]; let friends = [ ...state.friends ];
@ -118,7 +123,7 @@ export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (
return { ...state, friends }; return { ...state, friends };
} }
case FriendListActions.PROCESS_REQUESTS: { case FriendsActions.PROCESS_REQUESTS: {
const newRequests = (action.payload.requests || null); const newRequests = (action.payload.requests || null);
let requests = [ ...state.requests ]; let requests = [ ...state.requests ];
@ -133,6 +138,11 @@ export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (
return { ...state, requests }; return { ...state, requests };
} }
case FriendsActions.SET_ACTIVE_CHATS: {
const activeChats = (action.payload.chats || []);
return { ...state, activeChats };
}
default: default:
return state; return state;
} }

View File

@ -1,12 +1,12 @@
import { FC, useMemo, useState } from 'react'; import { FC, useMemo, useState } from 'react';
import { useFriendListContext } from '../../context/FriendListContext'; import { useFriendsContext } from '../../context/FriendsContext';
import { FriendBarItemView } from '../friend-bar-item/FriendBarItemView'; import { FriendBarItemView } from '../friend-bar-item/FriendBarItemView';
import { FriendBarViewProps } from './FriendBarView.types'; import { FriendBarViewProps } from './FriendBarView.types';
export const FriendBarView: FC<FriendBarViewProps> = props => export const FriendBarView: FC<FriendBarViewProps> = props =>
{ {
const { friendListState = null } = useFriendListContext(); const { friendsState = null } = useFriendsContext();
const { friends = null } = friendListState; const { friends = null } = friendsState;
const [ indexOffset, setIndexOffset ] = useState(0); const [ indexOffset, setIndexOffset ] = useState(0);
const [ maxDisplayCount, setMaxDisplayCount ] = useState(3); const [ maxDisplayCount, setMaxDisplayCount ] = useState(3);

View File

@ -1,4 +1,5 @@
import { FollowFriendMessageComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; import { SetRelationshipStatusComposer } from '@nitrots/nitro-renderer';
import { FollowFriendMessageComposer } from '@nitrots/nitro-renderer/src/nitro/communication/messages/outgoing/friendlist/FollowFriendMessageComposer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { LocalizeText } from '../../../../api'; import { LocalizeText } from '../../../../api';
import { SendMessageHook } from '../../../../hooks'; import { SendMessageHook } from '../../../../hooks';

View File

@ -0,0 +1,63 @@
import { FollowFriendMessageComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { LocalizeText } from '../../../../api';
import { SendMessageHook } from '../../../../hooks';
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
import { MessengerFriend } from '../../common/MessengerFriend';
import { FriendsGroupItemViewProps } from './FriendsGroupItemView.types';
export const FriendsGroupItemView: FC<FriendsGroupItemViewProps> = props =>
{
const { friend = null } = props;
const [ isExpanded, setIsExpanded ] = useState<boolean>(false);
const followFriend = useCallback(() =>
{
if(!friend) return;
SendMessageHook(new FollowFriendMessageComposer(friend.id));
}, [ friend ]);
const getCurrentRelationshipName = useCallback(() =>
{
if(!friend) return 'none';
switch(friend.relationshipStatus)
{
case MessengerFriend.RELATIONSHIP_HEART: return 'heart';
case MessengerFriend.RELATIONSHIP_SMILE: return 'smile';
case MessengerFriend.RELATIONSHIP_BOBBA: return 'bobba';
default: return 'none';
}
}, [ friend ]);
const updateRelationship = useCallback((type: number) =>
{
if(type !== friend.relationshipStatus) SendMessageHook(new SetRelationshipStatusComposer(friend.id, type));
setIsExpanded(false);
}, [ friend ]);
if(!friend) return null;
return (
<div className="px-2 py-1 d-flex gap-1 align-items-center">
<UserProfileIconView userId={ friend.id } />
<div>{ friend.name }</div>
<div className="ms-auto d-flex align-items-center gap-1">
{ !isExpanded && <>
{ friend.followingAllowed && <i onClick={ followFriend } className="icon icon-friendlist-follow cursor-pointer" title={ LocalizeText('friendlist.tip.follow') } /> }
{ friend.online && <i className="icon icon-friendlist-chat cursor-pointer" title={ LocalizeText('friendlist.tip.im') } /> }
<i className={ 'icon cursor-pointer icon-relationship-' + getCurrentRelationshipName() } onClick={ () => setIsExpanded(true) } title={ LocalizeText('infostand.link.relationship') } />
</> }
{ isExpanded && <>
<i className="icon icon-relationship-heart cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_HEART) } />
<i className="icon icon-relationship-smile cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_SMILE) } />
<i className="icon icon-relationship-bobba cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_BOBBA) } />
<i className="icon icon-relationship-none cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_NONE) } />
</> }
</div>
</div>
);
}

View File

@ -0,0 +1,6 @@
import { MessengerFriend } from '../../common/MessengerFriend';
export interface FriendsGroupItemViewProps
{
friend: MessengerFriend;
}

View File

@ -1,11 +1,11 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { MessengerFriend } from '../../common/MessengerFriend'; import { MessengerFriend } from '../../common/MessengerFriend';
import { MessengerRequest } from '../../common/MessengerRequest'; import { MessengerRequest } from '../../common/MessengerRequest';
import { FriendsListItemView } from '../friend-item/FriendsListItemView'; import { FriendsGroupItemView } from '../friends-group-item/FriendsGroupItemView';
import { FriendsRequestItemView } from '../request-item/FriendsRequestItemView'; import { FriendsRequestItemView } from '../friends-request-item/FriendsRequestItemView';
import { FriendsListViewProps } from './FriendsListView.types'; import { FriendsGroupViewProps } from './FriendsGroupView.types';
export const FriendsListView: FC<FriendsListViewProps> = props => export const FriendsGroupView: FC<FriendsGroupViewProps> = props =>
{ {
const { list = null } = props; const { list = null } = props;
@ -15,7 +15,7 @@ export const FriendsListView: FC<FriendsListViewProps> = props =>
{ list.map((item, index) => { list.map((item, index) =>
{ {
if(item instanceof MessengerFriend) if(item instanceof MessengerFriend)
return <FriendsListItemView key={ index } friend={ item } /> return <FriendsGroupItemView key={ index } friend={ item } />
else if(item instanceof MessengerRequest) else if(item instanceof MessengerRequest)
return <FriendsRequestItemView key={ index } request={ item } /> return <FriendsRequestItemView key={ index } request={ item } />
else else

View File

@ -1,7 +1,7 @@
import { MessengerFriend } from '../../common/MessengerFriend'; import { MessengerFriend } from '../../common/MessengerFriend';
import { MessengerRequest } from '../../common/MessengerRequest'; import { MessengerRequest } from '../../common/MessengerRequest';
export interface FriendsListViewProps export interface FriendsGroupViewProps
{ {
list: MessengerFriend[] | MessengerRequest[]; list: MessengerFriend[] | MessengerRequest[];
} }

View File

@ -0,0 +1,43 @@
import { FC, useState } from 'react';
import { LocalizeText } from '../../../../api';
import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
import { FriendsGroupView } from '../friends-group/FriendsGroupView';
import { FriendsListViewProps } from './FriendsListView.types';
const TABS: string[] = ['friendlist.friends', 'generic.search'];
export const FriendsListView: FC<FriendsListViewProps> = props =>
{
const { onlineFriends = [], offlineFriends = [], friendRequests = [], onCloseClick = null } = props;
const [ currentTab, setCurrentTab ] = useState<number>(0);
return (
<NitroCardView className="nitro-friends">
<NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ onCloseClick } />
<NitroCardContentView className="p-0">
<NitroCardTabsView>
{ TABS.map((tab, index) =>
{
return (<NitroCardTabsItemView key={ index } isActive={ currentTab === index } onClick={ () => setCurrentTab(index) }>
{ LocalizeText(tab) }
</NitroCardTabsItemView>);
}) }
</NitroCardTabsView>
<div className="text-black">
{ currentTab === 0 && <NitroCardAccordionView>
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends') + ` (${onlineFriends.length})` } defaultState={ true }>
<FriendsGroupView list={ onlineFriends } />
</NitroCardAccordionItemView>
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends.offlinecaption') + ` (${offlineFriends.length})` }>
<FriendsGroupView list={ offlineFriends } />
</NitroCardAccordionItemView>
{ friendRequests.length > 0 && <NitroCardAccordionItemView headerText={ LocalizeText('friendlist.tab.friendrequests') + ` (${friendRequests.length})` }>
<FriendsGroupView list={ friendRequests } />
</NitroCardAccordionItemView> }
</NitroCardAccordionView> }
</div>
</NitroCardContentView>
</NitroCardView>
);
};

View File

@ -0,0 +1,9 @@
import { MessengerFriend } from './../../common/MessengerFriend';
import { MessengerRequest } from './../../common/MessengerRequest';
export interface FriendsListViewProps
{
onCloseClick: () => void;
onlineFriends: MessengerFriend[];
offlineFriends: MessengerFriend[];
friendRequests: MessengerRequest[];
}

View File

@ -0,0 +1,37 @@
import { AcceptFriendMessageComposer, DeclineFriendMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
import { SendMessageHook } from '../../../../hooks/messages/message-event';
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
import { FriendsRequestItemViewProps } from './FriendsRequestItemView.types';
export const FriendsRequestItemView: FC<FriendsRequestItemViewProps> = 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 ]);
if(!request) return null;
return (
<div className="px-2 py-1 d-flex gap-1 align-items-center">
<UserProfileIconView userId={ request.id } />
<div>{ request.name }</div>
<div className="ms-auto d-flex align-items-center gap-1">
<i className="icon icon-accept cursor-pointer" onClick={ accept } />
<i className="icon icon-deny cursor-pointer" onClick={ decline } />
</div>
</div>
);
};

View File

@ -0,0 +1,6 @@
import { MessengerRequest } from '../../common/MessengerRequest';
export interface FriendsRequestItemViewProps
{
request: MessengerRequest;
}

View File

@ -0,0 +1,13 @@
import { FC } from 'react';
import { LocalizeText } from '../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
export const FriendsMessengerView: FC<{}> = props =>
{
return (<NitroCardView className="nitro-friends-messenger" simple={ true }>
<NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ () => {} } />
<NitroCardContentView className="p-0">
</NitroCardContentView>
</NitroCardView>);
};

View File

@ -1,5 +1,4 @@
import { MessengerRequest } from '../../common/MessengerRequest'; import { MessengerRequest } from './../../common/MessengerRequest';
export interface FriendsRequestItemViewProps export interface FriendsRequestItemViewProps
{ {
request: MessengerRequest; request: MessengerRequest;

View File

@ -1,8 +1,8 @@
import { RoomBannedUsersComposer, RoomBannedUsersEvent, RoomSettingsEvent, RoomUsersWithRightsComposer, RoomUsersWithRightsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer'; import { RoomBannedUsersComposer, RoomBannedUsersEvent, RoomSettingsEvent, RoomUsersWithRightsComposer, RoomUsersWithRightsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../api'; import { LocalizeText } from '../../../../api';
import { FriendListEvent } from '../../../../events'; import { FriendsEvent } from '../../../../events';
import { FriendListContentEvent } from '../../../../events/friend-list/FriendListContentEvent'; import { FriendListContentEvent } from '../../../../events/friends/FriendListContentEvent';
import { dispatchUiEvent, useUiEvent } from '../../../../hooks'; import { dispatchUiEvent, useUiEvent } from '../../../../hooks';
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages'; import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout'; import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
@ -87,7 +87,7 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
useEffect(() => useEffect(() =>
{ {
if(roomSettingsData) dispatchUiEvent(new FriendListEvent(FriendListEvent.REQUEST_FRIEND_LIST)); if(roomSettingsData) dispatchUiEvent(new FriendsEvent(FriendsEvent.REQUEST_FRIEND_LIST));
}, [roomSettingsData]) }, [roomSettingsData])
const save = useCallback((data: RoomSettingsData) => const save = useCallback((data: RoomSettingsData) =>

View File

@ -1,7 +1,7 @@
import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, UserProfileComposer, Wait } from '@nitrots/nitro-renderer'; import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, UserProfileComposer, Wait } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop } from '../../api'; import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop } from '../../api';
import { AvatarEditorEvent, CatalogEvent, FriendListEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; import { AvatarEditorEvent, CatalogEvent, FriendsEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events';
import { AchievementsUIEvent } from '../../events/achievements'; import { AchievementsUIEvent } from '../../events/achievements';
import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent'; import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent';
import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent';
@ -107,7 +107,7 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
dispatchUiEvent(new CatalogEvent(CatalogEvent.TOGGLE_CATALOG)); dispatchUiEvent(new CatalogEvent(CatalogEvent.TOGGLE_CATALOG));
return; return;
case ToolbarViewItems.FRIEND_LIST_ITEM: case ToolbarViewItems.FRIEND_LIST_ITEM:
dispatchUiEvent(new CatalogEvent(FriendListEvent.TOGGLE_FRIEND_LIST)); dispatchUiEvent(new CatalogEvent(FriendsEvent.TOGGLE_FRIEND_LIST));
return; return;
case ToolbarViewItems.CAMERA_ITEM: case ToolbarViewItems.CAMERA_ITEM:
dispatchUiEvent(new RoomWidgetCameraEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA)); dispatchUiEvent(new RoomWidgetCameraEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA));