Lots of widget updates

This commit is contained in:
Bill 2021-07-12 03:59:40 -04:00
parent 6302587ef8
commit fe998d1639
55 changed files with 499 additions and 213 deletions

View File

@ -62,3 +62,7 @@ ul {
.filter-none { .filter-none {
filter: unset !important; filter: unset !important;
} }
.w-unset {
width: unset;
}

View File

@ -9,7 +9,7 @@ import { GetRoomEngine } from '../../api/nitro/room/GetRoomEngine';
import { useRoomEngineEvent } from '../../hooks/events'; import { useRoomEngineEvent } from '../../hooks/events';
import { RoomContextProvider } from './context/RoomContext'; import { RoomContextProvider } from './context/RoomContext';
import { RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent } from './events'; import { RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent } from './events';
import { IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers'; import { FurnitureContextMenuWidgetHandler, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler } from './handlers';
import { RoomViewProps } from './RoomView.types'; import { RoomViewProps } from './RoomView.types';
import { RoomWidgetsView } from './widgets/RoomWidgetsView'; import { RoomWidgetsView } from './widgets/RoomWidgetsView';
@ -37,6 +37,7 @@ export const RoomView: FC<RoomViewProps> = props =>
widgetHandlerManager.registerHandler(new RoomWidgetInfostandHandler()); widgetHandlerManager.registerHandler(new RoomWidgetInfostandHandler());
widgetHandlerManager.registerHandler(new RoomWidgetChatInputHandler()); widgetHandlerManager.registerHandler(new RoomWidgetChatInputHandler());
widgetHandlerManager.registerHandler(new RoomWidgetChatHandler()); widgetHandlerManager.registerHandler(new RoomWidgetChatHandler());
widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
setWidgetHandler(widgetHandlerManager); setWidgetHandler(widgetHandlerManager);

View File

@ -0,0 +1,40 @@
import { NitroEvent, RoomEngineTriggerWidgetEvent } from 'nitro-renderer';
import { RoomWidgetUpdateEvent } from '../events';
import { RoomWidgetMessage, RoomWidgetUseProductMessage } from '../messages';
import { RoomWidgetHandler } from './RoomWidgetHandler';
export class FurnitureContextMenuWidgetHandler extends RoomWidgetHandler
{
public processEvent(event: NitroEvent): void
{
}
public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
{
switch(message.type)
{
case RoomWidgetUseProductMessage.MONSTERPLANT_SEED:
const productMessage = (message as RoomWidgetUseProductMessage);
this.container.roomSession.useMultistateItem(productMessage.objectId);
break;
}
return null;
}
public get eventTypes(): string[]
{
return [
RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU,
RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU
];
}
public get messageTypes(): string[]
{
return [
RoomWidgetUseProductMessage.MONSTERPLANT_SEED
];
}
}

View File

@ -168,8 +168,7 @@ export class RoomWidgetAvatarInfoHandler extends RoomWidgetHandler
RoomWidgetDanceMessage.DANCE, RoomWidgetDanceMessage.DANCE,
RoomWidgetAvatarExpressionMessage.AVATAR_EXPRESSION, RoomWidgetAvatarExpressionMessage.AVATAR_EXPRESSION,
RoomWidgetChangePostureMessage.CHANGE_POSTURE, RoomWidgetChangePostureMessage.CHANGE_POSTURE,
RoomWidgetUseProductMessage.PET_PRODUCT, RoomWidgetUseProductMessage.PET_PRODUCT
RoomWidgetUseProductMessage.MONSTERPLANT_SEED
]; ];
} }
} }

View File

@ -1,3 +1,4 @@
export * from './FurnitureContextMenuWidgetHandler';
export * from './IRoomWidgetHandler'; export * from './IRoomWidgetHandler';
export * from './IRoomWidgetHandlerManager'; export * from './IRoomWidgetHandlerManager';
export * from './RoomWidgetAvatarInfoHandler'; export * from './RoomWidgetAvatarInfoHandler';

View File

@ -1,5 +1,2 @@
export interface RoomWidgetViewProps export interface RoomWidgetViewProps
{} {}
export interface RoomWidgetProps
{}

View File

@ -1,6 +1,10 @@
.nitro-use-product-confirmation { .nitro-use-product-confirmation {
width: 350px;
.product-preview { .product-preview {
display: flex;
justify-content: center;
align-items: center;
width: 122px; width: 122px;
height: 130px; height: 130px;
background: url('../../../../assets/images/room-widgets/avatar-info/preview-background.png') no-repeat center; background: url('../../../../assets/images/room-widgets/avatar-info/preview-background.png') no-repeat center;
@ -9,5 +13,21 @@
width: 122px; width: 122px;
height: 130px; height: 130px;
} }
.monsterplant-image {
width: 122px;
height: 130px;
background: url('../../../../assets/images/room-widgets/furni-context-menu/monsterplant-preview.png') no-repeat center;
}
}
.mannequin-preview {
display: flex;
justify-content: center;
align-items: center;
width: 83px;
height: 130px;
background-image: url('../../../../assets/images/room-widgets/mannequin-widget/mannequin-spritesheet.png');
overflow: hidden;
} }
} }

View File

