import { AddLinkEventTracker, GetRoomEngine, GetSessionDataManager, ILinkEventTracker, RemoveLinkEventTracker, RoomEngineEvent, RoomEngineObjectEvent, RoomEnterEffect, RoomSessionDanceEvent } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; import { AvatarInfoFurni, AvatarInfoPet, AvatarInfoRentableBot, AvatarInfoUser, GetConfigurationValue, RoomWidgetUpdateRentableBotChatEvent } from '../../../../api'; import { Column, LayoutFurniIconImageView } from '../../../../common'; import { useAvatarInfoWidget, useNitroEvent, useRoom, useUiEvent } from '../../../../hooks'; import { AvatarInfoPetTrainingPanelView } from './AvatarInfoPetTrainingPanelView'; import { AvatarInfoRentableBotChatView } from './AvatarInfoRentableBotChatView'; import { AvatarInfoUseProductConfirmView } from './AvatarInfoUseProductConfirmView'; import { AvatarInfoUseProductView } from './AvatarInfoUseProductView'; import { InfoStandWidgetBotView } from './infostand/InfoStandWidgetBotView'; import { InfoStandWidgetFurniView } from './infostand/InfoStandWidgetFurniView'; import { InfoStandWidgetPetView } from './infostand/InfoStandWidgetPetView'; import { InfoStandWidgetRentableBotView } from './infostand/InfoStandWidgetRentableBotView'; import { InfoStandWidgetUserView } from './infostand/InfoStandWidgetUserView'; import { AvatarInfoWidgetAvatarView } from './menu/AvatarInfoWidgetAvatarView'; import { AvatarInfoWidgetDecorateView } from './menu/AvatarInfoWidgetDecorateView'; import { AvatarInfoWidgetFurniView } from './menu/AvatarInfoWidgetFurniView'; import { AvatarInfoWidgetNameView } from './menu/AvatarInfoWidgetNameView'; import { AvatarInfoWidgetOwnAvatarView } from './menu/AvatarInfoWidgetOwnAvatarView'; import { AvatarInfoWidgetOwnPetView } from './menu/AvatarInfoWidgetOwnPetView'; import { AvatarInfoWidgetPetView } from './menu/AvatarInfoWidgetPetView'; import { AvatarInfoWidgetRentableBotView } from './menu/AvatarInfoWidgetRentableBotView'; export const AvatarInfoWidgetView: FC<{}> = props => { const BLOCK_MENU_WINDOW_MS = 500; const BLOCK_ROTATE_WINDOW_MS = 500; const [ isGameMode, setGameMode ] = useState(false); const [ isDancing, setIsDancing ] = useState(false); const [ isTouchLayout, setIsTouchLayout ] = useState(false); const [ mobileFurniDetailsOpen, setMobileFurniDetailsOpen ] = useState(false); const [ mobileUserDetailsOpen, setMobileUserDetailsOpen ] = useState(false); const [ rentableBotChatEvent, setRentableBotChatEvent ] = useState(null); const { avatarInfo = null, setAvatarInfo = null, activeNameBubble = null, setActiveNameBubble = null, nameBubbles = [], removeNameBubble = null, productBubbles = [], confirmingProduct = null, updateConfirmingProduct = null, removeProductBubble = null, isDecorating = false, setIsDecorating = null } = useAvatarInfoWidget(); const { roomSession = null } = useRoom(); const updateAvatarClickControl = (updates: { suppressMenuUntil?: number; suppressRotateUntil?: number; }) => { const globalScope = (globalThis as any); if(!globalScope.__nitroAvatarClickControl) { globalScope.__nitroAvatarClickControl = { suppressMenuUntil: 0, suppressRotateUntil: 0 }; } Object.assign(globalScope.__nitroAvatarClickControl, updates); }; useNitroEvent(RoomEngineEvent.NORMAL_MODE, event => { if(isGameMode) setGameMode(false); }); useNitroEvent(RoomEngineEvent.GAME_MODE, event => { if(!isGameMode) setGameMode(true); }); useEffect(() => { const query = window.matchMedia('(pointer: coarse), (hover: none)'); const updateTouchLayout = () => setIsTouchLayout(query.matches); updateTouchLayout(); query.addEventListener('change', updateTouchLayout); return () => query.removeEventListener('change', updateTouchLayout); }, []); useNitroEvent(RoomSessionDanceEvent.RSDE_DANCE, event => { if(event.roomIndex !== roomSession.ownRoomIndex) return; setIsDancing((event.danceId !== 0)); }); useUiEvent(RoomWidgetUpdateRentableBotChatEvent.UPDATE_CHAT, event => setRentableBotChatEvent(event)); useNitroEvent(RoomEngineObjectEvent.REQUEST_MANIPULATION, event => { if(event.category !== avatarInfo?.category || event.objectId !== avatarInfo?.id) return; setMobileFurniDetailsOpen(false); }); useEffect(() => { const linkTracker: ILinkEventTracker = { linkReceived: (url: string) => { const parts = url.split('/'); if(parts.length < 2) return; switch(parts[1]) { case 'hide': setAvatarInfo(null); setActiveNameBubble(null); if(roomSession) GetRoomEngine().clearSelectedAvatar(roomSession.roomId); return; case 'block-menu': updateAvatarClickControl({ suppressMenuUntil: Date.now() + BLOCK_MENU_WINDOW_MS }); setAvatarInfo(null); setActiveNameBubble(null); return; case 'block-rotate': updateAvatarClickControl({ suppressRotateUntil: Date.now() + BLOCK_ROTATE_WINDOW_MS }); return; } }, eventUrlPrefix: 'avatar-info/' }; AddLinkEventTracker(linkTracker); return () => RemoveLinkEventTracker(linkTracker); }, [ roomSession, setActiveNameBubble, setAvatarInfo ]); useEffect(() => { if(avatarInfo?.type !== AvatarInfoFurni.FURNI) { setMobileFurniDetailsOpen(false); } if(avatarInfo?.type !== AvatarInfoUser.OWN_USER && avatarInfo?.type !== AvatarInfoUser.PEER) { setMobileUserDetailsOpen(false); } }, [ avatarInfo ]); const getMenuView = () => { if(!roomSession || isGameMode) return null; if(activeNameBubble) return setActiveNameBubble(null) } />; if(avatarInfo) { switch(avatarInfo.type) { case AvatarInfoFurni.FURNI: { const info = (avatarInfo as AvatarInfoFurni); if(!isDecorating) return null; return setAvatarInfo(null) } />; } case AvatarInfoUser.OWN_USER: case AvatarInfoUser.PEER: { const info = (avatarInfo as AvatarInfoUser); if(isTouchLayout && !mobileUserDetailsOpen) return null; if(GetConfigurationValue('user.tags.enabled')) GetSessionDataManager().getUserTags(info.roomIndex); if(info.isSpectatorMode) return null; if(info.isOwnUser) { if(RoomEnterEffect.isRunning()) return null; return setAvatarInfo(null) } />; } return setAvatarInfo(null) } />; } case AvatarInfoPet.PET_INFO: { const info = (avatarInfo as AvatarInfoPet); if(info.isOwner) return setAvatarInfo(null) } />; return setAvatarInfo(null) } />; } case AvatarInfoRentableBot.RENTABLE_BOT: { return setAvatarInfo(null) } />; } } } return null; }; const getInfostandView = () => { if(!avatarInfo) return null; switch(avatarInfo.type) { case AvatarInfoFurni.FURNI: if(isTouchLayout && !isDecorating) { const info = (avatarInfo as AvatarInfoFurni); if(!mobileFurniDetailsOpen) { return ( ); } } return setAvatarInfo(null) } />; case AvatarInfoUser.OWN_USER: case AvatarInfoUser.PEER: if(isTouchLayout) { const info = (avatarInfo as AvatarInfoUser); const figure = encodeURIComponent(info.figure || ''); const avatarHeadUrl = `https://www.habbo.com/habbo-imaging/avatarimage?figure=${ figure }&direction=2&head_direction=2&gesture=sml&size=m&headonly=1`; if(!mobileUserDetailsOpen) { return ( ); } } return setAvatarInfo(null) } />; case AvatarInfoUser.BOT: return setAvatarInfo(null) } />; case AvatarInfoRentableBot.RENTABLE_BOT: return setAvatarInfo(null) } />; case AvatarInfoPet.PET_INFO: return setAvatarInfo(null) } />; } }; return ( <> { isDecorating && } { getMenuView() } { avatarInfo && { getInfostandView() } } { (nameBubbles.length > 0) && nameBubbles.map((name, index) => removeNameBubble(index) } />) } { (productBubbles.length > 0) && productBubbles.map((item, index) => { return removeProductBubble(index) } />; }) } { rentableBotChatEvent && setRentableBotChatEvent(null) } /> } { confirmingProduct && updateConfirmingProduct(null) } /> } ); };