mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 14:40:50 +01:00
Update decorate mode
This commit is contained in:
parent
7581d8cdf2
commit
9769dcf887
@ -0,0 +1,20 @@
|
|||||||
|
import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
|
||||||
|
|
||||||
|
export class RoomWidgetUpdateDecorateModeEvent extends RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
public static UPDATE_DECORATE: string = 'RWUDME_UPDATE_DECORATE';
|
||||||
|
|
||||||
|
private _isDecorating: boolean;
|
||||||
|
|
||||||
|
constructor(isDecorating: boolean)
|
||||||
|
{
|
||||||
|
super(RoomWidgetUpdateDecorateModeEvent.UPDATE_DECORATE);
|
||||||
|
|
||||||
|
this._isDecorating = isDecorating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isDecorating(): boolean
|
||||||
|
{
|
||||||
|
return this._isDecorating;
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ export * from './RoomWidgetUpdateChatInputContentEvent';
|
|||||||
export * from './RoomWidgetUpdateCreditFurniEvent';
|
export * from './RoomWidgetUpdateCreditFurniEvent';
|
||||||
export * from './RoomWidgetUpdateCustomStackHeightEvent';
|
export * from './RoomWidgetUpdateCustomStackHeightEvent';
|
||||||
export * from './RoomWidgetUpdateDanceStatusEvent';
|
export * from './RoomWidgetUpdateDanceStatusEvent';
|
||||||
|
export * from './RoomWidgetUpdateDecorateModeEvent';
|
||||||
export * from './RoomWidgetUpdateDimmerEvent';
|
export * from './RoomWidgetUpdateDimmerEvent';
|
||||||
export * from './RoomWidgetUpdateDimmerStateEvent';
|
export * from './RoomWidgetUpdateDimmerStateEvent';
|
||||||
export * from './RoomWidgetUpdateEvent';
|
export * from './RoomWidgetUpdateEvent';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { RoomEnterEffect, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { RoomEnterEffect, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useMemo, useState } from 'react';
|
import { FC, useCallback, useMemo, useState } from 'react';
|
||||||
import { GetRoomSession, GetSessionDataManager, RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../../../api';
|
import { GetRoomSession, GetSessionDataManager, RoomWidgetObjectNameEvent, RoomWidgetRoomEngineUpdateEvent, RoomWidgetRoomObjectMessage, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../../../api';
|
||||||
import { CreateEventDispatcherHook } from '../../../../hooks/events/event-dispatcher.base';
|
import { CreateEventDispatcherHook } from '../../../../hooks/events/event-dispatcher.base';
|
||||||
import { useRoomContext } from '../../context/RoomContext';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { AvatarInfoWidgetAvatarView } from './views/avatar/AvatarInfoWidgetAvatarView';
|
import { AvatarInfoWidgetAvatarView } from './views/avatar/AvatarInfoWidgetAvatarView';
|
||||||
@ -264,6 +264,13 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
|
|||||||
|
|
||||||
// useUiEvent(FriendEnteredRoomEvent.ENTERED, onFriendEnteredRoomEvent);
|
// useUiEvent(FriendEnteredRoomEvent.ENTERED, onFriendEnteredRoomEvent);
|
||||||
|
|
||||||
|
const onRoomWidgetUpdateDecorateModeEvent = useCallback((event: RoomWidgetUpdateDecorateModeEvent) =>
|
||||||
|
{
|
||||||
|
setIsDecorating(event.isDecorating);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateEventDispatcherHook(RoomWidgetUpdateDecorateModeEvent.UPDATE_DECORATE, eventDispatcher, onRoomWidgetUpdateDecorateModeEvent);
|
||||||
|
|
||||||
const decorateView = useMemo(() =>
|
const decorateView = useMemo(() =>
|
||||||
{
|
{
|
||||||
GetRoomSession().isDecorating = isDecorating;
|
GetRoomSession().isDecorating = isDecorating;
|
||||||
@ -274,7 +281,7 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
|
|||||||
const userName = GetSessionDataManager().userName;
|
const userName = GetSessionDataManager().userName;
|
||||||
const roomIndex = GetRoomSession().ownRoomIndex;
|
const roomIndex = GetRoomSession().ownRoomIndex;
|
||||||
|
|
||||||
return <AvatarInfoWidgetDecorateView userId={ userId } userName={ userName } roomIndex={ roomIndex } setIsDecorating={ setIsDecorating } />;
|
return <AvatarInfoWidgetDecorateView userId={ userId } userName={ userName } roomIndex={ roomIndex } />;
|
||||||
}, [ isDecorating ]);
|
}, [ isDecorating ]);
|
||||||
|
|
||||||
const currentView = useMemo(() =>
|
const currentView = useMemo(() =>
|
||||||
@ -316,7 +323,7 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
|
|||||||
{
|
{
|
||||||
if(RoomEnterEffect.isRunning()) return null;
|
if(RoomEnterEffect.isRunning()) return null;
|
||||||
|
|
||||||
return <AvatarInfoWidgetOwnAvatarView userData={ event } isDancing={ isDancing } setIsDecorating={ setIsDecorating } close={ clearInfoStandEvent } />;
|
return <AvatarInfoWidgetOwnAvatarView userData={ event } isDancing={ isDancing } close={ clearInfoStandEvent } />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <AvatarInfoWidgetAvatarView userData={ event } close={ clearInfoStandEvent } />;
|
return <AvatarInfoWidgetAvatarView userData={ event } close={ clearInfoStandEvent } />;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC } from 'react';
|
import { FC, useCallback } from 'react';
|
||||||
import { LocalizeText } from '../../../../../../api';
|
import { LocalizeText, RoomWidgetUpdateDecorateModeEvent } from '../../../../../../api';
|
||||||
|
import { useRoomContext } from '../../../../context/RoomContext';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
||||||
import { ContextMenuListView } from '../../../context-menu/views/list/ContextMenuListView';
|
import { ContextMenuListView } from '../../../context-menu/views/list/ContextMenuListView';
|
||||||
@ -8,12 +9,18 @@ import { AvatarInfoWidgetDecorateViewProps } from './AvatarInfoWidgetDecorateVie
|
|||||||
|
|
||||||
export const AvatarInfoWidgetDecorateView: FC<AvatarInfoWidgetDecorateViewProps> = props =>
|
export const AvatarInfoWidgetDecorateView: FC<AvatarInfoWidgetDecorateViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { userId = -1, userName = '', roomIndex = -1, setIsDecorating = null } = props;
|
const { userId = -1, userName = '', roomIndex = -1 } = props;
|
||||||
|
const { eventDispatcher = null } = useRoomContext();
|
||||||
|
|
||||||
|
const stopDecorating = useCallback(() =>
|
||||||
|
{
|
||||||
|
eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(false));
|
||||||
|
}, [ eventDispatcher ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ roomIndex } category={ RoomObjectCategory.UNIT } close={ null }>
|
<ContextMenuView objectId={ roomIndex } category={ RoomObjectCategory.UNIT } close={ null }>
|
||||||
<ContextMenuListView>
|
<ContextMenuListView>
|
||||||
<ContextMenuListItemView onClick={ event => setIsDecorating(false) }>
|
<ContextMenuListItemView onClick={ stopDecorating }>
|
||||||
{ LocalizeText('widget.avatar.stop_decorating') }
|
{ LocalizeText('widget.avatar.stop_decorating') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</ContextMenuListView>
|
</ContextMenuListView>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { Dispatch, SetStateAction } from 'react';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetDecorateViewProps
|
export interface AvatarInfoWidgetDecorateViewProps
|
||||||
{
|
{
|
||||||
userId: number;
|
userId: number;
|
||||||
userName: string;
|
userName: string;
|
||||||
roomIndex: number;
|
roomIndex: number;
|
||||||
setIsDecorating: Dispatch<SetStateAction<boolean>>;
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { AvatarAction, AvatarExpressionEnum, RoomObjectCategory, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { AvatarAction, AvatarExpressionEnum, RoomObjectCategory, UserProfileComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUserActionMessage } from '../../../../../../api';
|
||||||
import { AvatarEditorEvent } from '../../../../../../events';
|
import { AvatarEditorEvent } from '../../../../../../events';
|
||||||
import { dispatchUiEvent, SendMessageHook } from '../../../../../../hooks';
|
import { dispatchUiEvent, SendMessageHook } from '../../../../../../hooks';
|
||||||
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
|
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
|
||||||
@ -18,9 +18,9 @@ const MODE_SIGNS = 4;
|
|||||||
|
|
||||||
export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProps> = props =>
|
export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { userData = null, isDancing = false, setIsDecorating = null, close = null } = props;
|
const { userData = null, isDancing = false, close = null } = props;
|
||||||
const [ mode, setMode ] = useState((isDancing && HasHabboClub()) ? MODE_CLUB_DANCES : MODE_NORMAL);
|
const [ mode, setMode ] = useState((isDancing && HasHabboClub()) ? MODE_CLUB_DANCES : MODE_NORMAL);
|
||||||
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
const processAction = useCallback((name: string) =>
|
const processAction = useCallback((name: string) =>
|
||||||
{
|
{
|
||||||
@ -40,7 +40,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
switch(name)
|
switch(name)
|
||||||
{
|
{
|
||||||
case 'decorate':
|
case 'decorate':
|
||||||
setIsDecorating(true);
|
eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(true));
|
||||||
break;
|
break;
|
||||||
case 'change_looks':
|
case 'change_looks':
|
||||||
dispatchUiEvent(new AvatarEditorEvent(AvatarEditorEvent.SHOW_EDITOR));
|
dispatchUiEvent(new AvatarEditorEvent(AvatarEditorEvent.SHOW_EDITOR));
|
||||||
@ -101,7 +101,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(hideMenu) close();
|
if(hideMenu) close();
|
||||||
}, [ roomSession, widgetHandler, userData, setIsDecorating, close ]);
|
}, [ roomSession, eventDispatcher, widgetHandler, userData, close ]);
|
||||||
|
|
||||||
const openProfile = useCallback(() =>
|
const openProfile = useCallback(() =>
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { Dispatch, SetStateAction } from 'react';
|
|
||||||
import { RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api';
|
import { RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api';
|
||||||
|
|
||||||
export interface AvatarInfoWidgetOwnAvatarViewProps
|
export interface AvatarInfoWidgetOwnAvatarViewProps
|
||||||
{
|
{
|
||||||
userData: RoomWidgetUpdateInfostandUserEvent;
|
userData: RoomWidgetUpdateInfostandUserEvent;
|
||||||
isDancing: boolean;
|
isDancing: boolean;
|
||||||
setIsDecorating: Dispatch<SetStateAction<boolean>>;
|
|
||||||
close: () => void;
|
close: () => void;
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,17 @@
|
|||||||
import { RoomObjectOperationType } from '@nitrots/nitro-renderer';
|
import { RoomObjectOperationType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { ProcessRoomObjectOperation, RoomWidgetRoomObjectUpdateEvent } from '../../../../../api';
|
import { ProcessRoomObjectOperation, RoomWidgetRoomObjectUpdateEvent, RoomWidgetUpdateDecorateModeEvent } from '../../../../../api';
|
||||||
|
import { BatchUpdates } from '../../../../../hooks';
|
||||||
import { CreateEventDispatcherHook } from '../../../../../hooks/events/event-dispatcher.base';
|
import { CreateEventDispatcherHook } from '../../../../../hooks/events/event-dispatcher.base';
|
||||||
import { useRoomContext } from '../../../context/RoomContext';
|
import { useRoomContext } from '../../../context/RoomContext';
|
||||||
import { ObjectLocationView } from '../../object-location/ObjectLocationView';
|
import { ObjectLocationView } from '../../object-location/ObjectLocationView';
|
||||||
|
|
||||||
export const FurnitureManipulationMenuView: FC<{}> = props =>
|
export const FurnitureManipulationMenuView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const [ objectId, setObjectId ] = useState(-1);
|
const [ objectId, setObjectId ] = useState(-1);
|
||||||
const [ objectType, setObjectType ] = useState(-1);
|
const [ objectType, setObjectType ] = useState(-1);
|
||||||
|
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
||||||
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION: {
|
|
||||||
setIsVisible(true);
|
|
||||||
setObjectId(event.id);
|
|
||||||
setObjectType(event.category);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED: {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED: {
|
|
||||||
setIsVisible(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const rotateFurniture = useCallback(() =>
|
const rotateFurniture = useCallback(() =>
|
||||||
{
|
{
|
||||||
@ -42,22 +23,87 @@ export const FurnitureManipulationMenuView: FC<{}> = props =>
|
|||||||
ProcessRoomObjectOperation(objectId, objectType, RoomObjectOperationType.OBJECT_MOVE);
|
ProcessRoomObjectOperation(objectId, objectType, RoomObjectOperationType.OBJECT_MOVE);
|
||||||
}, [ objectId, objectType ]);
|
}, [ objectId, objectType ]);
|
||||||
|
|
||||||
useEffect(() =>
|
const pickupFurniture = useCallback(() =>
|
||||||
{
|
{
|
||||||
if(!isVisible) return;
|
ProcessRoomObjectOperation(objectId, objectType, RoomObjectOperationType.OBJECT_PICKUP);
|
||||||
|
}, [ objectId, objectType ]);
|
||||||
|
|
||||||
moveFurniture();
|
const onRoomWidgetRoomObjectUpdateEvent = useCallback((event: RoomWidgetRoomObjectUpdateEvent) =>
|
||||||
}, [ isVisible, moveFurniture ]);
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION: {
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(true);
|
||||||
|
setObjectId(event.id);
|
||||||
|
setObjectType(event.category);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RoomWidgetRoomObjectUpdateEvent.FURNI_REMOVED: {
|
||||||
|
if(event.id === objectId)
|
||||||
|
{
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(false);
|
||||||
|
setObjectId(-1);
|
||||||
|
setObjectType(-1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED: {
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(false);
|
||||||
|
setObjectId(-1);
|
||||||
|
setObjectType(-1);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [ objectId ]);
|
||||||
|
|
||||||
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_REQUEST_MANIPULATION, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
||||||
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
CreateEventDispatcherHook(RoomWidgetRoomObjectUpdateEvent.OBJECT_DESELECTED, eventDispatcher, onRoomWidgetRoomObjectUpdateEvent);
|
||||||
|
|
||||||
|
const onRoomWidgetUpdateDecorateModeEvent = useCallback((event: RoomWidgetUpdateDecorateModeEvent) =>
|
||||||
|
{
|
||||||
|
if(event.isDecorating) return;
|
||||||
|
|
||||||
|
moveFurniture();
|
||||||
|
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(false);
|
||||||
|
setObjectId(-1);
|
||||||
|
setObjectType(-1);
|
||||||
|
});
|
||||||
|
}, [ moveFurniture ]);
|
||||||
|
|
||||||
|
CreateEventDispatcherHook(RoomWidgetUpdateDecorateModeEvent.UPDATE_DECORATE, eventDispatcher, onRoomWidgetUpdateDecorateModeEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!isVisible)
|
||||||
|
{
|
||||||
|
eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(false));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(true));
|
||||||
|
|
||||||
|
moveFurniture();
|
||||||
|
}, [ eventDispatcher, isVisible, moveFurniture ]);
|
||||||
|
|
||||||
if(!isVisible) return null;
|
if(!isVisible) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ObjectLocationView objectId={ objectId } category={ objectType }>
|
<ObjectLocationView objectId={ objectId } category={ objectType }>
|
||||||
<div className="btn-group">
|
<div className="btn-group">
|
||||||
<button type="button" className="btn btn-primary btn-sm">
|
<button type="button" className="btn btn-primary btn-sm" onClick={ pickupFurniture }>
|
||||||
<i className="fas fa-times" />
|
<i className="fas fa-times" />
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="btn btn-primary btn-sm" onClick={ rotateFurniture }>
|
<button type="button" className="btn btn-primary btn-sm" onClick={ rotateFurniture }>
|
||||||
|
Loading…
Reference in New Issue
Block a user