@ -7,7 +7,6 @@ import { CreateEventDispatcherHook } from '../../../../hooks/events/event-dispat
import { useRoomContext } from '../../context/RoomContext'; import { useRoomContext } from '../../context/RoomContext';
import { RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../events'; import { RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../events';
import { RoomWidgetRoomObjectMessage } from '../../messages'; import { RoomWidgetRoomObjectMessage } from '../../messages';
import { AvatarInfoWidgetViewProps } from './AvatarInfoWidgetView.types';
import { AvatarInfoWidgetAvatarView } from './views/avatar/AvatarInfoWidgetAvatarView'; import { AvatarInfoWidgetAvatarView } from './views/avatar/AvatarInfoWidgetAvatarView';
import { AvatarInfoWidgetDecorateView } from './views/decorate/AvatarInfoWidgetDecorateView'; import { AvatarInfoWidgetDecorateView } from './views/decorate/AvatarInfoWidgetDecorateView';
import { AvatarInfoWidgetNameView } from './views/name/AvatarInfoWidgetNameView'; import { AvatarInfoWidgetNameView } from './views/name/AvatarInfoWidgetNameView';
@ -19,7 +18,7 @@ import { AvatarInfoWidgetRentableBotView } from './views/rentable-bot/AvatarInfo
import { AvatarInfoUseProductConfirmView } from './views/use-product-confirm/AvatarInfoUseProductConfirmView'; import { AvatarInfoUseProductConfirmView } from './views/use-product-confirm/AvatarInfoUseProductConfirmView';
import { AvatarInfoUseProductView } from './views/use-product/AvatarInfoUseProductView'; import { AvatarInfoUseProductView } from './views/use-product/AvatarInfoUseProductView';
export const AvatarInfoWidgetView: FC<AvatarInfoWidgetViewProps> = props => export const AvatarInfoWidgetView: FC<{}> = props =>
{ {
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ name, setName ] = useState<RoomWidgetObjectNameEvent>(null); const [ name, setName ] = useState<RoomWidgetObjectNameEvent>(null);

View File

@ -1,4 +0,0 @@
import { RoomWidgetProps } from '../RoomWidgets.types';
export interface AvatarInfoWidgetViewProps extends RoomWidgetProps
{}

View File

@ -194,7 +194,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
}, []); }, []);
return ( return (
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } close={ close }> <ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
<ContextMenuHeaderView> <ContextMenuHeaderView>
{ userData.name } { userData.name }
</ContextMenuHeaderView> </ContextMenuHeaderView>

View File

@ -13,7 +13,7 @@ export const AvatarInfoWidgetNameView: FC<AvatarInfoWidgetNameViewProps> = props
}, [ nameData ]); }, [ nameData ]);
return ( return (
<ContextMenuView objectId={ nameData.roomIndex } category={ nameData.category } fades={ fades } className="name-only" close= { close }> <ContextMenuView objectId={ nameData.roomIndex } category={ nameData.category } userType={ nameData.userType } fades={ fades } className="name-only" close= { close }>
<div className="text-shadow"> <div className="text-shadow">
{ nameData.name } { nameData.name }
</div> </div>

View File

@ -105,7 +105,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
const isRidingHorse = IsRidingHorse(); const isRidingHorse = IsRidingHorse();
return ( return (
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } close={ close }> <ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
<ContextMenuHeaderView> <ContextMenuHeaderView>
{ userData.name } { userData.name }
</ContextMenuHeaderView> </ContextMenuHeaderView>

View File

@ -1,4 +1,4 @@
import { PetType, RoomObjectCategory, RoomObjectVariable } from 'nitro-renderer'; import { PetType, RoomObjectCategory, RoomObjectType, RoomObjectVariable } from 'nitro-renderer';
import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { GetOwnRoomObject } from '../../../../../../api'; import { GetOwnRoomObject } from '../../../../../../api';
import { LocalizeText } from '../../../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../../../utils/LocalizeText';
@ -139,7 +139,7 @@ export const AvatarInfoWidgetOwnPetView: FC<AvatarInfoWidgetOwnPetViewProps> = p
}, []); }, []);
return ( return (
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } close={ close }> <ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
<ContextMenuHeaderView> <ContextMenuHeaderView>
{ petData.name } { petData.name }
</ContextMenuHeaderView> </ContextMenuHeaderView>

View File

@ -1,4 +1,4 @@
import { BotCommandConfigurationEvent, BotRemoveComposer, BotSkillSaveComposer, Nitro, RequestBotCommandConfigurationComposer, RoomObjectCategory } from 'nitro-renderer'; import { BotCommandConfigurationEvent, BotRemoveComposer, BotSkillSaveComposer, Nitro, RequestBotCommandConfigurationComposer, RoomObjectCategory, RoomObjectType } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks/messages'; import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks/messages';
import { LocalizeText } from '../../../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../../../utils/LocalizeText';
@ -136,7 +136,7 @@ export const AvatarInfoWidgetRentableBotView: FC<AvatarInfoWidgetRentableBotView
const canControl = (rentableBotData.amIOwner || rentableBotData.amIAnyRoomController); const canControl = (rentableBotData.amIOwner || rentableBotData.amIAnyRoomController);
return ( return (
<ContextMenuView objectId={ rentableBotData.roomIndex } category={ RoomObjectCategory.UNIT } close={ close }> <ContextMenuView objectId={ rentableBotData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.RENTABLE_BOT } close={ close }>
<ContextMenuHeaderView> <ContextMenuHeaderView>
{ rentableBotData.name } { rentableBotData.name }
</ContextMenuHeaderView> </ContextMenuHeaderView>

View File

@ -26,6 +26,13 @@ export const AvatarInfoUseProductConfirmView: FC<AvatarInfoUseProductConfirmView
const [ furniData, setFurniData ] = useState<IFurnitureData>(null); const [ furniData, setFurniData ] = useState<IFurnitureData>(null);
const { roomSession = null, widgetHandler = null } = useRoomContext(); const { roomSession = null, widgetHandler = null } = useRoomContext();
const selectRoomObject = useCallback(() =>
{
if(!petData) return;
GetRoomEngine().selectRoomObject(roomSession.roomId, petData.roomIndex, RoomObjectCategory.UNIT);
}, [ roomSession, petData ]);
const useProduct = useCallback(() => const useProduct = useCallback(() =>
{ {
widgetHandler.processWidgetMessage(new RoomWidgetUseProductMessage(RoomWidgetUseProductMessage.PET_PRODUCT, item.requestRoomObjectId, petData.webID)); widgetHandler.processWidgetMessage(new RoomWidgetUseProductMessage(RoomWidgetUseProductMessage.PET_PRODUCT, item.requestRoomObjectId, petData.webID));
@ -217,49 +224,51 @@ export const AvatarInfoUseProductConfirmView: FC<AvatarInfoUseProductConfirmView
<NitroCardView className="nitro-use-product-confirmation"> <NitroCardView className="nitro-use-product-confirmation">
<NitroCardHeaderView headerText={ LocalizeText('useproduct.widget.title', [ 'name' ], [ petData.name ]) } onCloseClick={ close } /> <NitroCardHeaderView headerText={ LocalizeText('useproduct.widget.title', [ 'name' ], [ petData.name ]) } onCloseClick={ close } />
<NitroCardContentView> <NitroCardContentView>
<div className="d-flex"> <div className="row">
<div className="product-preview"> <div className="w-unset">
{ getPetImage } <div className="product-preview cursor-pointer" onClick={ selectRoomObject }>
{ getPetImage }
</div>
</div> </div>
<div className="d-flex flex-column ms-2 mt-2"> <div className="col d-flex flex-column justify-content-between">
<div className="d-flex flex-column justify-content-center align-items-center w-100 h-100"> <div className="d-flex flex-column">
{ (mode === _Str_11906) && { (mode === _Str_11906) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.shampoo', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.shampoo', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.shampoo') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.shampoo') }</div>
</> } </> }
{ (mode === _Str_11214) && { (mode === _Str_11214) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.custompart', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.custompart', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.custompart') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.custompart') }</div>
</> } </> }
{ (mode === _Str_11733) && { (mode === _Str_11733) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.custompartshampoo', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.custompartshampoo', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.custompartshampoo') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.custompartshampoo') }</div>
</> } </> }
{ (mode === _Str_11369) && { (mode === _Str_11369) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.saddle', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.saddle', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.saddle') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.saddle') }</div>
</> } </> }
{ (mode === _Str_8759) && { (mode === _Str_8759) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.revive_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.revive_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.revive_monsterplant') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.revive_monsterplant') }</div>
</> } </> }
{ (mode === _Str_8432) && { (mode === _Str_8432) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.rebreed_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.rebreed_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.rebreed_monsterplant') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.rebreed_monsterplant') }</div>
</> } </> }
{ (mode === _Str_9653) && { (mode === _Str_9653) &&
<> <>
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.fertilize_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div> <div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.fertilize_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black text-italics">{ LocalizeText('useproduct.widget.info.fertilize_monsterplant') }</div> <div className="text-black">{ LocalizeText('useproduct.widget.info.fertilize_monsterplant') }</div>
</> } </> }
</div> </div>
<div className="d-flex justify-content-between align-items-center w-100"> <div className="d-flex justify-content-between align-items-end w-100 h-100">
<button type="button" className="btn btn-danger" onClick={ close }>{ LocalizeText('useproduct.widget.cancel') }</button> <button type="button" className="btn btn-danger" onClick={ close }>{ LocalizeText('useproduct.widget.cancel') }</button>
<button type="button" className="btn btn-primary" onClick={ useProduct }>{ LocalizeText('useproduct.widget.use') }</button> <button type="button" className="btn btn-primary" onClick={ useProduct }>{ LocalizeText('useproduct.widget.use') }</button>
</div> </div>

View File

