diff --git a/src/events/friend-list/FriendEnteredRoomEvent.ts b/src/events/friend-list/FriendEnteredRoomEvent.ts new file mode 100644 index 00000000..5a7755eb --- /dev/null +++ b/src/events/friend-list/FriendEnteredRoomEvent.ts @@ -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); + } +} diff --git a/src/events/friend-list/index.ts b/src/events/friend-list/index.ts index 413293c4..4789fde9 100644 --- a/src/events/friend-list/index.ts +++ b/src/events/friend-list/index.ts @@ -1 +1,2 @@ +export * from './FriendEnteredRoomEvent'; export * from './FriendListEvent'; diff --git a/src/views/friend-list/FriendListView.tsx b/src/views/friend-list/FriendListView.tsx index defd406c..a620c0ea 100644 --- a/src/views/friend-list/FriendListView.tsx +++ b/src/views/friend-list/FriendListView.tsx @@ -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 = 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 ( diff --git a/src/views/room/events/RoomWidgetObjectNameEvent.ts b/src/views/room/events/RoomWidgetObjectNameEvent.ts index 2a3773e4..87fbe42f 100644 --- a/src/views/room/events/RoomWidgetObjectNameEvent.ts +++ b/src/views/room/events/RoomWidgetObjectNameEvent.ts @@ -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; diff --git a/src/views/room/handlers/RoomWidgetInfostandHandler.ts b/src/views/room/handlers/RoomWidgetInfostandHandler.ts index 9ad903bf..287c980c 100644 --- a/src/views/room/handlers/RoomWidgetInfostandHandler.ts +++ b/src/views/room/handlers/RoomWidgetInfostandHandler.ts @@ -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; } diff --git a/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx b/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx index 7d06c1e3..34626ff8 100644 --- a/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx +++ b/src/views/room/widgets/avatar-info/AvatarInfoWidgetView.tsx @@ -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 = props => { const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const [ name, setName ] = useState(null); + const [ nameBubbles, setNameBubbles ] = useState([]); const [ infoStandEvent, setInfoStandEvent ] = useState(null); const [ isGameMode, setGameMode ] = useState(false); const [ isDancing, setIsDancing ] = useState(false); const [ isDecorating, setIsDecorating ] = useState(GetRoomSession().isDecorating); const [ rentableBotChatEvent, setRentableBotChatEvent ] = useState(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 = 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 = 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 = props => { if(!infoStandEvent) return; - console.log('tru') - setInfoStandEvent(null); }, [ infoStandEvent ]); @@ -142,26 +175,6 @@ export const AvatarInfoWidgetView: FC = 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 = 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 = props => return ; }, [ 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 ; + if(name) + { + const nameBubbleIndex = nameBubbles.findIndex(bubble => + { + return (bubble.roomIndex === name.roomIndex); + }); + + if(nameBubbleIndex > -1) removeNameBubble(nameBubbleIndex); + + return ; + } if(infoStandEvent) { @@ -210,7 +233,12 @@ export const AvatarInfoWidgetView: FC = 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 = 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 removeNameBubble(index) } />; + }) } { rentableBotChatEvent && } )