diff --git a/src/components/room/widgets/avatar-info/AvatarInfoWidgetView.tsx b/src/components/room/widgets/avatar-info/AvatarInfoWidgetView.tsx index e76bda7..c6bcdd4 100644 --- a/src/components/room/widgets/avatar-info/AvatarInfoWidgetView.tsx +++ b/src/components/room/widgets/avatar-info/AvatarInfoWidgetView.tsx @@ -8,6 +8,7 @@ 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'; @@ -135,4 +136,4 @@ export const AvatarInfoWidgetView: FC<{}> = props => ) -} +} \ No newline at end of file diff --git a/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetFurniView.tsx b/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetFurniView.tsx index 087ab94..33ea96f 100644 --- a/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetFurniView.tsx +++ b/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetFurniView.tsx @@ -1,252 +1,488 @@ -import { RelationshipStatusInfoEvent, RelationshipStatusInfoMessageParser, RoomSessionFavoriteGroupUpdateEvent, RoomSessionUserBadgesEvent, RoomSessionUserFigureUpdateEvent, UserRelationshipsComposer } from '@nitrots/nitro-renderer'; -import { Dispatch, FC, FocusEvent, KeyboardEvent, SetStateAction, useEffect, useState } from 'react'; -import { FaPencilAlt, FaTimes } from 'react-icons/fa'; -import { AvatarInfoUser, CloneObject, GetConfiguration, GetGroupInformation, GetSessionDataManager, GetUserProfile, LocalizeText, SendMessageComposer } from '../../../../../api'; -import { Base, Column, Flex, LayoutAvatarImageView, LayoutBadgeImageView, Text, UserProfileIconView } from '../../../../../common'; -import { useMessageEvent, useRoom, useRoomSessionManagerEvent } from '../../../../../hooks'; -import { InfoStandWidgetUserRelationshipsView } from './InfoStandWidgetUserRelationshipsView'; -import { InfoStandWidgetUserTagsView } from './InfoStandWidgetUserTagsView'; -import { BackgroundsView } from '../../../../backgrounds/BackgroundsView'; +import { CrackableDataType, GroupInformationComposer, GroupInformationEvent, NowPlayingEvent, RoomControllerLevel, RoomObjectCategory, RoomObjectOperationType, RoomObjectVariable, RoomWidgetEnumItemExtradataParameter, RoomWidgetFurniInfoUsagePolicyEnum, SetObjectDataMessageComposer, SongInfoReceivedEvent, StringDataType } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useEffect, useState } from 'react'; +import { AvatarInfoFurni, CreateLinkEvent, GetGroupInformation, GetNitroInstance, GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../../api'; +import { Base, Button, Column, Flex, LayoutBadgeImageView, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, Text, UserProfileIconView } from '../../../../../common'; +import { useMessageEvent, useRoom, useSoundEvent } from '../../../../../hooks'; -interface InfoStandWidgetUserViewProps +interface InfoStandWidgetFurniViewProps { - avatarInfo: AvatarInfoUser; - setAvatarInfo: Dispatch>; + avatarInfo: AvatarInfoFurni; onClose: () => void; } -export const InfoStandWidgetUserView: FC = props => +const PICKUP_MODE_NONE: number = 0; +const PICKUP_MODE_EJECT: number = 1; +const PICKUP_MODE_FULL: number = 2; + +export const InfoStandWidgetFurniView: FC = props => { - const { avatarInfo = null, setAvatarInfo = null, onClose = null } = props; - const [ motto, setMotto ] = useState(null); - const [ isEditingMotto, setIsEditingMotto ] = useState(false); - const [ relationships, setRelationships ] = useState(null); + const { avatarInfo = null, onClose = null } = props; const { roomSession = null } = useRoom(); - const [ backgroundId, setBackgroundId ] = useState(null); - const [ standId, setStandId ] = useState(null); - const [ overlayId, setOverlayId ] = useState(null); - const [ isVisible, setIsVisible ] = useState(false); - const infostandBackgroundClass = `background-${ backgroundId }`; - const infostandStandClass = `stand-${ standId }`; - const infostandOverlayClass = `overlay-${ overlayId }`; + const [ pickupMode, setPickupMode ] = useState(0); + const [ canMove, setCanMove ] = useState(false); + const [ canRotate, setCanRotate ] = useState(false); + const [ canUse, setCanUse ] = useState(false); + const [ furniKeys, setFurniKeys ] = useState([]); + const [ furniValues, setFurniValues ] = useState([]); + const [ customKeys, setCustomKeys ] = useState([]); + const [ customValues, setCustomValues ] = useState([]); + const [ isCrackable, setIsCrackable ] = useState(false); + const [ crackableHits, setCrackableHits ] = useState(0); + const [ crackableTarget, setCrackableTarget ] = useState(0); + const [ godMode, setGodMode ] = useState(false); + const [ canSeeFurniId, setCanSeeFurniId ] = useState(false); + const [ groupName, setGroupName ] = useState(null); + const [ isJukeBox, setIsJukeBox ] = useState(false); + const [ isSongDisk, setIsSongDisk ] = useState(false); + const [ songId, setSongId ] = useState(-1); + const [ songName, setSongName ] = useState(''); + const [ songCreator, setSongCreator ] = useState(''); + const [itemLocation, setItemLocation] = useState<{ x: number; y: number; z: number; }>({ x: -1, y: -1, z: -1 }); - const saveMotto = (motto: string) => + useSoundEvent(NowPlayingEvent.NPE_SONG_CHANGED, event => { - if(!isEditingMotto || (motto.length > GetConfiguration('motto.max.length', 38))) return; + setSongId(event.id); + }, (isJukeBox || isSongDisk)); - roomSession.sendMottoMessage(motto); - - setIsEditingMotto(false); - } - - const onMottoBlur = (event: FocusEvent) => saveMotto(event.target.value); - - const onMottoKeyDown = (event: KeyboardEvent) => + useSoundEvent(SongInfoReceivedEvent.SIR_TRAX_SONG_INFO_RECEIVED, event => { - event.stopPropagation(); + if(event.id !== songId) return; - switch(event.key) + const songInfo = GetNitroInstance().soundManager.musicController.getSongInfo(event.id); + + if(!songInfo) return; + + setSongName(songInfo.name); + setSongCreator(songInfo.creator); + }, (isJukeBox || isSongDisk)); + + useEffect(() => + { + let pickupMode = PICKUP_MODE_NONE; + let canMove = false; + let canRotate = false; + let canUse = false; + let furniKeyss: string[] = []; + let furniValuess: string[] = []; + let customKeyss: string[] = []; + let customValuess: string[] = []; + let isCrackable = false; + let crackableHits = 0; + let crackableTarget = 0; + let godMode = false; + let canSeeFurniId = false; + let furniIsJukebox = false; + let furniIsSongDisk = false; + let furniSongId = -1; + + const roomObject = GetRoomEngine().getRoomObject( roomSession.roomId, avatarInfo.id, avatarInfo.isWallItem ? RoomObjectCategory.WALL : RoomObjectCategory.FLOOR ); + const location = roomObject.getLocation(); + if (location) { + setItemLocation({ x: location.x, y: location.y, z: location.z, }); + } + + const isValidController = (avatarInfo.roomControllerLevel >= RoomControllerLevel.GUEST); + + if(isValidController || avatarInfo.isOwner || avatarInfo.isRoomOwner || avatarInfo.isAnyRoomController) { - case 'Enter': - saveMotto((event.target as HTMLInputElement).value); - return; + canMove = true; + canRotate = !avatarInfo.isWallItem; + + if(avatarInfo.roomControllerLevel >= RoomControllerLevel.MODERATOR) godMode = true; } - } - useRoomSessionManagerEvent(RoomSessionUserBadgesEvent.RSUBE_BADGES, event => - { - if(!avatarInfo || (avatarInfo.webID !== event.userId)) return; - - const oldBadges = avatarInfo.badges.join(''); - - if(oldBadges === event.badges.join('')) return; - - setAvatarInfo(prevValue => + if(avatarInfo.isAnyRoomController) { - const newValue = CloneObject(prevValue); + canSeeFurniId = true; + } - newValue.badges = event.badges; + if((((avatarInfo.usagePolicy === RoomWidgetFurniInfoUsagePolicyEnum.EVERYBODY) || ((avatarInfo.usagePolicy === RoomWidgetFurniInfoUsagePolicyEnum.CONTROLLER) && isValidController)) || ((avatarInfo.extraParam === RoomWidgetEnumItemExtradataParameter.JUKEBOX) && isValidController)) || ((avatarInfo.extraParam === RoomWidgetEnumItemExtradataParameter.USABLE_PRODUCT) && isValidController)) canUse = true; - return newValue; - }); - }); - - useRoomSessionManagerEvent(RoomSessionUserFigureUpdateEvent.USER_FIGURE, event => - { - if(!avatarInfo || (avatarInfo.roomIndex !== event.roomIndex)) return; - - setAvatarInfo(prevValue => + if(avatarInfo.extraParam) { - const newValue = CloneObject(prevValue); + if(avatarInfo.extraParam === RoomWidgetEnumItemExtradataParameter.CRACKABLE_FURNI) + { + const stuffData = (avatarInfo.stuffData as CrackableDataType); - newValue.figure = event.figure; - newValue.motto = event.customInfo; - newValue.backgroundId = event.backgroundId; - newValue.standId = event.standId; - newValue.overlayId = event.overlayId; - newValue.achievementScore = event.activityPoints; + canUse = true; + isCrackable = true; + crackableHits = stuffData.hits; + crackableTarget = stuffData.target; + } - return newValue; - }); - }); + else if(avatarInfo.extraParam === RoomWidgetEnumItemExtradataParameter.JUKEBOX) + { + const playlist = GetNitroInstance().soundManager.musicController.getRoomItemPlaylist(); - useRoomSessionManagerEvent(RoomSessionFavoriteGroupUpdateEvent.FAVOURITE_GROUP_UPDATE, event => - { - if(!avatarInfo || (avatarInfo.roomIndex !== event.roomIndex)) return; + if(playlist) + { + furniSongId = playlist.nowPlayingSongId; + } - setAvatarInfo(prevValue => + furniIsJukebox = true; + } + + else if(avatarInfo.extraParam.indexOf(RoomWidgetEnumItemExtradataParameter.SONGDISK) === 0) + { + furniSongId = parseInt(avatarInfo.extraParam.substr(RoomWidgetEnumItemExtradataParameter.SONGDISK.length)); + + furniIsSongDisk = true; + } + + if(godMode) + { + const extraParam = avatarInfo.extraParam.substr(RoomWidgetEnumItemExtradataParameter.BRANDING_OPTIONS.length); + + if(extraParam) + { + const parts = extraParam.split('\t'); + + for(const part of parts) + { + const value = part.split('='); + + if(value && (value.length === 2)) + { + furniKeyss.push(value[0]); + furniValuess.push(value[1]); + } + } + } + } + } + + if(godMode) { - const newValue = CloneObject(prevValue); - const clearGroup = ((event.status === -1) || (event.habboGroupId <= 0)); + const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, avatarInfo.id, (avatarInfo.isWallItem) ? RoomObjectCategory.WALL : RoomObjectCategory.FLOOR); - newValue.groupId = clearGroup ? -1 : event.habboGroupId; - newValue.groupName = clearGroup ? null : event.habboGroupName - newValue.groupBadgeId = clearGroup ? null : GetSessionDataManager().getGroupBadge(event.habboGroupId); + if(roomObject) + { + const customVariables = roomObject.model.getValue(RoomObjectVariable.FURNITURE_CUSTOM_VARIABLES); + const furnitureData = roomObject.model.getValue<{ [index: string]: string }>(RoomObjectVariable.FURNITURE_DATA); - return newValue; - }); - }); + if(customVariables && customVariables.length) + { + for(const customVariable of customVariables) + { + customKeyss.push(customVariable); + customValuess.push((furnitureData[customVariable]) || ''); + } + } + } + } - useMessageEvent(RelationshipStatusInfoEvent, event => + if(avatarInfo.isOwner || avatarInfo.isAnyRoomController) pickupMode = PICKUP_MODE_FULL; + + else if(avatarInfo.isRoomOwner || (avatarInfo.roomControllerLevel >= RoomControllerLevel.GUILD_ADMIN)) pickupMode = PICKUP_MODE_EJECT; + + if(avatarInfo.isStickie) pickupMode = PICKUP_MODE_NONE; + + setPickupMode(pickupMode); + setCanMove(canMove); + setCanRotate(canRotate); + setCanUse(canUse); + setFurniKeys(furniKeyss); + setFurniValues(furniValuess); + setCustomKeys(customKeyss); + setCustomValues(customValuess); + setIsCrackable(isCrackable); + setCrackableHits(crackableHits); + setCrackableTarget(crackableTarget); + setGodMode(godMode); + setCanSeeFurniId(canSeeFurniId); + setGroupName(null); + setIsJukeBox(furniIsJukebox); + setIsSongDisk(furniIsSongDisk); + setSongId(furniSongId); + + if(avatarInfo.groupId) SendMessageComposer(new GroupInformationComposer(avatarInfo.groupId, false)); + }, [ roomSession, avatarInfo ]); + + useMessageEvent(GroupInformationEvent, event => { const parser = event.getParser(); - if(!avatarInfo || (avatarInfo.webID !== parser.userId)) return; + if(!avatarInfo || avatarInfo.groupId !== parser.id || parser.flag) return; - setRelationships(parser); + if(groupName) setGroupName(null); + + setGroupName(parser.title); }); useEffect(() => { - setIsEditingMotto(false); - setMotto(avatarInfo.motto); - setBackgroundId(avatarInfo.backgroundId); - setStandId(avatarInfo.standId); - setOverlayId(avatarInfo.overlayId); + const songInfo = GetNitroInstance().soundManager.musicController.getSongInfo(songId); - SendMessageComposer(new UserRelationshipsComposer(avatarInfo.webID)); + setSongName(songInfo?.name ?? ''); + setSongCreator(songInfo?.creator ?? ''); + }, [ songId ]); - return () => + const onFurniSettingChange = useCallback((index: number, value: string) => + { + const clone = Array.from(furniValues); + + clone[index] = value; + + setFurniValues(clone); + }, [ furniValues ]); + + const onCustomVariableChange = useCallback((index: number, value: string) => + { + const clone = Array.from(customValues); + + clone[index] = value; + + setCustomValues(clone); + }, [ customValues ]); + + const getFurniSettingsAsString = useCallback(() => + { + if(furniKeys.length === 0 || furniValues.length === 0) return ''; + + let data = ''; + + let i = 0; + + while(i < furniKeys.length) { - setIsEditingMotto(false); - setMotto(null); - setRelationships(null); - setBackgroundId(null); - setStandId(null); - setOverlayId(null); + const key = furniKeys[i]; + const value = furniValues[i]; + + data = (data + (key + '=' + value + '\t')); + + i++; } + + return data; + }, [ furniKeys, furniValues ]); + + const processButtonAction = useCallback((action: string) => + { + if(!action || (action === '')) return; + + let objectData: string = null; + + switch(action) + { + case 'buy_one': + CreateLinkEvent(`catalog/open/offerId/${ avatarInfo.purchaseOfferId }`); + return; + case 'move': + GetRoomEngine().processRoomObjectOperation(avatarInfo.id, avatarInfo.category, RoomObjectOperationType.OBJECT_MOVE); + break; + case 'rotate': + GetRoomEngine().processRoomObjectOperation(avatarInfo.id, avatarInfo.category, RoomObjectOperationType.OBJECT_ROTATE_POSITIVE); + break; + case 'pickup': + if(pickupMode === PICKUP_MODE_FULL) + { + GetRoomEngine().processRoomObjectOperation(avatarInfo.id, avatarInfo.category, RoomObjectOperationType.OBJECT_PICKUP); + } + else + { + GetRoomEngine().processRoomObjectOperation(avatarInfo.id, avatarInfo.category, RoomObjectOperationType.OBJECT_EJECT); + } + break; + case 'use': + GetRoomEngine().useRoomObject(avatarInfo.id, avatarInfo.category); + break; + case 'save_branding_configuration': { + const mapData = new Map(); + const dataParts = getFurniSettingsAsString().split('\t'); + + if(dataParts) + { + for(const part of dataParts) + { + const [ key, value ] = part.split('=', 2); + + mapData.set(key, value); + } + } + + GetRoomEngine().modifyRoomObjectDataWithMap(avatarInfo.id, avatarInfo.category, RoomObjectOperationType.OBJECT_SAVE_STUFF_DATA, mapData); + break; + } + case 'save_custom_variables': { + const map = new Map(); + + for(let i = 0; i < customKeys.length; i++) + { + const key = customKeys[i]; + const value = customValues[i]; + + if((key && key.length) && (value && value.length)) map.set(key, value); + } + + SendMessageComposer(new SetObjectDataMessageComposer(avatarInfo.id, map)); + break; + } + } + }, [ avatarInfo, pickupMode, customKeys, customValues, getFurniSettingsAsString ]); + + const getGroupBadgeCode = useCallback(() => + { + const stringDataType = (avatarInfo.stuffData as StringDataType); + + if(!stringDataType || !(stringDataType instanceof StringDataType)) return null; + + return stringDataType.getValue(2); }, [ avatarInfo ]); if(!avatarInfo) return null; return ( - - - - - - - { avatarInfo.name } + + + + + + { !(isSongDisk) && { avatarInfo.name } } + { (songName.length > 0) && { songName } } + - - -
-
- - - GetUserProfile(avatarInfo.webID) }> - - - - { avatarInfo.type === AvatarInfoUser.OWN_USER && - - { - event.stopPropagation(); setIsVisible(prevValue => !prevValue); - } } /> - } - - - - - { avatarInfo.badges[0] && } - - 0) } className="badge-image" onClick={ event => GetGroupInformation(avatarInfo.groupId) }> - { avatarInfo.groupId > 0 && - } - - - - - { avatarInfo.badges[1] && } - - - { avatarInfo.badges[2] && } - - - - - { avatarInfo.badges[3] && } - - - { avatarInfo.badges[4] && } - - - - -
-
- - - { (avatarInfo.type !== AvatarInfoUser.OWN_USER) && - - { motto } - } - { avatarInfo.type === AvatarInfoUser.OWN_USER && - - - - { !isEditingMotto && - setIsEditingMotto(true) }>{ motto }  } - { isEditingMotto && - ('motto.max.length', 38) } value={ motto } onChange={ event => setMotto(event.target.value) } onBlur={ onMottoBlur } onKeyDown={ onMottoKeyDown } autoFocus={ true } /> } - - } - -
-
- - - { LocalizeText('infostand.text.achievement_score') + ' ' + avatarInfo.achievementScore } - - { (avatarInfo.carryItem > 0) && - <> -
- - { LocalizeText('infostand.text.handitem', [ 'item' ], [ LocalizeText('handitem' + avatarInfo.carryItem) ]) } - - } -
- - - - { GetConfiguration('user.tags.enabled') && - - +
- } + + + { avatarInfo.stuffData.isUnique && +
+ +
} + { (avatarInfo.stuffData.rarityLevel > -1) && +
+ +
} + { avatarInfo.image && avatarInfo.image.src.length && + } +
+
+
+ + { avatarInfo.description } +
+
+ + + + + { LocalizeText('furni.owner', [ 'name' ], [ avatarInfo.ownerName ]) } + + + { (avatarInfo.purchaseOfferId > 0) && + + + } + + { (isJukeBox || isSongDisk) && + +
+ { (songId === -1) && + + { LocalizeText('infostand.jukebox.text.not.playing') } + } + { !!songName.length && + + + + { songName } + + } + { !!songCreator.length && + + + + { songCreator } + + } +
} + + { isCrackable && + <> +
+ { LocalizeText('infostand.crackable_furni.hits_remaining', [ 'hits', 'target' ], [ crackableHits.toString(), crackableTarget.toString() ]) } + } + { avatarInfo.groupId > 0 && + <> +
+ GetGroupInformation(avatarInfo.groupId) }> + + { groupName } + + } + <> +
+ + X = {itemLocation.x} and Y = {itemLocation.y}
+ BuildHeight = {itemLocation.z < 0.01 ? 0 : itemLocation.z}
+ { canSeeFurniId && Room Furnishing ID: { avatarInfo.id } } +
+ + {itemLocation.x > -1} + { godMode && + <> +
+ { (furniKeys.length > 0) && + <> +
+ + { furniKeys.map((key, index) => + { + return ( + + { key } + onFurniSettingChange(index, event.target.value) }/> + ); + }) } + + } + } + { (customKeys.length > 0) && + <> +
+ + { customKeys.map((key, index) => + { + return ( + + { key } + onCustomVariableChange(index, event.target.value) }/> + ); + }) } + + } +
+
- { (isVisible && avatarInfo.type === AvatarInfoUser.OWN_USER) && - - } + + { canMove && + } + { canRotate && + } + { (pickupMode !== PICKUP_MODE_NONE) && + } + { canUse && + } + { ((furniKeys.length > 0 && furniValues.length > 0) && (furniKeys.length === furniValues.length)) && + } + { ((customKeys.length > 0 && customValues.length > 0) && (customKeys.length === customValues.length)) && + } + ); -} +} \ No newline at end of file diff --git a/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetUserView.tsx b/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetUserView.tsx index e45b079..087ab94 100644 --- a/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetUserView.tsx +++ b/src/components/room/widgets/avatar-info/infostand/InfoStandWidgetUserView.tsx @@ -1,5 +1,5 @@ -import { RelationshipStatusInfoEvent, RoomSessionFavoriteGroupUpdateEvent, RoomSessionUserBadgesEvent, RoomSessionUserFigureUpdateEvent, UserRelationshipsComposer } from '@nitrots/nitro-renderer'; -import { Dispatch, FC, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react'; +import { RelationshipStatusInfoEvent, RelationshipStatusInfoMessageParser, RoomSessionFavoriteGroupUpdateEvent, RoomSessionUserBadgesEvent, RoomSessionUserFigureUpdateEvent, UserRelationshipsComposer } from '@nitrots/nitro-renderer'; +import { Dispatch, FC, FocusEvent, KeyboardEvent, SetStateAction, useEffect, useState } from 'react'; import { FaPencilAlt, FaTimes } from 'react-icons/fa'; import { AvatarInfoUser, CloneObject, GetConfiguration, GetGroupInformation, GetSessionDataManager, GetUserProfile, LocalizeText, SendMessageComposer } from '../../../../../api'; import { Base, Column, Flex, LayoutAvatarImageView, LayoutBadgeImageView, Text, UserProfileIconView } from '../../../../../common'; @@ -8,212 +8,245 @@ import { InfoStandWidgetUserRelationshipsView } from './InfoStandWidgetUserRelat import { InfoStandWidgetUserTagsView } from './InfoStandWidgetUserTagsView'; import { BackgroundsView } from '../../../../backgrounds/BackgroundsView'; -interface InfoStandWidgetUserViewProps { - avatarInfo: AvatarInfoUser | null; - setAvatarInfo: Dispatch>; +interface InfoStandWidgetUserViewProps +{ + avatarInfo: AvatarInfoUser; + setAvatarInfo: Dispatch>; onClose: () => void; } -export const InfoStandWidgetUserView: FC = ({ - avatarInfo, - setAvatarInfo, - onClose -}) => { - const [motto, setMotto] = useState(''); - const [isEditingMotto, setIsEditingMotto] = useState(false); - const [relationships, setRelationships] = useState(null); - const [isVisible, setIsVisible] = useState(false); - const { roomSession } = useRoom(); +export const InfoStandWidgetUserView: FC = props => +{ + const { avatarInfo = null, setAvatarInfo = null, onClose = null } = props; + const [ motto, setMotto ] = useState(null); + const [ isEditingMotto, setIsEditingMotto ] = useState(false); + const [ relationships, setRelationships ] = useState(null); + const { roomSession = null } = useRoom(); + const [ backgroundId, setBackgroundId ] = useState(null); + const [ standId, setStandId ] = useState(null); + const [ overlayId, setOverlayId ] = useState(null); + const [ isVisible, setIsVisible ] = useState(false); - const config = useMemo(() => ({ - maxMottoLength: GetConfiguration('motto.max.length', 38), - tagsEnabled: GetConfiguration('user.tags.enabled') - }), []); + const infostandBackgroundClass = `background-${ backgroundId }`; + const infostandStandClass = `stand-${ standId }`; + const infostandOverlayClass = `overlay-${ overlayId }`; - const backgroundClasses = useMemo(() => ({ - background: `background-${avatarInfo?.backgroundId ?? 0}`, - stand: `stand-${avatarInfo?.standId ?? 0}`, - overlay: `overlay-${avatarInfo?.overlayId ?? 0}` - }), [avatarInfo?.backgroundId, avatarInfo?.standId, avatarInfo?.overlayId]); + const saveMotto = (motto: string) => + { + if(!isEditingMotto || (motto.length > GetConfiguration('motto.max.length', 38))) return; + + roomSession.sendMottoMessage(motto); - const saveMotto = useCallback((newMotto: string) => { - if (!isEditingMotto || !roomSession || newMotto.length > config.maxMottoLength) return; - - roomSession.sendMottoMessage(newMotto); setIsEditingMotto(false); - }, [isEditingMotto, roomSession, config.maxMottoLength]); + } - const handleMottoBlur = useCallback((event: React.FocusEvent) => - saveMotto(event.target.value), [saveMotto]); + const onMottoBlur = (event: FocusEvent) => saveMotto(event.target.value); - const handleMottoKeyDown = useCallback((event: React.KeyboardEvent) => { + const onMottoKeyDown = (event: KeyboardEvent) => + { event.stopPropagation(); - if (event.key === 'Enter') saveMotto(event.currentTarget.value); - }, [saveMotto]); - const updateAvatarInfo = useCallback((updater: (prev: AvatarInfoUser) => AvatarInfoUser) => { - setAvatarInfo(prev => prev ? updater(CloneObject(prev)) : prev); - }, [setAvatarInfo]); + switch(event.key) + { + case 'Enter': + saveMotto((event.target as HTMLInputElement).value); + return; + } + } - useRoomSessionManagerEvent(RoomSessionUserBadgesEvent.RSUBE_BADGES, useCallback(event => { - if (!avatarInfo || avatarInfo.webID !== event.userId || avatarInfo.badges.join('') === event.badges.join('')) return; - updateAvatarInfo(prev => ({ ...prev, badges: event.badges })); - }, [avatarInfo, updateAvatarInfo])); + useRoomSessionManagerEvent(RoomSessionUserBadgesEvent.RSUBE_BADGES, event => + { + if(!avatarInfo || (avatarInfo.webID !== event.userId)) return; - useRoomSessionManagerEvent(RoomSessionUserFigureUpdateEvent.USER_FIGURE, useCallback(event => { - if (!avatarInfo || avatarInfo.roomIndex !== event.roomIndex) return; - updateAvatarInfo(prev => ({ - ...prev, - figure: event.figure, - motto: event.customInfo, - backgroundId: event.backgroundId, - standId: event.standId, - overlayId: event.overlayId, - achievementScore: event.activityPoints - })); - }, [avatarInfo, updateAvatarInfo])); + const oldBadges = avatarInfo.badges.join(''); - useRoomSessionManagerEvent(RoomSessionFavoriteGroupUpdateEvent.FAVOURITE_GROUP_UPDATE, useCallback(event => { - if (!avatarInfo || avatarInfo.roomIndex !== event.roomIndex) return; - const clearGroup = (event.status === -1 || event.habboGroupId <= 0); - updateAvatarInfo(prev => ({ - ...prev, - groupId: clearGroup ? -1 : event.habboGroupId, - groupName: clearGroup ? null : event.habboGroupName, - groupBadgeId: clearGroup ? null : GetSessionDataManager().getGroupBadge(event.habboGroupId) - })); - }, [avatarInfo, updateAvatarInfo])); + if(oldBadges === event.badges.join('')) return; - useMessageEvent(RelationshipStatusInfoEvent, useCallback(event => { + setAvatarInfo(prevValue => + { + const newValue = CloneObject(prevValue); + + newValue.badges = event.badges; + + return newValue; + }); + }); + + useRoomSessionManagerEvent(RoomSessionUserFigureUpdateEvent.USER_FIGURE, event => + { + if(!avatarInfo || (avatarInfo.roomIndex !== event.roomIndex)) return; + + setAvatarInfo(prevValue => + { + const newValue = CloneObject(prevValue); + + newValue.figure = event.figure; + newValue.motto = event.customInfo; + newValue.backgroundId = event.backgroundId; + newValue.standId = event.standId; + newValue.overlayId = event.overlayId; + newValue.achievementScore = event.activityPoints; + + return newValue; + }); + }); + + useRoomSessionManagerEvent(RoomSessionFavoriteGroupUpdateEvent.FAVOURITE_GROUP_UPDATE, event => + { + if(!avatarInfo || (avatarInfo.roomIndex !== event.roomIndex)) return; + + setAvatarInfo(prevValue => + { + const newValue = CloneObject(prevValue); + const clearGroup = ((event.status === -1) || (event.habboGroupId <= 0)); + + newValue.groupId = clearGroup ? -1 : event.habboGroupId; + newValue.groupName = clearGroup ? null : event.habboGroupName + newValue.groupBadgeId = clearGroup ? null : GetSessionDataManager().getGroupBadge(event.habboGroupId); + + return newValue; + }); + }); + + useMessageEvent(RelationshipStatusInfoEvent, event => + { const parser = event.getParser(); - if (!avatarInfo || avatarInfo.webID !== parser.userId) return; + + if(!avatarInfo || (avatarInfo.webID !== parser.userId)) return; + setRelationships(parser); - }, [avatarInfo])); + }); - useEffect(() => { - if (!avatarInfo) return; + useEffect(() => + { + setIsEditingMotto(false); + setMotto(avatarInfo.motto); + setBackgroundId(avatarInfo.backgroundId); + setStandId(avatarInfo.standId); + setOverlayId(avatarInfo.overlayId); - setMotto(avatarInfo.motto || ''); SendMessageComposer(new UserRelationshipsComposer(avatarInfo.webID)); - return () => { + return () => + { setIsEditingMotto(false); - setMotto(''); + setMotto(null); setRelationships(null); - }; - }, [avatarInfo]); + setBackgroundId(null); + setStandId(null); + setOverlayId(null); + } + }, [ avatarInfo ]); - if (!avatarInfo) return null; - - const isOwnUser = avatarInfo.type === AvatarInfoUser.OWN_USER; - const renderBadge = (index: number) => avatarInfo.badges[index] && ( - - - - ); + if(!avatarInfo) return null; return ( - - + + - - - {avatarInfo.name} + + + { avatarInfo.name } - +
- - - GetUserProfile(avatarInfo.webID)}> - - - - {isOwnUser && ( { e.stopPropagation(); setIsVisible(prev => !prev); }} /> )} + + + GetUserProfile(avatarInfo.webID) }> + + + + { avatarInfo.type === AvatarInfoUser.OWN_USER && + + { + event.stopPropagation(); setIsVisible(prevValue => !prevValue); + } } /> + } - - - {renderBadge(0)} - 0} className="badge-image" - onClick={() => avatarInfo.groupId > 0 && GetGroupInformation(avatarInfo.groupId)}> - {avatarInfo.groupId > 0 && ( - - )} + + + + { avatarInfo.badges[0] && } + + 0) } className="badge-image" onClick={ event => GetGroupInformation(avatarInfo.groupId) }> + { avatarInfo.groupId > 0 && + } + + + + + { avatarInfo.badges[1] && } + + + { avatarInfo.badges[2] && } + + + + + { avatarInfo.badges[3] && } + + + { avatarInfo.badges[4] && } - {renderBadge(1)}{renderBadge(2)} - {renderBadge(3)}{renderBadge(4)}
- + - {!isOwnUser ? ( - {motto} - ) : ( - + { (avatarInfo.type !== AvatarInfoUser.OWN_USER) && + + { motto } + } + { avatarInfo.type === AvatarInfoUser.OWN_USER && + - {!isEditingMotto ? ( - setIsEditingMotto(true)}>{motto}  - ) : ( - setMotto(e.target.value)} - onBlur={handleMottoBlur} - onKeyDown={handleMottoKeyDown} - autoFocus - /> - )} - - )} + + { !isEditingMotto && + setIsEditingMotto(true) }>{ motto }  } + { isEditingMotto && + ('motto.max.length', 38) } value={ motto } onChange={ event => setMotto(event.target.value) } onBlur={ onMottoBlur } onKeyDown={ onMottoKeyDown } autoFocus={ true } /> } + + }
- + - {LocalizeText('infostand.text.achievement_score')} {avatarInfo.achievementScore} + { LocalizeText('infostand.text.achievement_score') + ' ' + avatarInfo.achievementScore } - {avatarInfo.carryItem > 0 && ( + { (avatarInfo.carryItem > 0) && <>
- {LocalizeText('infostand.text.handitem', ['item'], [LocalizeText('handitem' + avatarInfo.carryItem)])} + { LocalizeText('infostand.text.handitem', [ 'item' ], [ LocalizeText('handitem' + avatarInfo.carryItem) ]) } - - )} + }
- - {config.tagsEnabled && ( - - + + + + { GetConfiguration('user.tags.enabled') && + + - )} + } - {isVisible && isOwnUser && ( + { (isVisible && avatarInfo.type === AvatarInfoUser.OWN_USER) && updateAvatarInfo(prev => ({ ...prev, backgroundId: id }))} - selectedStand={avatarInfo.standId ?? 0} - setSelectedStand={id => updateAvatarInfo(prev => ({ ...prev, standId: id }))} - selectedOverlay={avatarInfo.overlayId ?? 0} - setSelectedOverlay={id => updateAvatarInfo(prev => ({ ...prev, overlayId: id }))} + setIsVisible={ setIsVisible } + selectedBackground={ backgroundId } + setSelectedBackground={ setBackgroundId } + selectedStand={ standId } + setSelectedStand={ setStandId } + selectedOverlay={ overlayId } + setSelectedOverlay={ setOverlayId } /> - )} + }
); -}; \ No newline at end of file +}