@ -1,4 +1,4 @@
import { RoomObjectCategory } from 'nitro-renderer'; import { RoomObjectCategory, RoomObjectType } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { GetFurnitureDataForRoomObject } from '../../../../../../api'; import { GetFurnitureDataForRoomObject } from '../../../../../../api';
import { LocalizeText } from '../../../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../../../utils/LocalizeText';
@ -83,7 +83,7 @@ export const AvatarInfoUseProductView: FC<AvatarInfoUseProductViewProps> = props
}, [ item, updateConfirmingProduct ]); }, [ item, updateConfirmingProduct ]);
return ( return (
<ContextMenuView objectId={ item.id } category={ RoomObjectCategory.UNIT } close={ close }> <ContextMenuView objectId={ item.id } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
<ContextMenuHeaderView> <ContextMenuHeaderView>
{ item.name } { item.name }
</ContextMenuHeaderView> </ContextMenuHeaderView>

View File

@ -7,13 +7,12 @@ import { RoomWidgetCameraEvent } from '../../../../events/room-widgets/camera/Ro
import { useCameraEvent } from '../../../../hooks/events/nitro/camera/camera-event'; import { useCameraEvent } from '../../../../hooks/events/nitro/camera/camera-event';
import { useUiEvent } from '../../../../hooks/events/ui/ui-event'; import { useUiEvent } from '../../../../hooks/events/ui/ui-event';
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages/message-event'; import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages/message-event';
import { CameraWidgetViewProps } from './CameraWidgetView.types';
import { CameraWidgetContextProvider } from './context/CameraWidgetContext'; import { CameraWidgetContextProvider } from './context/CameraWidgetContext';
import { CameraWidgetCaptureView } from './views/capture/CameraWidgetCaptureView'; import { CameraWidgetCaptureView } from './views/capture/CameraWidgetCaptureView';
import { CameraWidgetCheckoutView } from './views/checkout/CameraWidgetCheckoutView'; import { CameraWidgetCheckoutView } from './views/checkout/CameraWidgetCheckoutView';
import { CameraWidgetEditorView } from './views/editor/CameraWidgetEditorView'; import { CameraWidgetEditorView } from './views/editor/CameraWidgetEditorView';
export const CameraWidgetView: FC<CameraWidgetViewProps> = props => export const CameraWidgetView: FC<{}> = props =>
{ {
const [ effectsReady, setEffectsReady ] = useState(false); const [ effectsReady, setEffectsReady ] = useState(false);

View File

@ -1,4 +0,0 @@
import { RoomWidgetProps } from '../RoomWidgets.types';
export interface CameraWidgetViewProps extends RoomWidgetProps
{}

View File

@ -6,10 +6,9 @@ import { LocalizeText } from '../../../../utils/LocalizeText';
import { useRoomContext } from '../../context/RoomContext'; import { useRoomContext } from '../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateInfostandUserEvent } from '../../events'; import { RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateInfostandUserEvent } from '../../events';
import { RoomWidgetChatMessage, RoomWidgetChatTypingMessage } from '../../messages'; import { RoomWidgetChatMessage, RoomWidgetChatTypingMessage } from '../../messages';
import { ChatInputViewProps } from './ChatInputView.types';
import { ChatInputStyleSelectorView } from './style-selector/ChatInputStyleSelectorView'; import { ChatInputStyleSelectorView } from './style-selector/ChatInputStyleSelectorView';
export const ChatInputView: FC<ChatInputViewProps> = props => export const ChatInputView: FC<{}> = props =>
{ {
const [ chatValue, setChatValue ] = useState<string>(''); const [ chatValue, setChatValue ] = useState<string>('');
const [ selectedUsername, setSelectedUsername ] = useState(''); const [ selectedUsername, setSelectedUsername ] = useState('');

View File

@ -1,6 +0,0 @@
import { RoomWidgetProps } from '../RoomWidgets.types';
export interface ChatInputViewProps extends RoomWidgetProps
{
}

View File

@ -3,11 +3,10 @@ import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { CreateEventDispatcherHook, useRoomEngineEvent } from '../../../../hooks/events'; import { CreateEventDispatcherHook, useRoomEngineEvent } from '../../../../hooks/events';
import { useRoomContext } from '../../context/RoomContext'; import { useRoomContext } from '../../context/RoomContext';
import { RoomWidgetUpdateChatEvent } from '../../events'; import { RoomWidgetUpdateChatEvent } from '../../events';
import { ChatWidgetViewProps } from './ChatWidgetView.types';
import { ChatWidgetMessageView } from './message/ChatWidgetMessageView'; import { ChatWidgetMessageView } from './message/ChatWidgetMessageView';
import { ChatBubbleMessage } from './utils/ChatBubbleMessage'; import { ChatBubbleMessage } from './utils/ChatBubbleMessage';
export const ChatWidgetView: FC<ChatWidgetViewProps> = props => export const ChatWidgetView: FC<{}> = props =>
{ {
const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]); const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]);
const { roomSession = null, eventDispatcher = null } = useRoomContext(); const { roomSession = null, eventDispatcher = null } = useRoomContext();

View File

@ -1,6 +0,0 @@
import { RoomWidgetProps } from '../RoomWidgets.types';
export interface ChatWidgetViewProps extends RoomWidgetProps
{
}

View File

@ -1,24 +1,43 @@
import { FixedSizeStack, Nitro } from 'nitro-renderer'; import { FixedSizeStack, Nitro, NitroPoint, NitroRectangle, RoomObjectType } from 'nitro-renderer';
import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { GetRoomObjectBounds, GetRoomSession, GetTicker } from '../../../../api'; import { GetRoomEngine, GetRoomObjectBounds, GetRoomSession, GetTicker } from '../../../../api';
import { ContextMenuViewProps } from './ContextMenuView.types'; import { ContextMenuViewProps } from './ContextMenuView.types';
const LOCATION_STACK_SIZE: number = 25;
const BUBBLE_DROP_SPEED: number = 3;
const fadeDelay = 3000; const fadeDelay = 3000;
const fadeLength = 75; const fadeLength = 75;
const SPACE_AROUND_EDGES = 10; const SPACE_AROUND_EDGES = 10;
export const ContextMenuView: FC<ContextMenuViewProps> = props => export const ContextMenuView: FC<ContextMenuViewProps> = props =>
{ {
const { objectId = -1, category = -1, fades = false, className = '', close = null, children = null } = props; const { objectId = -1, category = -1, userType = -1, fades = false, className = '', close = null, children = null } = props;
const [ pos, setPos ] = useState<{ x: number, y: number }>({ x: null, y: null }); const [ pos, setPos ] = useState<{ x: number, y: number }>({ x: null, y: null });
const [ stack, setStack ] = useState<FixedSizeStack>(null); const [ deltaYStack, setDeltaYStack ] = useState<FixedSizeStack>(null);
const [ currentDeltaY, setCurrentDeltaY ] = useState(-1000000);
const [ opacity, setOpacity ] = useState(1); const [ opacity, setOpacity ] = useState(1);
const [ isFading, setIsFading ] = useState(false); const [ isFading, setIsFading ] = useState(false);
const [ fadeTime, setFadeTime ] = useState(0); const [ fadeTime, setFadeTime ] = useState(0);
const [ frozen, setFrozen ] = useState(false); const [ frozen, setFrozen ] = useState(false);
const elementRef = useRef<HTMLDivElement>(); const elementRef = useRef<HTMLDivElement>();
const update = useCallback((time: number) => const getOffset = useCallback((bounds: NitroRectangle) =>
{
let height = -(elementRef.current.offsetHeight);
if((userType > -1) && ((userType === RoomObjectType.USER) || (userType === RoomObjectType.BOT) || (userType === RoomObjectType.RENTABLE_BOT)))
{
height = (height + ((bounds.height > 50) ? 15 : 0));
}
else
{
height = (height - 14);
}
return height;
}, [ userType ]);
const updateFade = useCallback((time: number) =>
{ {
let newFadeTime = time; let newFadeTime = time;
let newOpacity = 1; let newOpacity = 1;
@ -38,37 +57,59 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
{ {
close(); close();
return; return false;
} }
setOpacity(newOpacity); setOpacity(newOpacity);
} }
const bounds = GetRoomObjectBounds(GetRoomSession().roomId, objectId, category); return true;
}, [ isFading, close ]);
if(!bounds || !elementRef.current) return; const updatePosition = useCallback((bounds: NitroRectangle, location: NitroPoint) =>
{
if(!bounds || !location || !deltaYStack) return;
let left = Math.round((bounds.left + (bounds.width / 2)) - (elementRef.current.offsetWidth / 2)); const offset = getOffset(bounds);
let top = Math.round((bounds.top - elementRef.current.offsetHeight));
deltaYStack.addValue((location.y - bounds.top));
let maxStack = deltaYStack.getMax();
if(maxStack < (currentDeltaY - BUBBLE_DROP_SPEED)) maxStack = (currentDeltaY - BUBBLE_DROP_SPEED);
const deltaY = (location.y - maxStack);
let x = (location.x - (elementRef.current.offsetWidth / 2));
let y = (deltaY + offset);
const maxLeft = ((Nitro.instance.width - elementRef.current.offsetWidth) - SPACE_AROUND_EDGES); const maxLeft = ((Nitro.instance.width - elementRef.current.offsetWidth) - SPACE_AROUND_EDGES);
const maxTop = ((Nitro.instance.height - elementRef.current.offsetHeight) - SPACE_AROUND_EDGES); const maxTop = ((Nitro.instance.height - elementRef.current.offsetHeight) - SPACE_AROUND_EDGES);
if(left < SPACE_AROUND_EDGES) left = SPACE_AROUND_EDGES; if(x < SPACE_AROUND_EDGES) x = SPACE_AROUND_EDGES;
else if(left > maxLeft) left = maxLeft; else if(x > maxLeft) x = maxLeft;
if(top < SPACE_AROUND_EDGES) top = SPACE_AROUND_EDGES; if(y < SPACE_AROUND_EDGES) y = SPACE_AROUND_EDGES;
else if(top > maxTop) top = maxTop; else if(y > maxTop) y = maxTop;
setPos({ setCurrentDeltaY(maxStack);
x: left, setPos({ x, y });
y: top }, [ deltaYStack, currentDeltaY, getOffset ]);
});
}, [ objectId, category, isFading, close ]); const update = useCallback((time: number) =>
{
if(!elementRef.current || !updateFade(time)) return;
const bounds = GetRoomObjectBounds(GetRoomSession().roomId, objectId, category);
const location = GetRoomEngine().getRoomObjectScreenLocation(GetRoomSession().roomId, objectId, category);
updatePosition(bounds, location);
}, [ objectId, category, updateFade, updatePosition ]);
useEffect(() => useEffect(() =>
{ {
setStack(new FixedSizeStack(25)); setDeltaYStack(new FixedSizeStack(LOCATION_STACK_SIZE));
setCurrentDeltaY(-1000000);
}, []); }, []);
useEffect(() => useEffect(() =>
@ -101,7 +142,7 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
}, [ fades ]); }, [ fades ]);
return ( return (
<div ref={ elementRef } className={ `position-absolute nitro-context-menu ${ className }${ (pos.x !== null ? ' visible' : ' invisible') }` } style={ { left: (pos.x || 0), top: (pos.y || 0), opacity: opacity } } onMouseEnter={ event => setFrozen(true) } onMouseLeave={ event => setFrozen(false) }> <div ref={ elementRef } className={ `position-absolute nitro-context-menu ${ className }${ (pos.x !== null ? ' visible' : ' invisible') }` } style={ { left: (pos.x || 0), top: (pos.y || 0), opacity: opacity } }>
{ children } { children }
</div> </div>
); );

View File

@ -2,6 +2,7 @@ export interface ContextMenuViewProps
{ {
objectId: number; objectId: number;
category: number; category: number;
userType?: number;
fades?: boolean; fades?: boolean;
className?: string; className?: string;
close: () => void; close: () => void;

View File

@ -1,4 +0,0 @@
import { RoomWidgetProps } from '../RoomWidgets.types';
export interface FurnitureWidgetProps extends RoomWidgetProps
{}

View File

@ -1,6 +1,6 @@
@import './engraving-lock/FurnitureEngravingLockView';
@import './dimmer/FurnitureDimmerView'; @import './dimmer/FurnitureDimmerView';
@import './exchange-credit/FurnitureExchangeCreditView'; @import './exchange-credit/FurnitureExchangeCreditView';
@import './friend-furni/FurnitureFriendFurniView';
@import './manipulation-menu/FurnitureManipulationMenuView'; @import './manipulation-menu/FurnitureManipulationMenuView';
@import './mannequin/FurnitureMannequinView'; @import './mannequin/FurnitureMannequinView';
@import './stickie/FurnitureStickieView'; @import './stickie/FurnitureStickieView';

View File

@ -2,9 +2,8 @@ import { FC } from 'react';
import { FurnitureBackgroundColorView } from './background-color/FurnitureBackgroundColorView'; import { FurnitureBackgroundColorView } from './background-color/FurnitureBackgroundColorView';
import { FurnitureContextMenuView } from './context-menu/FurnitureContextMenuView'; import { FurnitureContextMenuView } from './context-menu/FurnitureContextMenuView';
import { FurnitureDimmerView } from './dimmer/FurnitureDimmerView'; import { FurnitureDimmerView } from './dimmer/FurnitureDimmerView';
import { FurnitureEngravingLockView } from './engraving-lock/FurnitureEngravingLockView';
import { FurnitureExchangeCreditView } from './exchange-credit/FurnitureExchangeCreditView'; import { FurnitureExchangeCreditView } from './exchange-credit/FurnitureExchangeCreditView';
import { FurnitureWidgetsViewProps } from './FurnitureWidgetsView.types'; import { FurnitureFriendFurniView } from './friend-furni/FurnitureFriendFurniView';
import { FurnitureHighScoreView } from './high-score/FurnitureHighScoreView'; import { FurnitureHighScoreView } from './high-score/FurnitureHighScoreView';
import { FurnitureManipulationMenuView } from './manipulation-menu/FurnitureManipulationMenuView'; import { FurnitureManipulationMenuView } from './manipulation-menu/FurnitureManipulationMenuView';
import { FurnitureMannequinView } from './mannequin/FurnitureMannequinView'; import { FurnitureMannequinView } from './mannequin/FurnitureMannequinView';
@ -12,14 +11,14 @@ import { FurniturePresentView } from './present/FurniturePresentView';
import { FurnitureStickieView } from './stickie/FurnitureStickieView'; import { FurnitureStickieView } from './stickie/FurnitureStickieView';
import { FurnitureTrophyView } from './trophy/FurnitureTrophyView'; import { FurnitureTrophyView } from './trophy/FurnitureTrophyView';
export const FurnitureWidgetsView: FC<FurnitureWidgetsViewProps> = props => export const FurnitureWidgetsView: FC<{}> = props =>
{ {
return ( return (
<div className="position-absolute nitro-room-widgets t-0 l-0"> <div className="position-absolute nitro-room-widgets t-0 l-0">
<FurnitureBackgroundColorView /> <FurnitureBackgroundColorView />
<FurnitureContextMenuView /> <FurnitureContextMenuView />
<FurnitureDimmerView /> <FurnitureDimmerView />
<FurnitureEngravingLockView /> <FurnitureFriendFurniView />
<FurnitureExchangeCreditView /> <FurnitureExchangeCreditView />
<FurnitureHighScoreView /> <FurnitureHighScoreView />
<FurnitureManipulationMenuView /> <FurnitureManipulationMenuView />

View File

@ -1,6 +0,0 @@
import { FurnitureWidgetProps } from './FurnitureWidget.types';
export interface FurnitureWidgetsViewProps extends FurnitureWidgetProps
{
}

View File

@ -1,73 +1,91 @@
import { ContextMenuEnum, IRoomObject, RoomEngineObjectEvent, RoomEngineTriggerWidgetEvent, RoomObjectCategory } from 'nitro-renderer'; import { ContextMenuEnum, RoomEngineTriggerWidgetEvent, RoomObjectCategory } from 'nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { GetRoomEngine, IsOwnerOfFurniture } from '../../../../../api'; import { GetRoomEngine, IsOwnerOfFurniture } from '../../../../../api';
import { useRoomEngineEvent } from '../../../../../hooks/events'; import { useRoomEngineEvent } from '../../../../../hooks/events';
import { LocalizeText } from '../../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../../utils/LocalizeText';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetFurniActionMessage } from '../../../messages';
import { ContextMenuView } from '../../context-menu/ContextMenuView'; import { ContextMenuView } from '../../context-menu/ContextMenuView';
import { ContextMenuHeaderView } from '../../context-menu/views/header/ContextMenuHeaderView'; import { ContextMenuHeaderView } from '../../context-menu/views/header/ContextMenuHeaderView';
import { ContextMenuListItemView } from '../../context-menu/views/list-item/ContextMenuListItemView'; import { ContextMenuListItemView } from '../../context-menu/views/list-item/ContextMenuListItemView';
import { MonsterPlantSeedConfirmView } from './views/monsterplant-seed/MonsterPlantSeedConfirmView';
import { PurchasableClothingConfirmView } from './views/purchaseable-clothing/PurchasableClothingConfirmView';
const MONSTERPLANT_SEED_CONFIRMATION: string = 'MONSTERPLANT_SEED_CONFIRMATION'; const MONSTERPLANT_SEED_CONFIRMATION: string = 'MONSTERPLANT_SEED_CONFIRMATION';
const PURCHASABLE_CLOTHING_CONFIRMATION: string = 'PURCHASABLE_CLOTHING_CONFIRMATION';
export const FurnitureContextMenuView: FC<{}> = props => export const FurnitureContextMenuView: FC<{}> = props =>
{ {
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext(); const [ objectId, setObjectId ] = useState(-1);
const [ roomObject, setRoomObject ] = useState<IRoomObject>(null); const [ mode, setMode ] = useState<string>(null);
const [ contextMenu, setContextMenu ] = useState<string>(null); const [ confirmMode, setConfirmMode ] = useState<string>(null);
const [ confirmingObjectId, setConfirmingObjectId ] = useState(-1);
const { roomSession = null, widgetHandler = null } = useRoomContext();
const close = useCallback(() => const close = useCallback(() =>
{ {
setRoomObject(null); setObjectId(-1);
setContextMenu(null); setMode(null);
}, []);
const closeConfirm = useCallback(() =>
{
setConfirmMode(null);
setConfirmingObjectId(-1);
}, []); }, []);
const onRoomEngineTriggerWidgetEvent = useCallback((event: RoomEngineTriggerWidgetEvent) => const onRoomEngineTriggerWidgetEvent = useCallback((event: RoomEngineTriggerWidgetEvent) =>
{ {
const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, event.objectId, event.category); const object = GetRoomEngine().getRoomObject(roomSession.roomId, event.objectId, event.category);
if(!roomObject) return; if(!object) return;
switch(event.type) switch(event.type)
{ {
case RoomEngineTriggerWidgetEvent.REQUEST_MONSTERPLANT_SEED_PLANT_CONFIRMATION_DIALOG:
setConfirmingObjectId(object.id);
setConfirmMode(MONSTERPLANT_SEED_CONFIRMATION);
close();
return;
case RoomEngineTriggerWidgetEvent.REQUEST_PURCHASABLE_CLOTHING_CONFIRMATION_DIALOG:
setConfirmingObjectId(object.id);
setConfirmMode(PURCHASABLE_CLOTHING_CONFIRMATION);
close();
return;
case RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU: case RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU:
setObjectId(object.id);
switch(event.contextMenu) switch(event.contextMenu)
{ {
case ContextMenuEnum.FRIEND_FURNITURE: case ContextMenuEnum.FRIEND_FURNITURE:
setMode(ContextMenuEnum.FRIEND_FURNITURE);
return; return;
case ContextMenuEnum.MONSTERPLANT_SEED: case ContextMenuEnum.MONSTERPLANT_SEED:
if(IsOwnerOfFurniture(roomObject)) if(IsOwnerOfFurniture(object)) setMode(ContextMenuEnum.MONSTERPLANT_SEED);
{
setRoomObject(roomObject);
setContextMenu(ContextMenuEnum.MONSTERPLANT_SEED);
}
return; return;
case ContextMenuEnum.MYSTERY_BOX: case ContextMenuEnum.MYSTERY_BOX:
return; return;
case ContextMenuEnum.RANDOM_TELEPORT: case ContextMenuEnum.RANDOM_TELEPORT:
setMode(ContextMenuEnum.RANDOM_TELEPORT);
return; return;
case ContextMenuEnum.PURCHASABLE_CLOTHING: case ContextMenuEnum.PURCHASABLE_CLOTHING:
if(IsOwnerOfFurniture(object)) setMode(ContextMenuEnum.PURCHASABLE_CLOTHING);
return; return;
} }
return; return;
case RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU: case RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU:
close(); if(object.id === objectId) close();
return; return;
} }
}, [ roomSession, close ]); }, [ roomSession, objectId, close ]);
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU, onRoomEngineTriggerWidgetEvent); useRoomEngineEvent(RoomEngineTriggerWidgetEvent.OPEN_FURNI_CONTEXT_MENU, onRoomEngineTriggerWidgetEvent);
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU, onRoomEngineTriggerWidgetEvent); useRoomEngineEvent(RoomEngineTriggerWidgetEvent.CLOSE_FURNI_CONTEXT_MENU, onRoomEngineTriggerWidgetEvent);
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_MONSTERPLANT_SEED_PLANT_CONFIRMATION_DIALOG, onRoomEngineTriggerWidgetEvent);
const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) => useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PURCHASABLE_CLOTHING_CONFIRMATION_DIALOG, onRoomEngineTriggerWidgetEvent);
{
if(!roomObject || (event.objectId !== roomObject.id)) return;
close();
}, [ roomObject, close ]);
useRoomEngineEvent(RoomEngineObjectEvent.REMOVED, onRoomEngineObjectEvent);
const processAction = useCallback((name: string) => const processAction = useCallback((name: string) =>
{ {
@ -75,26 +93,69 @@ export const FurnitureContextMenuView: FC<{}> = props =>
{ {
switch(name) switch(name)
{ {
case 'use_friend_furni':
roomSession.useMultistateItem(objectId);
break;
case 'use_monsterplant_seed': case 'use_monsterplant_seed':
setContextMenu(MONSTERPLANT_SEED_CONFIRMATION); setConfirmMode(MONSTERPLANT_SEED_CONFIRMATION);
setConfirmingObjectId(objectId);
break;
case 'use_random_teleport':
widgetHandler.processWidgetMessage(new RoomWidgetFurniActionMessage(RoomWidgetFurniActionMessage.USE, objectId, RoomObjectCategory.FLOOR));
break;
case 'use_purchaseable_clothing':
setConfirmMode(PURCHASABLE_CLOTHING_CONFIRMATION);
setConfirmingObjectId(objectId);
break; break;
} }
} }
}, [ ]);
if(!roomObject || !contextMenu) return null; close();
}, [ roomSession, widgetHandler, objectId, close ]);
return ( return (
<ContextMenuView objectId={ roomObject.id } category={ RoomObjectCategory.FLOOR } close={ close }> <>
{ (contextMenu === ContextMenuEnum.MONSTERPLANT_SEED) && { (confirmMode === MONSTERPLANT_SEED_CONFIRMATION) && <MonsterPlantSeedConfirmView objectId={ confirmingObjectId } close={ closeConfirm } /> }
<> { (confirmMode === PURCHASABLE_CLOTHING_CONFIRMATION) && <PurchasableClothingConfirmView objectId={ confirmingObjectId } close={ closeConfirm } /> }
<ContextMenuHeaderView> { (objectId >= 0) && mode &&
{ LocalizeText('furni.mnstr_seed.name') } <ContextMenuView objectId={ objectId } category={ RoomObjectCategory.FLOOR } close={ close } fades={ true }>
</ContextMenuHeaderView> { (mode === ContextMenuEnum.FRIEND_FURNITURE) &&
<ContextMenuListItemView onClick={ event => processAction('use_monsterplant_seed') }> <>
{ LocalizeText('widget.monsterplant_seed.button.use') } <ContextMenuHeaderView>
</ContextMenuListItemView> { LocalizeText('friendfurni.context.title') }
</> } </ContextMenuHeaderView>
</ContextMenuView> <ContextMenuListItemView onClick={ event => processAction('use_friend_furni') }>
{ LocalizeText('friendfurni.context.use') }
</ContextMenuListItemView>
</> }
{ (mode === ContextMenuEnum.MONSTERPLANT_SEED) &&
<>
<ContextMenuHeaderView>
{ LocalizeText('furni.mnstr_seed.name') }
</ContextMenuHeaderView>
<ContextMenuListItemView onClick={ event => processAction('use_monsterplant_seed') }>
{ LocalizeText('widget.monsterplant_seed.button.use') }
</ContextMenuListItemView>
</> }
{ (mode === ContextMenuEnum.RANDOM_TELEPORT) &&
<>
<ContextMenuHeaderView>
{ LocalizeText('furni.random_teleport.name') }
</ContextMenuHeaderView>
<ContextMenuListItemView onClick={ event => processAction('use_random_teleport') }>
{ LocalizeText('widget.random_teleport.button.use') }
</ContextMenuListItemView>
</> }
{ (mode === ContextMenuEnum.PURCHASABLE_CLOTHING) &&
<>
<ContextMenuHeaderView>
{ LocalizeText('furni.generic_usable.name') }
</ContextMenuHeaderView>
<ContextMenuListItemView onClick={ event => processAction('use_purchaseable_clothing') }>
{ LocalizeText('widget.generic_usable.button.use') }
</ContextMenuListItemView>
</> }
</ContextMenuView> }
</>
) )
} }

