Add friend name bubbles

This commit is contained in:
Bill 2021-07-07 03:56:11 -04:00
parent eac7794091
commit f6194e7f13
6 changed files with 112 additions and 42 deletions

View File

@ -0,0 +1,11 @@
import { RoomWidgetObjectNameEvent } from '../../views/room/events';
export class FriendEnteredRoomEvent extends RoomWidgetObjectNameEvent
{
public static ENTERED: string = 'FERE_ENTERED';
constructor(roomIndex: number, category: number, id: number, name: string, userType: number)
{
super(FriendEnteredRoomEvent.ENTERED, roomIndex, category, id, name, userType);
}
}

View File

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

View File

@ -1,8 +1,10 @@
import { MessengerInitComposer } from 'nitro-renderer';
import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory } from 'nitro-renderer';
import React, { FC, useCallback, useEffect, useReducer, useState } from 'react';
import { createPortal } from 'react-dom';
import { FriendListEvent } from '../../events';
import { useUiEvent } from '../../hooks/events/ui/ui-event';
import { GetRoomSession } from '../../api';
import { FriendEnteredRoomEvent, FriendListEvent } from '../../events';
import { useRoomEngineEvent } from '../../hooks/events';
import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event';
import { SendMessageHook } from '../../hooks/messages/message-event';
import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardHeaderView, NitroCardView } from '../../layout';
import { LocalizeText } from '../../utils/LocalizeText';
@ -48,6 +50,30 @@ export const FriendListView: FC<FriendListViewProps> = props =>
SendMessageHook(new MessengerInitComposer());
}, []);
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) =>
{
const roomSession = GetRoomSession();
if(!roomSession) return;
if(event.category !== RoomObjectCategory.UNIT) return;
const userData = roomSession.userDataManager.getUserDataByIndex(event.objectId);
if(!userData) return;
const friend = friendListState.friends.find(friend =>
{
return (friend.id === userData.webID);
});
if(!friend) return;
dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type));
}, [ friendListState.friends ]);
useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent);
return (
<FriendListContextProvider value={ { friendListState, dispatchFriendListState } }>
<FriendListMessageHandler />

View File

@ -10,9 +10,9 @@ export class RoomWidgetObjectNameEvent extends RoomWidgetUpdateEvent
private _name: string;
private _userType: number;
constructor(roomIndex: number, category: number, id: number, name: string, userType: number)
constructor(type: string, roomIndex: number, category: number, id: number, name: string, userType: number)
{
super(RoomWidgetObjectNameEvent.TYPE);
super(type);
this._roomIndex = roomIndex;
this._category = category;

View File

@ -286,7 +286,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
}
}
if(name) this.container.eventDispatcher.dispatchEvent(new RoomWidgetObjectNameEvent(message.id, message.category, id, name, userType));
if(name) this.container.eventDispatcher.dispatchEvent(new RoomWidgetObjectNameEvent(RoomWidgetObjectNameEvent.TYPE, message.id, message.category, id, name, userType));
return null;
}

View File

