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
+}