View File

@ -0,0 +1,83 @@
import { IFurnitureData, RoomObjectCategory } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { GetFurnitureDataForRoomObject } from '../../../../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../../../layout';
import { LocalizeText } from '../../../../../../../utils/LocalizeText';
import { FurniCategory } from '../../../../../../inventory/common/FurniCategory';
import { useRoomContext } from '../../../../../context/RoomContext';
import { RoomWidgetUseProductMessage } from '../../../../../messages';
import { MonsterPlantSeedConfirmViewProps } from './MonsterPlantSeedConfirmView.types';
const MODE_DEFAULT: number = -1;
const MODE_MONSTERPLANT_SEED: number = 0;
export const MonsterPlantSeedConfirmView: FC<MonsterPlantSeedConfirmViewProps> = props =>
{
const { objectId = -1, close = null } = props;
const [ furniData, setFurniData ] = useState<IFurnitureData>(null);
const [ mode, setMode ] = useState(MODE_DEFAULT);
const { roomSession = null, widgetHandler = null } = useRoomContext();
const useProduct = useCallback(() =>
{
widgetHandler.processWidgetMessage(new RoomWidgetUseProductMessage(RoomWidgetUseProductMessage.MONSTERPLANT_SEED, objectId));
close();
}, [ widgetHandler, objectId, close ]);
useEffect(() =>
{
if(!roomSession || (objectId === -1)) return;
const furniData = GetFurnitureDataForRoomObject(roomSession.roomId, objectId, RoomObjectCategory.FLOOR);
if(!furniData) return;
setFurniData(furniData);
let mode = MODE_DEFAULT;
switch(furniData.specialType)
{
case FurniCategory.MONSTERPLANT_SEED:
mode = MODE_MONSTERPLANT_SEED;
break;
}
if(mode === MODE_DEFAULT)
{
close();
return;
}
setMode(mode);
}, [ roomSession, objectId, close ]);
if(mode === MODE_DEFAULT) return null;
return (
<NitroCardView className="nitro-use-product-confirmation">
<NitroCardHeaderView headerText={ LocalizeText('useproduct.widget.title.plant_seed', [ 'name' ], [ furniData.name ]) } onCloseClick={ close } />
<NitroCardContentView className="d-flex">
<div className="row">
<div className="w-unset">
<div className="product-preview">
<div className="monsterplant-image" />
</div>
</div>
<div className="col d-flex flex-column justify-content-between">
<div className="d-flex flex-column">
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.plant_seed', [ 'productName' ], [ furniData.name ] ) }</div>
<div className="text-black">{ LocalizeText('useproduct.widget.info.plant_seed') }</div>
</div>
<div className="d-flex justify-content-between align-items-end w-100 h-100">
<button type="button" className="btn btn-danger" onClick={ close }>{ LocalizeText('useproduct.widget.cancel') }</button>
<button type="button" className="btn btn-primary" onClick={ useProduct }>{ LocalizeText('widget.monsterplant_seed.button.use') }</button>
</div>
</div>
</div>
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -0,0 +1,5 @@
export interface MonsterPlantSeedConfirmViewProps
{
objectId: number;
close: () => void;
}

View File

@ -0,0 +1,102 @@
import { FigureData, RedeemItemClothingComposer, RoomObjectCategory, UserFigureComposer } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { GetAvatarRenderManager, GetConnection, GetFurnitureDataForRoomObject, GetSessionDataManager } from '../../../../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../../../layout';
import { LocalizeText } from '../../../../../../../utils/LocalizeText';
import { FurniCategory } from '../../../../../../inventory/common/FurniCategory';
import { AvatarImageView } from '../../../../../../shared/avatar-image/AvatarImageView';
import { useRoomContext } from '../../../../../context/RoomContext';
import { PurchasableClothingConfirmViewProps } from './PurchasableClothingConfirmView.types';
const MODE_DEFAULT: number = -1;
const MODE_PURCHASABLE_CLOTHING: number = 0;
export const PurchasableClothingConfirmView: FC<PurchasableClothingConfirmViewProps> = props =>
{
const { objectId = -1, close = null } = props;
const [ mode, setMode ] = useState(MODE_DEFAULT);
const [ gender, setGender ] = useState<string>(FigureData.MALE);
const [ newFigure, setNewFigure ] = useState<string>(null);
const { roomSession = null } = useRoomContext();
const useProduct = useCallback(() =>
{
GetConnection().send(new RedeemItemClothingComposer(objectId));
GetConnection().send(new UserFigureComposer(gender, newFigure));
close();
}, [ objectId, gender, newFigure, close ]);
useEffect(() =>
{
let mode = MODE_DEFAULT;
const figure = GetSessionDataManager().figure;
const gender = GetSessionDataManager().gender;
const validSets: number[] = [];
if(roomSession && (objectId >= 0))
{
const furniData = GetFurnitureDataForRoomObject(roomSession.roomId, objectId, RoomObjectCategory.FLOOR);
if(furniData)
{
switch(furniData.specialType)
{
case FurniCategory._Str_12534:
mode = MODE_PURCHASABLE_CLOTHING;
const setIds = furniData.customParams.split(',').map(part => parseInt(part));
for(const setId of setIds)
{
if(GetAvatarRenderManager().isValidFigureSetForGender(setId, gender)) validSets.push(setId);
}
break;
}
}
}
if(mode === MODE_DEFAULT)
{
close();
return;
}
setGender(gender);
setNewFigure(GetAvatarRenderManager().getFigureStringWithFigureIds(figure, gender, validSets));
// if owns clothing, change to it
setMode(mode);
}, [ roomSession, objectId, close ]);
if(mode === MODE_DEFAULT) return null;
return (
<NitroCardView className="nitro-use-product-confirmation">
<NitroCardHeaderView headerText={ LocalizeText('useproduct.widget.title.bind_clothing') } onCloseClick={ close } />
<NitroCardContentView className="d-flex">
<div className="row">
<div className="w-unset">
<div className="mannequin-preview">
<AvatarImageView figure={ newFigure } direction={ 2 } />
</div>
</div>
<div className="col d-flex flex-column justify-content-between">
<div className="d-flex flex-column">
<div className="text-black mb-3">{ LocalizeText('useproduct.widget.text.bind_clothing') }</div>
<div className="text-black">{ LocalizeText('useproduct.widget.info.bind_clothing') }</div>
</div>
<div className="d-flex justify-content-between align-items-end w-100 h-100">
<button type="button" className="btn btn-danger" onClick={ close }>{ LocalizeText('useproduct.widget.cancel') }</button>
<button type="button" className="btn btn-primary" onClick={ useProduct }>{ LocalizeText('useproduct.widget.bind_clothing') }</button>
</div>
</div>
</div>
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -0,0 +1,5 @@
export interface PurchasableClothingConfirmViewProps
{
objectId: number;
close: () => void;
}

View File

@ -3,9 +3,8 @@ import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../
import { LocalizeText } from '../../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../../utils/LocalizeText';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { FurnitureDimmerData } from './FurnitureDimmerData'; import { FurnitureDimmerData } from './FurnitureDimmerData';
import { FurnitureDimmerViewProps } from './FurnitureDimmerView.types';
export const FurnitureDimmerView: FC<FurnitureDimmerViewProps> = props => export const FurnitureDimmerView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ dimmerData, setDimmerData ] = useState<FurnitureDimmerData>(null); const [ dimmerData, setDimmerData ] = useState<FurnitureDimmerData>(null);

View File

@ -1,4 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureDimmerViewProps extends FurnitureWidgetProps
{}

View File

@ -1,4 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureEngravingLockViewProps extends FurnitureWidgetProps
{}

View File

@ -8,9 +8,8 @@ import { LocalizeText } from '../../../../../utils/LocalizeText';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../../events';
import { FurnitureExchangeCreditData } from './FurnitureExchangeCreditData'; import { FurnitureExchangeCreditData } from './FurnitureExchangeCreditData';
import { FurnitureExchangeCreditProps } from './FurnitureExchangeCreditView.types';
export const FurnitureExchangeCreditView: FC<FurnitureExchangeCreditProps> = props => export const FurnitureExchangeCreditView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ exchangeCreditData, setExchangeCreditData ] = useState<FurnitureExchangeCreditData>(null); const [ exchangeCreditData, setExchangeCreditData ] = useState<FurnitureExchangeCreditData>(null);

View File

@ -1,4 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureExchangeCreditProps extends FurnitureWidgetProps
{}

View File

@ -10,10 +10,9 @@ import { LocalizeText } from '../../../../../utils/LocalizeText';
import { AvatarImageView } from '../../../../shared/avatar-image/AvatarImageView'; import { AvatarImageView } from '../../../../shared/avatar-image/AvatarImageView';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../../events';
import { FurnitureEngravingLockData } from './FurnitureEngravingLockData'; import { FurnitureEngravingLockData } from './FriendFurniLockData';
import { FurnitureEngravingLockViewProps } from './FurnitureEngravingLockView.types';
export const FurnitureEngravingLockView: FC<FurnitureEngravingLockViewProps> = props => export const FurnitureFriendFurniView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ engravingLockData, setEngravingLockData ] = useState<FurnitureEngravingLockData>(null); const [ engravingLockData, setEngravingLockData ] = useState<FurnitureEngravingLockData>(null);

View File

@ -2,9 +2,8 @@ import { NitroEvent, RoomEngineTriggerWidgetEvent } from 'nitro-renderer';
import { FC } from 'react'; import { FC } from 'react';
import { useRoomEngineEvent } from '../../../../../hooks/events/nitro/room/room-engine-event'; import { useRoomEngineEvent } from '../../../../../hooks/events/nitro/room/room-engine-event';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { FurnitureHighScoreViewProps } from './FurnitureHighScoreView.types';
export const FurnitureHighScoreView: FC<FurnitureHighScoreViewProps> = props => export const FurnitureHighScoreView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();

View File

@ -1,6 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureHighScoreViewProps extends FurnitureWidgetProps
{
}

View File

@ -5,9 +5,8 @@ import { CreateEventDispatcherHook } from '../../../../../hooks/events/event-dis
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../../events';
import { ObjectLocationView } from '../../object-location/ObjectLocationView'; import { ObjectLocationView } from '../../object-location/ObjectLocationView';
import { FurnitureManipulationMenuViewProps } from './FurnitureManipulationMenuView.types';
export const FurnitureManipulationMenuView: FC<FurnitureManipulationMenuViewProps> = props => export const FurnitureManipulationMenuView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ isVisible, setIsVisible ] = useState(false); const [ isVisible, setIsVisible ] = useState(false);