@ -1,6 +1,8 @@
import { RoomEnterEffect, RoomObjectCategory } from 'nitro-renderer';
import { FC, useCallback, useMemo, useState } from 'react';
import { GetRoomSession, GetSessionDataManager } from '../../../../api';
import { FriendEnteredRoomEvent } from '../../../../events';
import { useUiEvent } from '../../../../hooks/events';
import { CreateEventDispatcherHook } from '../../../../hooks/events/event-dispatcher.base';
import { useRoomContext } from '../../context/RoomContext';
import { RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent } from '../../events';
@ -19,12 +21,35 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
{
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ name, setName ] = useState<RoomWidgetObjectNameEvent>(null);
const [ nameBubbles, setNameBubbles ] = useState<RoomWidgetObjectNameEvent[]>([]);
const [ infoStandEvent, setInfoStandEvent ] = useState<RoomWidgetUpdateInfostandEvent>(null);
const [ isGameMode, setGameMode ] = useState(false);
const [ isDancing, setIsDancing ] = useState(false);
const [ isDecorating, setIsDecorating ] = useState(GetRoomSession().isDecorating);
const [ rentableBotChatEvent, setRentableBotChatEvent ] = useState<RoomWidgetUpdateRentableBotChatEvent>(null);
const removeNameBubble = useCallback((index: number) =>
{
setNameBubbles(prevValue =>
{
const newValue = [ ...prevValue ];
newValue.splice(index, 1);
return newValue;
});
}, []);
const clearInfoStandEvent = useCallback(() =>
{
setInfoStandEvent(null);
}, []);
const clearName = useCallback(() =>
{
setName(null);
}, []);
const onRoomWidgetRoomEngineUpdateEvent = useCallback((event: RoomWidgetRoomEngineUpdateEvent) =>
{
switch(event.type)
@ -50,6 +75,16 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
if(event.id === name.id) setName(null);
}
if(event.category === RoomObjectCategory.UNIT)
{
const nameBubbleIndex = nameBubbles.findIndex(bubble =>
{
return (bubble.roomIndex === event.id);
});
if(nameBubbleIndex > -1) removeNameBubble(nameBubbleIndex);
}
if(infoStandEvent)
{
if(infoStandEvent instanceof RoomWidgetUpdateInfostandFurniEvent)
@ -67,7 +102,7 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
if(infoStandEvent.roomIndex === event.id) setInfoStandEvent(null);
}
}
}, [ name, infoStandEvent ]);
}, [ name, infoStandEvent, nameBubbles, removeNameBubble ]);
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.USER_REMOVED, eventDispatcher, onRoomObjectRemoved);
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED, eventDispatcher, onRoomObjectRemoved);
@ -104,8 +139,6 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
{
if(!infoStandEvent) return;
console.log('tru')
setInfoStandEvent(null);
}, [ infoStandEvent ]);
@ -142,26 +175,6 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
CreateEventDispatcherHook(RoomWidgetUpdateDanceStatusEvent.UPDATE_DANCE, eventDispatcher, onRoomWidgetUpdateDanceStatusEvent);
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
{
switch(event.type)
{
case RoomWidgetRoomObjectUpdateEvent.USER_ADDED: {
// bubble if friend
return;
}
case RoomWidgetRoomObjectUpdateEvent.OBJECT_SELECTED: {
// set if waiting for pet
return;
}
}
}, []);
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.USER_ADDED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_SELECTED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
const onRoomWidgetUpdateRentableBotChatEvent = useCallback((event: RoomWidgetUpdateRentableBotChatEvent) =>
{
setRentableBotChatEvent(event);
@ -169,6 +182,16 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
CreateEventDispatcherHook(RoomWidgetUpdateRentableBotChatEvent.UPDATE_CHAT, eventDispatcher, onRoomWidgetUpdateRentableBotChatEvent);
const onFriendEnteredRoomEvent = useCallback((event: FriendEnteredRoomEvent) =>
{
setNameBubbles(prevValue =>
{
return [ ...prevValue, event ];
})
}, []);
useUiEvent(FriendEnteredRoomEvent.ENTERED, onFriendEnteredRoomEvent);
const decorateView = useMemo(() =>
{
GetRoomSession().isDecorating = isDecorating;
@ -182,23 +205,23 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
return <AvatarInfoWidgetDecorateView userId={ userId } userName={ userName } roomIndex={ roomIndex } setIsDecorating={ setIsDecorating } />;
}, [ isDecorating ]);
const clearInfoStandEvent = useCallback(() =>
{
setInfoStandEvent(null);
}, []);
const clearName = useCallback(() =>
{
setName(null);
}, []);
const currentView = useMemo(() =>
{
if(isGameMode) return null;
if(decorateView) return decorateView;
if(name) return <AvatarInfoWidgetNameView nameData={ name } close={ clearName } />;
if(name)
{
const nameBubbleIndex = nameBubbles.findIndex(bubble =>
{
return (bubble.roomIndex === name.roomIndex);
});
if(nameBubbleIndex > -1) removeNameBubble(nameBubbleIndex);
return <AvatarInfoWidgetNameView nameData={ name } close={ clearName } />;
}
if(infoStandEvent)
{
@ -210,7 +233,12 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
if(event.isSpectatorMode) return null;
// if existing name bubble remove it
const nameBubbleIndex = nameBubbles.findIndex(bubble =>
{
return (bubble.roomIndex === event.roomIndex);
});
if(nameBubbleIndex > -1) removeNameBubble(nameBubbleIndex);
if(event.isOwnUser)
{
@ -241,11 +269,15 @@ export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props =>
}
return null;
}, [ isGameMode, decorateView, name, isDancing, infoStandEvent, clearName, clearInfoStandEvent ]);
}, [ isGameMode, decorateView, name, nameBubbles, isDancing, infoStandEvent, clearName, clearInfoStandEvent, removeNameBubble ]);
return (
<>
{ currentView }
{ (nameBubbles.length > 0) && nameBubbles.map((name, index) =>
{
return <AvatarInfoWidgetNameView nameData={ name } close={ () => removeNameBubble(index) } />;
}) }
{ rentableBotChatEvent && <AvatarInfoRentableBotChatView chatEvent={ rentableBotChatEvent } /> }
</>
)