View File

@ -1,6 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureManipulationMenuViewProps extends FurnitureWidgetProps
{
}

View File

@ -10,8 +10,8 @@ import { LocalizeText } from '../../../../../utils/LocalizeText';
import { AvatarImageView } from '../../../../shared/avatar-image/AvatarImageView'; import { AvatarImageView } from '../../../../shared/avatar-image/AvatarImageView';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../../events';
import { MannequinViewMode } from './common/MannequinViewMode';
import { FurnitureMannequinData } from './FurnitureMannequinData'; import { FurnitureMannequinData } from './FurnitureMannequinData';
import { FurnitureMannequinViewMode, FurnitureMannequinViewProps } from './FurnitureMannequinView.types';
const parts = [ const parts = [
AvatarFigurePartType.CHEST_ACCESSORY, AvatarFigurePartType.CHEST_ACCESSORY,
@ -23,7 +23,7 @@ const parts = [
]; ];
const baseAvatar = ['hd', 99999, 99998]; const baseAvatar = ['hd', 99999, 99998];
export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props => export const FurnitureMannequinView: FC<{}> = props =>
{ {
const { eventDispatcher = null } = useRoomContext(); const { eventDispatcher = null } = useRoomContext();
@ -64,7 +64,7 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
if(userCanEdit) if(userCanEdit)
{ {
setViewMode(FurnitureMannequinViewMode.EDIT); setViewMode(MannequinViewMode.EDIT);
} }
else else
{ {
@ -72,15 +72,15 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
if(userGender.toUpperCase() !== mannequinData.gender.toUpperCase()) if(userGender.toUpperCase() !== mannequinData.gender.toUpperCase())
{ {
setViewMode(FurnitureMannequinViewMode.INCOMPATIBLE_GENDER); setViewMode(MannequinViewMode.INCOMPATIBLE_GENDER);
} }
else if(userClubLevel < mannequinData.clubLevel) else if(userClubLevel < mannequinData.clubLevel)
{ {
setViewMode(FurnitureMannequinViewMode.CLUB); setViewMode(MannequinViewMode.CLUB);
} }
else else
{ {
setViewMode(FurnitureMannequinViewMode.DEFAULT); setViewMode(MannequinViewMode.DEFAULT);
} }
} }
}, []); }, []);
@ -138,11 +138,11 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
return; return;
case 'load_figure': case 'load_figure':
loadMannequinFigure(Nitro.instance.avatar.createFigureContainer(Nitro.instance.sessionDataManager.figure)); loadMannequinFigure(Nitro.instance.avatar.createFigureContainer(Nitro.instance.sessionDataManager.figure));
setViewMode(FurnitureMannequinViewMode.SAVE); setViewMode(MannequinViewMode.SAVE);
return; return;
case 'back': case 'back':
loadMannequinFigure(Nitro.instance.avatar.createFigureContainer(mannequinData.figure)); loadMannequinFigure(Nitro.instance.avatar.createFigureContainer(mannequinData.figure));
setViewMode(FurnitureMannequinViewMode.EDIT); setViewMode(MannequinViewMode.EDIT);
return; return;
case 'save_name': case 'save_name':
GetRoomSession().connection.send(new FurnitureMannequinSaveNameComposer(mannequinData.objectId, mannequinData.name)); GetRoomSession().connection.send(new FurnitureMannequinSaveNameComposer(mannequinData.objectId, mannequinData.name));
@ -179,7 +179,7 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
</div> </div>
</div> </div>
<div className="d-flex flex-column justify-content-between col"> <div className="d-flex flex-column justify-content-between col">
{ viewMode === FurnitureMannequinViewMode.DEFAULT && { viewMode === MannequinViewMode.DEFAULT &&
<> <>
<div className="h-100"> <div className="h-100">
<div className="mb-1 text-black fw-bold">{ mannequinData.name }</div> <div className="mb-1 text-black fw-bold">{ mannequinData.name }</div>
@ -187,7 +187,7 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
</div> </div>
<div className="btn btn-success float-end" onClick={ event => processAction('wear') }>{ LocalizeText('mannequin.widget.wear') }</div> <div className="btn btn-success float-end" onClick={ event => processAction('wear') }>{ LocalizeText('mannequin.widget.wear') }</div>
</> } </> }
{ viewMode === FurnitureMannequinViewMode.EDIT && { viewMode === MannequinViewMode.EDIT &&
<> <>
<input type="text" className="form-control mb-2" value={ mannequinData.name } onChange={ event => processAction('set_name', event.target.value) } onKeyDown={ event => handleKeyDown(event) } /> <input type="text" className="form-control mb-2" value={ mannequinData.name } onChange={ event => processAction('set_name', event.target.value) } onKeyDown={ event => handleKeyDown(event) } />
<div className="d-flex flex-column w-100"> <div className="d-flex flex-column w-100">
@ -195,7 +195,7 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
<div className="btn btn-success w-100" onClick={ event => processAction('wear') }>{ LocalizeText('mannequin.widget.wear') }</div> <div className="btn btn-success w-100" onClick={ event => processAction('wear') }>{ LocalizeText('mannequin.widget.wear') }</div>
</div> </div>
</> } </> }
{ viewMode === FurnitureMannequinViewMode.SAVE && { viewMode === MannequinViewMode.SAVE &&
<> <>
<div className="h-100"> <div className="h-100">
<div className="mb-1 text-black fw-bold">{ mannequinData.name }</div> <div className="mb-1 text-black fw-bold">{ mannequinData.name }</div>
@ -206,9 +206,9 @@ export const FurnitureMannequinView: FC<FurnitureMannequinViewProps> = props =>
<div className="btn btn-success" onClick={ event => processAction('save_figure') }>{ LocalizeText('mannequin.widget.save') }</div> <div className="btn btn-success" onClick={ event => processAction('save_figure') }>{ LocalizeText('mannequin.widget.save') }</div>
</div> </div>
</> } </> }
{ viewMode === FurnitureMannequinViewMode.CLUB && { viewMode === MannequinViewMode.CLUB &&
<div className="text-black">{ LocalizeText('mannequin.widget.clubnotification') }</div> } <div className="text-black">{ LocalizeText('mannequin.widget.clubnotification') }</div> }
{ viewMode === FurnitureMannequinViewMode.INCOMPATIBLE_GENDER && { viewMode === MannequinViewMode.INCOMPATIBLE_GENDER &&
<div className="text-black">{ LocalizeText('mannequin.widget.wronggender') }</div> } <div className="text-black">{ LocalizeText('mannequin.widget.wronggender') }</div> }
</div> </div>
</div> </div>

View File

@ -1,9 +1,4 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types'; export class MannequinViewMode
export interface FurnitureMannequinViewProps extends FurnitureWidgetProps
{}
export class FurnitureMannequinViewMode
{ {
public static readonly EDIT: string = 'edit'; public static readonly EDIT: string = 'edit';
public static readonly SAVE: string = 'save'; public static readonly SAVE: string = 'save';

View File

@ -2,9 +2,8 @@ import { NitroEvent, RoomEngineTriggerWidgetEvent } from 'nitro-renderer';
import { FC } from 'react'; import { FC } from 'react';
import { useRoomEngineEvent } from '../../../../../hooks/events/nitro/room/room-engine-event'; import { useRoomEngineEvent } from '../../../../../hooks/events/nitro/room/room-engine-event';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { FurniturePresentViewProps } from './FurniturePresentView.types';
export const FurniturePresentView: FC<FurniturePresentViewProps> = props => export const FurniturePresentView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();

View File

@ -1,6 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurniturePresentViewProps extends FurnitureWidgetProps
{
}

View File

@ -9,9 +9,8 @@ import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../../events';
import { FurnitureStickieData } from './FurnitureStickieData'; import { FurnitureStickieData } from './FurnitureStickieData';
import { getStickieColorName, STICKIE_COLORS } from './FurnitureStickieUtils'; import { getStickieColorName, STICKIE_COLORS } from './FurnitureStickieUtils';
import { FurnitureStickieViewProps } from './FurnitureStickieView.types';
export const FurnitureStickieView: FC<FurnitureStickieViewProps> = props => export const FurnitureStickieView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ stickieData, setStickieData ] = useState<FurnitureStickieData>(null); const [ stickieData, setStickieData ] = useState<FurnitureStickieData>(null);

View File

@ -1,6 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureStickieViewProps extends FurnitureWidgetProps
{
}

View File

@ -8,9 +8,8 @@ import { LocalizeText } from '../../../../../utils/LocalizeText';
import { useRoomContext } from '../../../context/RoomContext'; import { useRoomContext } from '../../../context/RoomContext';
import { RoomWidgetRoomObjectUpdateEvent } from '../../../events'; import { RoomWidgetRoomObjectUpdateEvent } from '../../../events';
import { FurnitureTrophyData } from './FurnitureTrophyData'; import { FurnitureTrophyData } from './FurnitureTrophyData';
import { FurnitureTrophyViewProps } from './FurnitureTrophyView.types';
export const FurnitureTrophyView: FC<FurnitureTrophyViewProps> = props => export const FurnitureTrophyView: FC<{}> = props =>
{ {
const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ trophyData, setTrophyData ] = useState<FurnitureTrophyData>(null); const [ trophyData, setTrophyData ] = useState<FurnitureTrophyData>(null);

View File

@ -1,4 +0,0 @@
import { FurnitureWidgetProps } from '../FurnitureWidget.types';
export interface FurnitureTrophyViewProps extends FurnitureWidgetProps
{}

View File

@ -3,6 +3,7 @@ import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../../../utils/LocalizeText'; import { LocalizeText } from '../../../../../../utils/LocalizeText';
import { BadgeImageView } from '../../../../../shared/badge-image/BadgeImageView'; import { BadgeImageView } from '../../../../../shared/badge-image/BadgeImageView';
import { LimitedEditionCompactPlateView } from '../../../../../shared/limited-edition/compact-plate/LimitedEditionCompactPlateView'; import { LimitedEditionCompactPlateView } from '../../../../../shared/limited-edition/compact-plate/LimitedEditionCompactPlateView';
import { RarityLevelView } from '../../../../../shared/rarity-level/RarityLevelView';
import { useRoomContext } from '../../../../context/RoomContext'; import { useRoomContext } from '../../../../context/RoomContext';
import { RoomWidgetFurniActionMessage } from '../../../../messages'; import { RoomWidgetFurniActionMessage } from '../../../../messages';
import { InfoStandBaseView } from '../base/InfoStandBaseView'; import { InfoStandBaseView } from '../base/InfoStandBaseView';
@ -183,6 +184,10 @@ export const InfoStandWidgetFurniView: FC<InfoStandWidgetFurniViewProps> = props
<div className="position-absolute r-0"> <div className="position-absolute r-0">
<LimitedEditionCompactPlateView uniqueNumber={ furniData.stuffData.uniqueNumber } uniqueSeries={ furniData.stuffData.uniqueSeries } /> <LimitedEditionCompactPlateView uniqueNumber={ furniData.stuffData.uniqueNumber } uniqueSeries={ furniData.stuffData.uniqueSeries } />
</div> } </div> }
{ (furniData.stuffData.rarityLevel > -1) &&
<div className="position-absolute r-0">
<RarityLevelView level={ furniData.stuffData.rarityLevel } />
</div> }
{ furniData.image.src.length && { furniData.image.src.length &&
<img className="d-block mx-auto" src={ furniData.image.src } alt="" /> } <img className="d-block mx-auto" src={ furniData.image.src } alt="" /> }
</div> </div>