mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 14:40:50 +01:00
Update avatar info widget
This commit is contained in:
parent
02556310b1
commit
c6512be476
@ -0,0 +1,71 @@
|
|||||||
|
import { BotSkillSaveComposer } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, useMemo, useState } from 'react';
|
||||||
|
import { GetRoomObjectBounds, GetRoomSession, LocalizeText, RoomWidgetUpdateRentableBotChatEvent } from '../../../../api';
|
||||||
|
import { Base, Button, Column, Flex, Text } from '../../../../common';
|
||||||
|
import { SendMessageHook } from '../../../../hooks';
|
||||||
|
import { DraggableWindow, DraggableWindowPosition } from '../../../../layout';
|
||||||
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
|
import { BotSkillsEnum } from './common/BotSkillsEnum';
|
||||||
|
|
||||||
|
interface AvatarInfoRentableBotChatViewProps
|
||||||
|
{
|
||||||
|
chatEvent: RoomWidgetUpdateRentableBotChatEvent;
|
||||||
|
close(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AvatarInfoRentableBotChatView: FC<AvatarInfoRentableBotChatViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { chatEvent = null, close = null } = props;
|
||||||
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
|
const [ newText, setNewText ] = useState<string>(chatEvent.chat === '${bot.skill.chatter.configuration.text.placeholder}' ? '' : chatEvent.chat);
|
||||||
|
const [ automaticChat, setAutomaticChat ] = useState<boolean>(chatEvent.automaticChat);
|
||||||
|
const [ mixSentences, setMixSentences ] = useState<boolean>(chatEvent.mixSentences);
|
||||||
|
const [ chatDelay, setChatDelay ] = useState<number>(chatEvent.chatDelay);
|
||||||
|
|
||||||
|
const getObjectLocation = useMemo(() => GetRoomObjectBounds(GetRoomSession().roomId, chatEvent.objectId, chatEvent.category, 1), [ chatEvent ]);
|
||||||
|
|
||||||
|
const formatChatString = (value: string) => value.replace(/;#;/g, ' ').replace(/\r\n|\r|\n/g, '\r');
|
||||||
|
|
||||||
|
const save = () =>
|
||||||
|
{
|
||||||
|
const chatConfiguration = formatChatString(newText) + ';#;' + automaticChat + ';#;' + chatDelay + ';#;' + mixSentences;
|
||||||
|
|
||||||
|
SendMessageHook(new BotSkillSaveComposer(chatEvent.botId, BotSkillsEnum.SETUP_CHAT, chatConfiguration));
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DraggableWindow position={ DraggableWindowPosition.NOTHING } handleSelector=".drag-handler" style={ { top: getObjectLocation.y, left: getObjectLocation.x } }>
|
||||||
|
<Base className="nitro-context-menu bot-chat">
|
||||||
|
<ContextMenuHeaderView className="drag-handler">
|
||||||
|
{ LocalizeText('bot.skill.chatter.configuration.title') }
|
||||||
|
</ContextMenuHeaderView>
|
||||||
|
<Column className="p-1">
|
||||||
|
<Column gap={ 1 }>
|
||||||
|
<Text variant="white">{ LocalizeText('bot.skill.chatter.configuration.chat.text') }</Text>
|
||||||
|
<textarea className="form-control form-control-sm" placeholder={LocalizeText('bot.skill.chatter.configuration.text.placeholder')} value={newText} rows={7} onChange={e => setNewText(e.target.value)} />
|
||||||
|
</Column>
|
||||||
|
<Column gap={ 1 }>
|
||||||
|
<Flex gap={ 1 } alignItems="center" justifyContent="between">
|
||||||
|
<Text fullWidth variant="white">{ LocalizeText('bot.skill.chatter.configuration.automatic.chat') }</Text>
|
||||||
|
<input type="checkbox" className="form-check-input" checked={ automaticChat } onChange={ event => setAutomaticChat(event.target.checked) } />
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={ 1 } alignItems="center" justifyContent="between">
|
||||||
|
<Text fullWidth variant="white">{ LocalizeText('bot.skill.chatter.configuration.markov') }</Text>
|
||||||
|
<input type="checkbox" className="form-check-input" checked={ mixSentences } onChange={ event => setMixSentences(event.target.checked) } />
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={ 1 } alignItems="center" justifyContent="between">
|
||||||
|
<Text fullWidth variant="white">{ LocalizeText('bot.skill.chatter.configuration.chat.delay') }</Text>
|
||||||
|
<input type="number" className="form-control form-control-sm" value={ chatDelay } onChange={ event => setChatDelay(event.target.valueAsNumber) }/>
|
||||||
|
</Flex>
|
||||||
|
</Column>
|
||||||
|
<Flex alignItems="center" justifyContent="between" gap={ 1 }>
|
||||||
|
<Button fullWidth variant="primary" onClick={ close }>{ LocalizeText('cancel') }</Button>
|
||||||
|
<Button fullWidth variant="success" onClick={ save }>{ LocalizeText('save') }</Button>
|
||||||
|
</Flex>
|
||||||
|
</Column>
|
||||||
|
</Base>
|
||||||
|
</DraggableWindow>
|
||||||
|
);
|
||||||
|
}
|
@ -1,11 +1,17 @@
|
|||||||
import { IFurnitureData, PetCustomPart, PetFigureData, RoomObjectCategory, RoomObjectVariable, RoomUserData } from '@nitrots/nitro-renderer';
|
import { IFurnitureData, PetCustomPart, PetFigureData, RoomObjectCategory, RoomObjectVariable, RoomUserData } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetFurnitureDataForRoomObject, GetRoomEngine, LocalizeText, RoomWidgetUseProductMessage } from '../../../../../../api';
|
import { GetFurnitureDataForRoomObject, GetRoomEngine, LocalizeText, RoomWidgetUseProductMessage, UseProductItem } from '../../../../api';
|
||||||
import { FurniCategory } from '../../../../../../components/inventory/common/FurniCategory';
|
import { Base, Button, Column, Flex, Text } from '../../../../common';
|
||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../../layout';
|
import { FurniCategory } from '../../../../components/inventory/common/FurniCategory';
|
||||||
import { PetImageView } from '../../../../../shared/pet-image/PetImageView';
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { PetImageView } from '../../../shared/pet-image/PetImageView';
|
||||||
import { AvatarInfoUseProductConfirmViewProps } from './AvatarInfoUseProductConfirmView.types';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
|
|
||||||
|
interface AvatarInfoUseProductConfirmViewProps
|
||||||
|
{
|
||||||
|
item: UseProductItem;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const _Str_5091: number = -1;
|
const _Str_5091: number = -1;
|
||||||
const _Str_11906: number = 0;
|
const _Str_11906: number = 0;
|
||||||
@ -221,57 +227,57 @@ export const AvatarInfoUseProductConfirmView: FC<AvatarInfoUseProductConfirmView
|
|||||||
return (
|
return (
|
||||||
<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 center>
|
||||||
<div className="row">
|
<Flex gap={ 2 } overflow="hidden">
|
||||||
<div className="w-unset">
|
<Column>
|
||||||
<div className="product-preview cursor-pointer" onClick={ selectRoomObject }>
|
<Base pointer className="product-preview" onClick={ selectRoomObject }>
|
||||||
{ getPetImage }
|
{ getPetImage }
|
||||||
</div>
|
</Base>
|
||||||
</div>
|
</Column>
|
||||||
<div className="col d-flex flex-column justify-content-between">
|
<Column justifyContent="between" overflow="auto">
|
||||||
<div className="d-flex flex-column">
|
<Column gap={ 2 }>
|
||||||
{ (mode === _Str_11906) &&
|
{ (mode === _Str_11906) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.shampoo', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.shampoo', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.shampoo') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.shampoo') }</Text>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === _Str_11214) &&
|
{ (mode === _Str_11214) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.custompart', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.custompart', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.custompart') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.custompart') }</Text>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === _Str_11733) &&
|
{ (mode === _Str_11733) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.custompartshampoo', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.custompartshampoo', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.custompartshampoo') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.custompartshampoo') }</Text>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === _Str_11369) &&
|
{ (mode === _Str_11369) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.saddle', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.saddle', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.saddle') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.saddle') }</Text>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === _Str_8759) &&
|
{ (mode === _Str_8759) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.revive_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.revive_monsterplant', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.revive_monsterplant') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.revive_monsterplant') }</Text>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === _Str_8432) &&
|
{ (mode === _Str_8432) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.rebreed_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.rebreed_monsterplant', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.rebreed_monsterplant') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.rebreed_monsterplant') }</Text>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === _Str_9653) &&
|
{ (mode === _Str_9653) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black mb-2">{ LocalizeText('useproduct.widget.text.fertilize_monsterplant', [ 'productName' ], [ furniData.name ] ) }</div>
|
<Text>{ LocalizeText('useproduct.widget.text.fertilize_monsterplant', [ 'productName' ], [ furniData.name ] ) }</Text>
|
||||||
<div className="text-black">{ LocalizeText('useproduct.widget.info.fertilize_monsterplant') }</div>
|
<Text>{ LocalizeText('useproduct.widget.info.fertilize_monsterplant') }</Text>
|
||||||
</> }
|
</> }
|
||||||
</div>
|
</Column>
|
||||||
<div className="d-flex justify-content-between align-items-end w-100 h-100">
|
<Flex alignItems="center" justifyContent="between">
|
||||||
<button type="button" className="btn btn-danger" onClick={ close }>{ LocalizeText('useproduct.widget.cancel') }</button>
|
<Button variant="danger" onClick={ close }>{ LocalizeText('useproduct.widget.cancel') }</Button>
|
||||||
<button type="button" className="btn btn-primary" onClick={ useProduct }>{ LocalizeText('useproduct.widget.use') }</button>
|
<Button variant="success" onClick={ useProduct }>{ LocalizeText('useproduct.widget.use') }</Button>
|
||||||
</div>
|
</Flex>
|
||||||
</div>
|
</Column>
|
||||||
</div>
|
</Flex>
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
</NitroCardView>
|
</NitroCardView>
|
||||||
)
|
)
|
@ -1,12 +1,18 @@
|
|||||||
import { RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
import { RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { GetFurnitureDataForRoomObject, LocalizeText } from '../../../../../../api';
|
import { GetFurnitureDataForRoomObject, LocalizeText, UseProductItem } from '../../../../api';
|
||||||
import { FurniCategory } from '../../../../../../components/inventory/common/FurniCategory';
|
import { FurniCategory } from '../../../../components/inventory/common/FurniCategory';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
import { AvatarInfoUseProductViewProps } from './AvatarInfoUseProductView.types';
|
|
||||||
|
interface AvatarInfoUseProductViewProps
|
||||||
|
{
|
||||||
|
item: UseProductItem;
|
||||||
|
updateConfirmingProduct: (product: UseProductItem) => void;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const PRODUCT_PAGE_UKNOWN: number = 0;
|
const PRODUCT_PAGE_UKNOWN: number = 0;
|
||||||
const PRODUCT_PAGE_SHAMPOO: number = 1;
|
const PRODUCT_PAGE_SHAMPOO: number = 1;
|
@ -1,11 +1,18 @@
|
|||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { RoomControllerLevel, RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
import { RoomControllerLevel, RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetOwnRoomObject, GetUserProfile, LocalizeText, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetOwnRoomObject, GetUserProfile, LocalizeText, RoomWidgetMessage, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUserActionMessage } from '../../../../api';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { BatchUpdates } from '../../../../hooks';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { AvatarInfoWidgetAvatarViewProps } from './AvatarInfoWidgetAvatarView.types';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
|
|
||||||
|
interface AvatarInfoWidgetAvatarViewProps
|
||||||
|
{
|
||||||
|
userData: RoomWidgetUpdateInfostandUserEvent;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const MODE_NORMAL = 0;
|
const MODE_NORMAL = 0;
|
||||||
const MODE_MODERATE = 1;
|
const MODE_MODERATE = 1;
|
||||||
@ -21,12 +28,6 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
const [ respectsLeft, setRespectsLeft ] = useState(0);
|
const [ respectsLeft, setRespectsLeft ] = useState(0);
|
||||||
const { widgetHandler = null } = useRoomContext();
|
const { widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
setMode(MODE_NORMAL);
|
|
||||||
setRespectsLeft(userData.respectLeft);
|
|
||||||
}, [ userData ])
|
|
||||||
|
|
||||||
const isShowGiveRights = useMemo(() =>
|
const isShowGiveRights = useMemo(() =>
|
||||||
{
|
{
|
||||||
return (userData.amIOwner && (userData.targetRoomControllerLevel < RoomControllerLevel.GUEST) && !userData.isGuildRoom);
|
return (userData.amIOwner && (userData.targetRoomControllerLevel < RoomControllerLevel.GUEST) && !userData.isGuildRoom);
|
||||||
@ -42,7 +43,23 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
return (userData.canBeKicked || userData.canBeBanned || userData.canBeMuted || isShowGiveRights || isShowRemoveRights);
|
return (userData.canBeKicked || userData.canBeBanned || userData.canBeMuted || isShowGiveRights || isShowRemoveRights);
|
||||||
}, [ isShowGiveRights, isShowRemoveRights, userData ]);
|
}, [ isShowGiveRights, isShowRemoveRights, userData ]);
|
||||||
|
|
||||||
const processAction = useCallback((name: string) =>
|
const canGiveHandItem = useMemo(() =>
|
||||||
|
{
|
||||||
|
let flag = false;
|
||||||
|
|
||||||
|
const roomObject = GetOwnRoomObject();
|
||||||
|
|
||||||
|
if(roomObject)
|
||||||
|
{
|
||||||
|
const carryId = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT);
|
||||||
|
|
||||||
|
if((carryId > 0) && (carryId < 999999)) flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const processAction = (name: string) =>
|
||||||
{
|
{
|
||||||
let messageType: string = null;
|
let messageType: string = null;
|
||||||
let message: RoomWidgetMessage = null;
|
let message: RoomWidgetMessage = null;
|
||||||
@ -173,23 +190,16 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(hideMenu) close();
|
if(hideMenu) close();
|
||||||
}, [ widgetHandler, userData, close ]);
|
}
|
||||||
|
|
||||||
const canGiveHandItem = useMemo(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
let flag = false;
|
BatchUpdates(() =>
|
||||||
|
|
||||||
const roomObject = GetOwnRoomObject();
|
|
||||||
|
|
||||||
if(roomObject)
|
|
||||||
{
|
{
|
||||||
const carryId = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT);
|
setMode(MODE_NORMAL);
|
||||||
|
setRespectsLeft(userData.respectLeft);
|
||||||
if((carryId > 0) && (carryId < 999999)) flag = true;
|
});
|
||||||
}
|
}, [ userData ]);
|
||||||
|
|
||||||
return flag;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
||||||
@ -225,12 +235,12 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
{ moderateMenuHasContent &&
|
{ moderateMenuHasContent &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('moderate') }>
|
<ContextMenuListItemView onClick={ event => processAction('moderate') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('infostand.link.moderate') }
|
{ LocalizeText('infostand.link.moderate') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ userData.isAmbassador &&
|
{ userData.isAmbassador &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('ambassador') }>
|
<ContextMenuListItemView onClick={ event => processAction('ambassador') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('infostand.link.ambassador') }
|
{ LocalizeText('infostand.link.ambassador') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ canGiveHandItem && <ContextMenuListItemView onClick={ event => processAction('pass_hand_item') }>
|
{ canGiveHandItem && <ContextMenuListItemView onClick={ event => processAction('pass_hand_item') }>
|
||||||
@ -243,11 +253,11 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
{ LocalizeText('infostand.button.kick') }
|
{ LocalizeText('infostand.button.kick') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('mute') }>
|
<ContextMenuListItemView onClick={ event => processAction('mute') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('infostand.button.mute') }
|
{ LocalizeText('infostand.button.mute') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('ban') }>
|
<ContextMenuListItemView onClick={ event => processAction('ban') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('infostand.button.ban') }
|
{ LocalizeText('infostand.button.ban') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
{ isShowGiveRights &&
|
{ isShowGiveRights &&
|
||||||
@ -259,7 +269,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
{ LocalizeText('infostand.button.removerights') }
|
{ LocalizeText('infostand.button.removerights') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
@ -275,7 +285,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
{ LocalizeText('infostand.button.perm_ban') }
|
{ LocalizeText('infostand.button.perm_ban') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back_moderate') }>
|
<ContextMenuListItemView onClick={ event => processAction('back_moderate') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
@ -291,7 +301,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
{ LocalizeText('infostand.button.mute_10min') }
|
{ LocalizeText('infostand.button.mute_10min') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back_moderate') }>
|
<ContextMenuListItemView onClick={ event => processAction('back_moderate') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
@ -304,11 +314,11 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
{ LocalizeText('infostand.button.kick') }
|
{ LocalizeText('infostand.button.kick') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('ambassador_mute') }>
|
<ContextMenuListItemView onClick={ event => processAction('ambassador_mute') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
|
||||||
{ LocalizeText('infostand.button.mute') }
|
{ LocalizeText('infostand.button.mute') }
|
||||||
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
@ -327,7 +337,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
{ LocalizeText('infostand.button.mute_18hour') }
|
{ LocalizeText('infostand.button.mute_18hour') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back_ambassador') }>
|
<ContextMenuListItemView onClick={ event => processAction('back_ambassador') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
@ -1,21 +1,24 @@
|
|||||||
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback } from 'react';
|
import { FC } from 'react';
|
||||||
import { LocalizeText, RoomWidgetUpdateDecorateModeEvent } from '../../../../../../api';
|
import { LocalizeText, RoomWidgetUpdateDecorateModeEvent } from '../../../../api';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListView } from '../context-menu/ContextMenuListView';
|
||||||
import { ContextMenuListView } from '../../../context-menu/views/list/ContextMenuListView';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
import { AvatarInfoWidgetDecorateViewProps } from './AvatarInfoWidgetDecorateView.types';
|
|
||||||
|
interface AvatarInfoWidgetDecorateViewProps
|
||||||
|
{
|
||||||
|
userId: number;
|
||||||
|
userName: string;
|
||||||
|
roomIndex: number;
|
||||||
|
}
|
||||||
|
|
||||||
export const AvatarInfoWidgetDecorateView: FC<AvatarInfoWidgetDecorateViewProps> = props =>
|
export const AvatarInfoWidgetDecorateView: FC<AvatarInfoWidgetDecorateViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { userId = -1, userName = '', roomIndex = -1 } = props;
|
const { userId = -1, userName = '', roomIndex = -1 } = props;
|
||||||
const { eventDispatcher = null } = useRoomContext();
|
const { eventDispatcher = null } = useRoomContext();
|
||||||
|
|
||||||
const stopDecorating = useCallback(() =>
|
const stopDecorating = () => eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(false));
|
||||||
{
|
|
||||||
eventDispatcher.dispatchEvent(new RoomWidgetUpdateDecorateModeEvent(false));
|
|
||||||
}, [ eventDispatcher ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ roomIndex } category={ RoomObjectCategory.UNIT } close={ null }>
|
<ContextMenuView objectId={ roomIndex } category={ RoomObjectCategory.UNIT } close={ null }>
|
@ -1,16 +1,18 @@
|
|||||||
import { FC, useMemo } from 'react';
|
import { FC, useMemo } from 'react';
|
||||||
import { GetSessionDataManager } from '../../../../../../api';
|
import { GetSessionDataManager, RoomWidgetObjectNameEvent } from '../../../../api';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
import { AvatarInfoWidgetNameViewProps } from './AvatarInfoWidgetNameView.types';
|
|
||||||
|
interface AvatarInfoWidgetNameViewProps
|
||||||
|
{
|
||||||
|
nameData: RoomWidgetObjectNameEvent;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export const AvatarInfoWidgetNameView: FC<AvatarInfoWidgetNameViewProps> = props =>
|
export const AvatarInfoWidgetNameView: FC<AvatarInfoWidgetNameViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { nameData = null, close = null } = props;
|
const { nameData = null, close = null } = props;
|
||||||
|
|
||||||
const fades = useMemo(() =>
|
const fades = useMemo(() => (nameData.id !== GetSessionDataManager().userId), [ nameData ]);
|
||||||
{
|
|
||||||
return (nameData.id !== GetSessionDataManager().userId);
|
|
||||||
}, [ nameData ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ nameData.roomIndex } category={ nameData.category } userType={ nameData.userType } fades={ fades } className="name-only" close= { close }>
|
<ContextMenuView objectId={ nameData.roomIndex } category={ nameData.category } userType={ nameData.userType } fades={ fades } className="name-only" close= { close }>
|
@ -1,15 +1,23 @@
|
|||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { AvatarAction, AvatarExpressionEnum, RoomControllerLevel, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { AvatarAction, AvatarExpressionEnum, RoomControllerLevel, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useMemo, useState } from 'react';
|
import { FC, useCallback, useMemo, useState } from 'react';
|
||||||
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, GetUserProfile, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, GetUserProfile, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUserActionMessage } from '../../../../api';
|
||||||
import { AvatarEditorEvent } from '../../../../../../events';
|
import { Flex } from '../../../../common';
|
||||||
import { HelpNameChangeEvent } from '../../../../../../events/help/HelpNameChangeEvent';
|
import { AvatarEditorEvent } from '../../../../events';
|
||||||
import { dispatchUiEvent } from '../../../../../../hooks';
|
import { HelpNameChangeEvent } from '../../../../events/help/HelpNameChangeEvent';
|
||||||
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
|
import { dispatchUiEvent } from '../../../../hooks';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { AvatarInfoWidgetOwnAvatarViewProps } from './AvatarInfoWidgetOwnAvatarView.types';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
|
|
||||||
|
interface AvatarInfoWidgetOwnAvatarViewProps
|
||||||
|
{
|
||||||
|
userData: RoomWidgetUpdateInfostandUserEvent;
|
||||||
|
isDancing: boolean;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const MODE_NORMAL = 0;
|
const MODE_NORMAL = 0;
|
||||||
const MODE_CLUB_DANCES = 1;
|
const MODE_CLUB_DANCES = 1;
|
||||||
@ -134,7 +142,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
{ (HasHabboClub() && !isRidingHorse) &&
|
{ (HasHabboClub() && !isRidingHorse) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('dance_menu') }>
|
<ContextMenuListItemView onClick={ event => processAction('dance_menu') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('widget.memenu.dance') }
|
{ LocalizeText('widget.memenu.dance') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ (!isDancing && !HasHabboClub() && !isRidingHorse) &&
|
{ (!isDancing && !HasHabboClub() && !isRidingHorse) &&
|
||||||
@ -146,11 +154,11 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
{ LocalizeText('widget.memenu.dance.stop') }
|
{ LocalizeText('widget.memenu.dance.stop') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
<ContextMenuListItemView onClick={ event => processAction('expressions') }>
|
<ContextMenuListItemView onClick={ event => processAction('expressions') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('infostand.link.expressions') }
|
{ LocalizeText('infostand.link.expressions') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('signs') }>
|
<ContextMenuListItemView onClick={ event => processAction('signs') }>
|
||||||
<i className="fas fa-chevron-right right" />
|
<FontAwesomeIcon icon="chevron-right" className="right" />
|
||||||
{ LocalizeText('infostand.show.signs') }
|
{ LocalizeText('infostand.show.signs') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
{ (userData.carryItem > 0) &&
|
{ (userData.carryItem > 0) &&
|
||||||
@ -177,7 +185,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
{ LocalizeText('widget.memenu.dance4') }
|
{ LocalizeText('widget.memenu.dance4') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
@ -196,12 +204,12 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
{ LocalizeText('widget.memenu.wave') }
|
{ LocalizeText('widget.memenu.wave') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ GetCanUseExpression() &&
|
{ GetCanUseExpression() &&
|
||||||
<ContextMenuListItemView canSelect={ HasHabboVip() } onClick={ event => processAction('laugh') }>
|
<ContextMenuListItemView disabled={ !HasHabboVip() } onClick={ event => processAction('laugh') }>
|
||||||
<CurrencyIcon type="hc" />
|
<CurrencyIcon type="hc" />
|
||||||
{ LocalizeText('widget.memenu.laugh') }
|
{ LocalizeText('widget.memenu.laugh') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ GetCanUseExpression() &&
|
{ GetCanUseExpression() &&
|
||||||
<ContextMenuListItemView canSelect={ HasHabboVip() } onClick={ event => processAction('blow') }>
|
<ContextMenuListItemView disabled={ !HasHabboVip() } onClick={ event => processAction('blow') }>
|
||||||
<CurrencyIcon type="hc" />
|
<CurrencyIcon type="hc" />
|
||||||
{ LocalizeText('widget.memenu.blow') }
|
{ LocalizeText('widget.memenu.blow') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
@ -209,13 +217,13 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
{ LocalizeText('widget.memenu.idle') }
|
{ LocalizeText('widget.memenu.idle') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
{ (mode === MODE_SIGNS) &&
|
{ (mode === MODE_SIGNS) &&
|
||||||
<>
|
<>
|
||||||
<div className="d-flex menu-list-split-3">
|
<Flex className="menu-list-split-3">
|
||||||
<ContextMenuListItemView onClick={ event => processAction('sign_1') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_1') }>
|
||||||
1
|
1
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
@ -225,8 +233,8 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('sign_3') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_3') }>
|
||||||
3
|
3
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</div>
|
</Flex>
|
||||||
<div className="d-flex menu-list-split-3">
|
<Flex className="menu-list-split-3">
|
||||||
<ContextMenuListItemView onClick={ event => processAction('sign_4') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_4') }>
|
||||||
4
|
4
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
@ -236,8 +244,8 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('sign_6') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_6') }>
|
||||||
6
|
6
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</div>
|
</Flex>
|
||||||
<div className="d-flex menu-list-split-3">
|
<Flex className="menu-list-split-3">
|
||||||
<ContextMenuListItemView onClick={ event => processAction('sign_7') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_7') }>
|
||||||
7
|
7
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
@ -247,8 +255,8 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('sign_9') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_9') }>
|
||||||
9
|
9
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</div>
|
</Flex>
|
||||||
<div className="d-flex menu-list-split-3">
|
<Flex className="menu-list-split-3">
|
||||||
<ContextMenuListItemView onClick={ event => processAction('sign_10') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_10') }>
|
||||||
10
|
10
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
@ -258,8 +266,8 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('sign_15') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_15') }>
|
||||||
<i className="icon icon-sign-smile" />
|
<i className="icon icon-sign-smile" />
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</div>
|
</Flex>
|
||||||
<div className="d-flex menu-list-split-3">
|
<Flex className="menu-list-split-3">
|
||||||
<ContextMenuListItemView onClick={ event => processAction('sign_12') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_12') }>
|
||||||
<i className="icon icon-sign-skull" />
|
<i className="icon icon-sign-skull" />
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
@ -269,8 +277,8 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('sign_17') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_17') }>
|
||||||
<i className="icon icon-sign-yellow" />
|
<i className="icon icon-sign-yellow" />
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</div>
|
</Flex>
|
||||||
<div className="d-flex menu-list-split-3">
|
<Flex className="menu-list-split-3">
|
||||||
<ContextMenuListItemView onClick={ event => processAction('sign_16') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_16') }>
|
||||||
<i className="icon icon-sign-red" />
|
<i className="icon icon-sign-red" />
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
@ -280,9 +288,9 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('sign_11') }>
|
<ContextMenuListItemView onClick={ event => processAction('sign_11') }>
|
||||||
<i className="icon icon-sign-heart" />
|
<i className="icon icon-sign-heart" />
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</div>
|
</Flex>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
<ContextMenuListItemView onClick={ event => processAction('back') }>
|
||||||
<i className="fas fa-chevron-left left" />
|
<FontAwesomeIcon icon="chevron-left" className="left" />
|
||||||
{ LocalizeText('generic.back') }
|
{ LocalizeText('generic.back') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
@ -1,11 +1,17 @@
|
|||||||
import { PetType, RoomObjectCategory, RoomObjectType, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
import { PetType, RoomObjectCategory, RoomObjectType, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetOwnRoomObject, LocalizeText, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetOwnRoomObject, LocalizeText, RoomWidgetMessage, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUserActionMessage } from '../../../../api';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { BatchUpdates } from '../../../../hooks';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { AvatarInfoWidgetOwnPetViewProps } from './AvatarInfoWidgetOwnPetView.types';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
|
|
||||||
|
interface AvatarInfoWidgetOwnPetViewProps
|
||||||
|
{
|
||||||
|
petData: RoomWidgetUpdateInfostandPetEvent;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const _Str_2906: number = 0;
|
const _Str_2906: number = 0;
|
||||||
const _Str_5818: number = 1;
|
const _Str_5818: number = 1;
|
||||||
@ -19,21 +25,23 @@ export const AvatarInfoWidgetOwnPetView: FC<AvatarInfoWidgetOwnPetViewProps> = p
|
|||||||
const [ respectsLeft, setRespectsLeft ] = useState(0);
|
const [ respectsLeft, setRespectsLeft ] = useState(0);
|
||||||
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
useEffect(() =>
|
const canGiveHandItem = useMemo(() =>
|
||||||
{
|
{
|
||||||
setMode(prevValue =>
|
let flag = false;
|
||||||
{
|
|
||||||
if(petData.petType === PetType.MONSTERPLANT) return _Str_10946;
|
|
||||||
else if(petData.saddle && !petData.rider) return _Str_5818;
|
|
||||||
else if(petData.rider) return _Str_5938;
|
|
||||||
|
|
||||||
return _Str_2906;
|
const roomObject = GetOwnRoomObject();
|
||||||
});
|
|
||||||
|
|
||||||
setRespectsLeft(petData.respectsPetLeft);
|
if(roomObject)
|
||||||
}, [ petData ])
|
{
|
||||||
|
const carryId = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT);
|
||||||
|
|
||||||
const processAction = useCallback((name: string) =>
|
if((carryId > 0) && (carryId < 999999)) flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const processAction = (name: string) =>
|
||||||
{
|
{
|
||||||
let messageType: string = null;
|
let messageType: string = null;
|
||||||
let message: RoomWidgetMessage = null;
|
let message: RoomWidgetMessage = null;
|
||||||
@ -118,23 +126,24 @@ export const AvatarInfoWidgetOwnPetView: FC<AvatarInfoWidgetOwnPetViewProps> = p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(hideMenu) close();
|
if(hideMenu) close();
|
||||||
}, [ widgetHandler, petData, mode, close ]);
|
}
|
||||||
|
|
||||||
const canGiveHandItem = useMemo(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
let flag = false;
|
BatchUpdates(() =>
|
||||||
|
|
||||||
const roomObject = GetOwnRoomObject();
|
|
||||||
|
|
||||||
if(roomObject)
|
|
||||||
{
|
{
|
||||||
const carryId = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT);
|
setMode(prevValue =>
|
||||||
|
{
|
||||||
|
if(petData.petType === PetType.MONSTERPLANT) return _Str_10946;
|
||||||
|
else if(petData.saddle && !petData.rider) return _Str_5818;
|
||||||
|
else if(petData.rider) return _Str_5938;
|
||||||
|
|
||||||
if((carryId > 0) && (carryId < 999999)) flag = true;
|
return _Str_2906;
|
||||||
}
|
});
|
||||||
|
|
||||||
return flag;
|
setRespectsLeft(petData.respectsPetLeft);
|
||||||
}, []);
|
});
|
||||||
|
}, [ petData ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
||||||
@ -167,8 +176,8 @@ export const AvatarInfoWidgetOwnPetView: FC<AvatarInfoWidgetOwnPetViewProps> = p
|
|||||||
<ContextMenuListItemView onClick={ event => processAction('mount') }>
|
<ContextMenuListItemView onClick={ event => processAction('mount') }>
|
||||||
{ LocalizeText('infostand.button.mount') }
|
{ LocalizeText('infostand.button.mount') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('toggle_riding_permission') }>
|
<ContextMenuListItemView onClick={ event => processAction('toggle_riding_permission') } gap={ 1 }>
|
||||||
<input type="checkbox" className="me-1" checked={ !!petData.publiclyRideable } readOnly={ true } />
|
<input type="checkbox" checked={ !!petData.publiclyRideable } readOnly={ true } />
|
||||||
{ LocalizeText('infostand.button.toggle_riding_permission') }
|
{ LocalizeText('infostand.button.toggle_riding_permission') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
{ (respectsLeft > 0) &&
|
{ (respectsLeft > 0) &&
|
||||||
@ -214,8 +223,8 @@ export const AvatarInfoWidgetOwnPetView: FC<AvatarInfoWidgetOwnPetViewProps> = p
|
|||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ !petData.dead && (petData.level === petData.maximumLevel) && petData.breedable &&
|
{ !petData.dead && (petData.level === petData.maximumLevel) && petData.breedable &&
|
||||||
<>
|
<>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('toggle_breeding_permission') }>
|
<ContextMenuListItemView onClick={ event => processAction('toggle_breeding_permission') } gap={ 1 }>
|
||||||
<input type="checkbox" className="me-1" checked={ petData.publiclyBreedable } readOnly={ true } />
|
<input type="checkbox" checked={ petData.publiclyBreedable } readOnly={ true } />
|
||||||
{ LocalizeText('infostand.button.toggle_breeding_permission') }
|
{ LocalizeText('infostand.button.toggle_breeding_permission') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
<ContextMenuListItemView onClick={ event => processAction('breed') }>
|
<ContextMenuListItemView onClick={ event => processAction('breed') }>
|
@ -1,11 +1,17 @@
|
|||||||
import { PetType, RoomControllerLevel, RoomObjectCategory, RoomObjectType, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
import { PetType, RoomControllerLevel, RoomObjectCategory, RoomObjectType, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetOwnRoomObject, GetSessionDataManager, LocalizeText, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetOwnRoomObject, GetSessionDataManager, LocalizeText, RoomWidgetMessage, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUserActionMessage } from '../../../../api';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { BatchUpdates } from '../../../../hooks';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { AvatarInfoWidgetPetViewProps } from './AvatarInfoWidgetPetView.types';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
|
|
||||||
|
interface AvatarInfoWidgetPetViewProps
|
||||||
|
{
|
||||||
|
petData: RoomWidgetUpdateInfostandPetEvent;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const _Str_2906: number = 0;
|
const _Str_2906: number = 0;
|
||||||
const _Str_5818: number = 1;
|
const _Str_5818: number = 1;
|
||||||
@ -19,21 +25,28 @@ export const AvatarInfoWidgetPetView: FC<AvatarInfoWidgetPetViewProps> = props =
|
|||||||
const [ respectsLeft, setRespectsLeft ] = useState(0);
|
const [ respectsLeft, setRespectsLeft ] = useState(0);
|
||||||
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
useEffect(() =>
|
const canPickUp = useMemo(() =>
|
||||||
{
|
{
|
||||||
setMode(prevValue =>
|
return (roomSession.isRoomOwner || (roomSession.controllerLevel >= RoomControllerLevel.GUEST) || GetSessionDataManager().isModerator);
|
||||||
{
|
}, [ roomSession ]);
|
||||||
if(petData.petType === PetType.MONSTERPLANT) return _Str_13388;
|
|
||||||
else if(petData.saddle && !petData.rider) return _Str_5818;
|
|
||||||
else if(petData.rider) return _Str_5938;
|
|
||||||
|
|
||||||
return _Str_2906;
|
const canGiveHandItem = useMemo(() =>
|
||||||
});
|
{
|
||||||
|
let flag = false;
|
||||||
|
|
||||||
setRespectsLeft(petData.respectsPetLeft);
|
const roomObject = GetOwnRoomObject();
|
||||||
}, [ petData ])
|
|
||||||
|
|
||||||
const processAction = useCallback((name: string) =>
|
if(roomObject)
|
||||||
|
{
|
||||||
|
const carryId = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT);
|
||||||
|
|
||||||
|
if((carryId > 0) && (carryId < 999999)) flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const processAction = (name: string) =>
|
||||||
{
|
{
|
||||||
let messageType: string = null;
|
let messageType: string = null;
|
||||||
let message: RoomWidgetMessage = null;
|
let message: RoomWidgetMessage = null;
|
||||||
@ -80,28 +93,24 @@ export const AvatarInfoWidgetPetView: FC<AvatarInfoWidgetPetViewProps> = props =
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(hideMenu) close();
|
if(hideMenu) close();
|
||||||
}, [ widgetHandler, petData, close ]);
|
}
|
||||||
|
|
||||||
const canPickUp = useMemo(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
return (roomSession.isRoomOwner || (roomSession.controllerLevel >= RoomControllerLevel.GUEST) || GetSessionDataManager().isModerator);
|
BatchUpdates(() =>
|
||||||
}, [ roomSession ]);
|
|
||||||
|
|
||||||
const canGiveHandItem = useMemo(() =>
|
|
||||||
{
|
|
||||||
let flag = false;
|
|
||||||
|
|
||||||
const roomObject = GetOwnRoomObject();
|
|
||||||
|
|
||||||
if(roomObject)
|
|
||||||
{
|
{
|
||||||
const carryId = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT);
|
setMode(prevValue =>
|
||||||
|
{
|
||||||
|
if(petData.petType === PetType.MONSTERPLANT) return _Str_13388;
|
||||||
|
else if(petData.saddle && !petData.rider) return _Str_5818;
|
||||||
|
else if(petData.rider) return _Str_5938;
|
||||||
|
|
||||||
if((carryId > 0) && (carryId < 999999)) flag = true;
|
return _Str_2906;
|
||||||
}
|
});
|
||||||
|
|
||||||
return flag;
|
setRespectsLeft(petData.respectsPetLeft);
|
||||||
}, []);
|
});
|
||||||
|
}, [ petData ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
@ -1,13 +1,19 @@
|
|||||||
import { BotCommandConfigurationEvent, BotRemoveComposer, BotSkillSaveComposer, RequestBotCommandConfigurationComposer, RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
import { BotCommandConfigurationEvent, BotRemoveComposer, BotSkillSaveComposer, RequestBotCommandConfigurationComposer, RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { GetNitroInstance, LocalizeText, RoomWidgetUpdateRentableBotChatEvent } from '../../../../../../api';
|
import { GetNitroInstance, LocalizeText, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateRentableBotChatEvent } from '../../../../api';
|
||||||
import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks/messages';
|
import { Button, Column, Flex, Text } from '../../../../common';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../context-menu/ContextMenuHeaderView';
|
||||||
import { ContextMenuListItemView } from '../../../context-menu/views/list-item/ContextMenuListItemView';
|
import { ContextMenuListItemView } from '../context-menu/ContextMenuListItemView';
|
||||||
import { BotSkillsEnum } from '../../common/BotSkillsEnum';
|
import { ContextMenuView } from '../context-menu/ContextMenuView';
|
||||||
import { AvatarInfoWidgetRentableBotViewProps } from './AvatarInfoWidgetRentableBotView.types';
|
import { BotSkillsEnum } from './common/BotSkillsEnum';
|
||||||
|
|
||||||
|
interface AvatarInfoWidgetRentableBotViewProps
|
||||||
|
{
|
||||||
|
rentableBotData: RoomWidgetUpdateInfostandRentableBotEvent;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const MODE_NORMAL = 0;
|
const MODE_NORMAL = 0;
|
||||||
const MODE_CHANGE_NAME = 1;
|
const MODE_CHANGE_NAME = 1;
|
||||||
@ -21,17 +27,10 @@ export const AvatarInfoWidgetRentableBotView: FC<AvatarInfoWidgetRentableBotView
|
|||||||
const [ newMotto, setNewMotto ] = useState('');
|
const [ newMotto, setNewMotto ] = useState('');
|
||||||
const { eventDispatcher = null } = useRoomContext();
|
const { eventDispatcher = null } = useRoomContext();
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
setMode(MODE_NORMAL);
|
|
||||||
}, [ rentableBotData ]);
|
|
||||||
|
|
||||||
const onBotCommandConfigurationEvent = useCallback((event: BotCommandConfigurationEvent) =>
|
const onBotCommandConfigurationEvent = useCallback((event: BotCommandConfigurationEvent) =>
|
||||||
{
|
{
|
||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
if(!parser) return;
|
|
||||||
|
|
||||||
if(parser.botId !== rentableBotData.webID) return;
|
if(parser.botId !== rentableBotData.webID) return;
|
||||||
|
|
||||||
switch(parser.commandId)
|
switch(parser.commandId)
|
||||||
@ -69,12 +68,9 @@ export const AvatarInfoWidgetRentableBotView: FC<AvatarInfoWidgetRentableBotView
|
|||||||
|
|
||||||
CreateMessageHook(BotCommandConfigurationEvent, onBotCommandConfigurationEvent);
|
CreateMessageHook(BotCommandConfigurationEvent, onBotCommandConfigurationEvent);
|
||||||
|
|
||||||
const requestBotCommandConfiguration = useCallback((skillType: number) =>
|
const requestBotCommandConfiguration = (skillType: number) => SendMessageHook(new RequestBotCommandConfigurationComposer(rentableBotData.webID, skillType));
|
||||||
{
|
|
||||||
SendMessageHook(new RequestBotCommandConfigurationComposer(rentableBotData.webID, skillType));
|
|
||||||
}, [ rentableBotData ]);
|
|
||||||
|
|
||||||
const processAction = useCallback((name: string) =>
|
const processAction = (name: string) =>
|
||||||
{
|
{
|
||||||
let hideMenu = true;
|
let hideMenu = true;
|
||||||
|
|
||||||
@ -130,7 +126,12 @@ export const AvatarInfoWidgetRentableBotView: FC<AvatarInfoWidgetRentableBotView
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(hideMenu) close();
|
if(hideMenu) close();
|
||||||
}, [ rentableBotData, newName, newMotto, requestBotCommandConfiguration, close ]);
|
}
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setMode(MODE_NORMAL);
|
||||||
|
}, [ rentableBotData ]);
|
||||||
|
|
||||||
const canControl = (rentableBotData.amIOwner || rentableBotData.amIAnyRoomController);
|
const canControl = (rentableBotData.amIOwner || rentableBotData.amIAnyRoomController);
|
||||||
|
|
||||||
@ -139,63 +140,63 @@ export const AvatarInfoWidgetRentableBotView: FC<AvatarInfoWidgetRentableBotView
|
|||||||
<ContextMenuHeaderView>
|
<ContextMenuHeaderView>
|
||||||
{ rentableBotData.name }
|
{ rentableBotData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
{ (mode === MODE_NORMAL) &&
|
{ (mode === MODE_NORMAL) && canControl &&
|
||||||
<>
|
<>
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.DONATE_TO_ALL) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.DONATE_TO_ALL) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('donate_to_all') }>
|
<ContextMenuListItemView onClick={ event => processAction('donate_to_all') }>
|
||||||
{ LocalizeText('avatar.widget.donate_to_all') }
|
{ LocalizeText('avatar.widget.donate_to_all') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.DONATE_TO_USER) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.DONATE_TO_USER) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('donate_to_user') }>
|
<ContextMenuListItemView onClick={ event => processAction('donate_to_user') }>
|
||||||
{ LocalizeText('avatar.widget.donate_to_user') }
|
{ LocalizeText('avatar.widget.donate_to_user') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.CHANGE_BOT_NAME) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.CHANGE_BOT_NAME) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('change_bot_name') }>
|
<ContextMenuListItemView onClick={ event => processAction('change_bot_name') }>
|
||||||
{ LocalizeText('avatar.widget.change_bot_name') }
|
{ LocalizeText('avatar.widget.change_bot_name') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.CHANGE_BOT_MOTTO) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.CHANGE_BOT_MOTTO) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('change_bot_motto') }>
|
<ContextMenuListItemView onClick={ event => processAction('change_bot_motto') }>
|
||||||
{ LocalizeText('avatar.widget.change_bot_motto') }
|
{ LocalizeText('avatar.widget.change_bot_motto') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.DRESS_UP) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.DRESS_UP) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('dress_up') }>
|
<ContextMenuListItemView onClick={ event => processAction('dress_up') }>
|
||||||
{ LocalizeText('avatar.widget.dress_up') }
|
{ LocalizeText('avatar.widget.dress_up') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.RANDOM_WALK) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.RANDOM_WALK) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('random_walk') }>
|
<ContextMenuListItemView onClick={ event => processAction('random_walk') }>
|
||||||
{ LocalizeText('avatar.widget.random_walk') }
|
{ LocalizeText('avatar.widget.random_walk') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.SETUP_CHAT) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.SETUP_CHAT) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('setup_chat') }>
|
<ContextMenuListItemView onClick={ event => processAction('setup_chat') }>
|
||||||
{ LocalizeText('avatar.widget.setup_chat') }
|
{ LocalizeText('avatar.widget.setup_chat') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.DANCE) >= 0) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.DANCE) >= 0) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('dance') }>
|
<ContextMenuListItemView onClick={ event => processAction('dance') }>
|
||||||
{ LocalizeText('avatar.widget.dance') }
|
{ LocalizeText('avatar.widget.dance') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
{ ((rentableBotData.botSkills.indexOf(BotSkillsEnum.NO_PICK_UP) === -1) && canControl) &&
|
{ (rentableBotData.botSkills.indexOf(BotSkillsEnum.NO_PICK_UP) === -1) &&
|
||||||
<ContextMenuListItemView onClick={ event => processAction('pick') }>
|
<ContextMenuListItemView onClick={ event => processAction('pick') }>
|
||||||
{ LocalizeText('avatar.widget.pick_up') }
|
{ LocalizeText('avatar.widget.pick_up') }
|
||||||
</ContextMenuListItemView> }
|
</ContextMenuListItemView> }
|
||||||
</> }
|
</> }
|
||||||
{ (mode === MODE_CHANGE_NAME) &&
|
{ (mode === MODE_CHANGE_NAME) &&
|
||||||
<div className="d-flex flex-column menu-item" onClick={ null }>
|
<Column className="menu-item" onClick={ null } gap={ 1 }>
|
||||||
<p className="mb-1">{ LocalizeText('bot.skill.name.configuration.new.name') }</p>
|
<Text variant="white">{ LocalizeText('bot.skill.name.configuration.new.name') }</Text>
|
||||||
<input type="text" className="form-control form-control-sm mb-2" value={ newName } onChange={ event => setNewName(event.target.value) } />
|
<input type="text" className="form-control form-control-sm" value={ newName } onChange={ event => setNewName(event.target.value) } />
|
||||||
<div className="d-flex justify-content-between align-items-center">
|
<Flex alignItems="center" justifyContent="between" gap={ 1 }>
|
||||||
<button type="button" className="btn btn-secondary btn-sm" onClick={ event => processAction(null) }>{ LocalizeText('cancel') }</button>
|
<Button fullWidth variant="secondary" onClick={ event => processAction(null) }>{ LocalizeText('cancel') }</Button>
|
||||||
<button type="button" className="btn btn-success btn-sm" onClick={ event => processAction('save_bot_name') }>{ LocalizeText('save') }</button>
|
<Button fullWidth variant="success" onClick={ event => processAction('save_bot_name') }>{ LocalizeText('save') }</Button>
|
||||||
</div>
|
</Flex>
|
||||||
</div> }
|
</Column> }
|
||||||
{ (mode === MODE_CHANGE_MOTTO) &&
|
{ (mode === MODE_CHANGE_MOTTO) &&
|
||||||
<div className="d-flex flex-column menu-item" onClick={ null }>
|
<Column className="menu-item" onClick={ null } gap={ 1 }>
|
||||||
<p className="mb-1">{ LocalizeText('bot.skill.name.configuration.new.motto') }</p>
|
<Text variant="white">{ LocalizeText('bot.skill.name.configuration.new.motto') }</Text>
|
||||||
<input type="text" className="form-control form-control-sm mb-2" value={ newMotto } onChange={ event => setNewMotto(event.target.value) } />
|
<input type="text" className="form-control form-control-sm" value={ newMotto } onChange={ event => setNewMotto(event.target.value) } />
|
||||||
<div className="d-flex justify-content-between align-items-center">
|
<Flex alignItems="center" justifyContent="between" gap={ 1 }>
|
||||||
<button type="button" className="btn btn-secondary btn-sm" onClick={ event => processAction(null) }>{ LocalizeText('cancel') }</button>
|
<Button fullWidth variant="secondary" onClick={ event => processAction(null) }>{ LocalizeText('cancel') }</Button>
|
||||||
<button type="button" className="btn btn-success btn-sm" onClick={ event => processAction('save_bot_motto') }>{ LocalizeText('save') }</button>
|
<Button fullWidth variant="success" onClick={ event => processAction('save_bot_motto') }>{ LocalizeText('save') }</Button>
|
||||||
</div>
|
</Flex>
|
||||||
</div> }
|
</Column> }
|
||||||
</ContextMenuView>
|
</ContextMenuView>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -3,16 +3,16 @@ import { FC, useCallback, useMemo, useState } from 'react';
|
|||||||
import { GetRoomSession, GetSessionDataManager, RoomWidgetObjectNameEvent, RoomWidgetRoomObjectMessage, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUpdateRoomEngineEvent, RoomWidgetUpdateRoomObjectEvent, RoomWidgetUseProductBubbleEvent, UseProductItem } from '../../../../api';
|
import { GetRoomSession, GetSessionDataManager, RoomWidgetObjectNameEvent, RoomWidgetRoomObjectMessage, RoomWidgetUpdateDanceStatusEvent, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUpdateInfostandEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent, RoomWidgetUpdateRentableBotChatEvent, RoomWidgetUpdateRoomEngineEvent, RoomWidgetUpdateRoomObjectEvent, 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 { AvatarInfoRentableBotChatView } from './AvatarInfoRentableBotChatView';
|
||||||
import { AvatarInfoWidgetDecorateView } from './views/decorate/AvatarInfoWidgetDecorateView';
|
import { AvatarInfoUseProductConfirmView } from './AvatarInfoUseProductConfirmView';
|
||||||
import { AvatarInfoWidgetNameView } from './views/name/AvatarInfoWidgetNameView';
|
import { AvatarInfoUseProductView } from './AvatarInfoUseProductView';
|
||||||
import { AvatarInfoWidgetOwnAvatarView } from './views/own-avatar/AvatarInfoWidgetOwnAvatarView';
|
import { AvatarInfoWidgetAvatarView } from './AvatarInfoWidgetAvatarView';
|
||||||
import { AvatarInfoWidgetOwnPetView } from './views/own-pet/AvatarInfoWidgetOwnPetView';
|
import { AvatarInfoWidgetDecorateView } from './AvatarInfoWidgetDecorateView';
|
||||||
import { AvatarInfoWidgetPetView } from './views/pet/AvatarInfoWidgetPetView';
|
import { AvatarInfoWidgetNameView } from './AvatarInfoWidgetNameView';
|
||||||
import { AvatarInfoRentableBotChatView } from './views/rentable-bot-chat/AvatarInfoRentableBotChatView';
|
import { AvatarInfoWidgetOwnAvatarView } from './AvatarInfoWidgetOwnAvatarView';
|
||||||
import { AvatarInfoWidgetRentableBotView } from './views/rentable-bot/AvatarInfoWidgetRentableBotView';
|
import { AvatarInfoWidgetOwnPetView } from './AvatarInfoWidgetOwnPetView';
|
||||||
import { AvatarInfoUseProductConfirmView } from './views/use-product-confirm/AvatarInfoUseProductConfirmView';
|
import { AvatarInfoWidgetPetView } from './AvatarInfoWidgetPetView';
|
||||||
import { AvatarInfoUseProductView } from './views/use-product/AvatarInfoUseProductView';
|
import { AvatarInfoWidgetRentableBotView } from './AvatarInfoWidgetRentableBotView';
|
||||||
|
|
||||||
export const AvatarInfoWidgetView: FC<{}> = props =>
|
export const AvatarInfoWidgetView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import { RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetAvatarViewProps
|
|
||||||
{
|
|
||||||
userData: RoomWidgetUpdateInfostandUserEvent;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
export interface AvatarInfoWidgetDecorateViewProps
|
|
||||||
{
|
|
||||||
userId: number;
|
|
||||||
userName: string;
|
|
||||||
roomIndex: number;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { RoomWidgetObjectNameEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetNameViewProps
|
|
||||||
{
|
|
||||||
nameData: RoomWidgetObjectNameEvent;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetOwnAvatarViewProps
|
|
||||||
{
|
|
||||||
userData: RoomWidgetUpdateInfostandUserEvent;
|
|
||||||
isDancing: boolean;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { RoomWidgetUpdateInfostandPetEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetOwnPetViewProps
|
|
||||||
{
|
|
||||||
petData: RoomWidgetUpdateInfostandPetEvent;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { RoomWidgetUpdateInfostandPetEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetPetViewProps
|
|
||||||
{
|
|
||||||
petData: RoomWidgetUpdateInfostandPetEvent;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
import { BotSkillSaveComposer } from '@nitrots/nitro-renderer';
|
|
||||||
import { FC, useCallback, useMemo, useState } from 'react';
|
|
||||||
import { GetRoomObjectBounds, GetRoomSession, LocalizeText } from '../../../../../../api';
|
|
||||||
import { SendMessageHook } from '../../../../../../hooks';
|
|
||||||
import { DraggableWindow, DraggableWindowPosition } from '../../../../../../layout';
|
|
||||||
import { BotSkillsEnum } from '../../common/BotSkillsEnum';
|
|
||||||
import { AvatarInfoRentableBotChatViewProps } from './AvatarInfoRentableBotChatView.types';
|
|
||||||
|
|
||||||
export const AvatarInfoRentableBotChatView: FC<AvatarInfoRentableBotChatViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { chatEvent = null, close = null } = props;
|
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
|
||||||
const [ newText, setNewText ] = useState<string>(chatEvent.chat === '${bot.skill.chatter.configuration.text.placeholder}' ? '' : chatEvent.chat);
|
|
||||||
const [ automaticChat, setAutomaticChat ] = useState<boolean>(chatEvent.automaticChat);
|
|
||||||
const [ mixSentences, setMixSentences ] = useState<boolean>(chatEvent.mixSentences);
|
|
||||||
const [ chatDelay, setChatDelay ] = useState<number>(chatEvent.chatDelay);
|
|
||||||
|
|
||||||
const getObjectLocation = useMemo(() =>
|
|
||||||
{
|
|
||||||
return GetRoomObjectBounds(GetRoomSession().roomId, chatEvent.objectId, chatEvent.category, 1);
|
|
||||||
}, [ chatEvent ]);
|
|
||||||
|
|
||||||
const formatChatString = useCallback((value: string) =>
|
|
||||||
{
|
|
||||||
return value.replace(/;#;/g, ' ').replace(/\r\n|\r|\n/g, '\r');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const save = useCallback(() =>
|
|
||||||
{
|
|
||||||
const chatConfiguration = formatChatString(newText) + ';#;' + automaticChat + ';#;' + chatDelay + ';#;' + mixSentences;
|
|
||||||
SendMessageHook(new BotSkillSaveComposer(chatEvent.botId, BotSkillsEnum.SETUP_CHAT, chatConfiguration));
|
|
||||||
close();
|
|
||||||
}, [automaticChat, chatDelay, chatEvent.botId, close, formatChatString, mixSentences, newText]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DraggableWindow position={ DraggableWindowPosition.NOTHING } handleSelector=".drag-handler" style={ { top: getObjectLocation.y, left: getObjectLocation.x } }>
|
|
||||||
<div className="nitro-context-menu">
|
|
||||||
<div className="drag-handler">
|
|
||||||
<div className="px-2">
|
|
||||||
<div className="d-flex flex-column menu-item">
|
|
||||||
<p className="mb-1">{ LocalizeText('bot.skill.chatter.configuration.chat.text') }</p>
|
|
||||||
<textarea className="form-control form-control-sm mb-2" placeholder={LocalizeText('bot.skill.chatter.configuration.text.placeholder')} value={newText} rows={7} onChange={e => setNewText(e.target.value)}/>
|
|
||||||
</div>
|
|
||||||
<div className="d-flex flex-row menu-item">
|
|
||||||
<p className="mb-1 me-2">{ LocalizeText('bot.skill.chatter.configuration.automatic.chat') }</p>
|
|
||||||
<input type="checkbox" className="form-check-input" checked={automaticChat} onChange={e => setAutomaticChat(e.target.checked)} />
|
|
||||||
</div>
|
|
||||||
<div className="d-flex flex-row menu-item">
|
|
||||||
<p className="mb-1 me-2">{ LocalizeText('bot.skill.chatter.configuration.markov')}</p>
|
|
||||||
<input type="checkbox" className="form-check-input" checked={mixSentences} onChange={ e => setMixSentences(e.target.checked)} />
|
|
||||||
</div>
|
|
||||||
<div className="d-flex flex-row menu-item">
|
|
||||||
<p className="mb-1 me-2">{ LocalizeText('bot.skill.chatter.configuration.chat.delay') }</p>
|
|
||||||
<input type="number" className="form-control form-control-sm mb-2" value={chatDelay} onChange={e => setChatDelay(e.target.valueAsNumber)}/>
|
|
||||||
</div>
|
|
||||||
<div className="d-flex flex-row justify-content-between mt-1">
|
|
||||||
<button type="button" className="btn btn-secondary btn-sm" onClick={close}>{ LocalizeText('cancel')}</button>
|
|
||||||
<button type="button" className="btn btn-success btn-sm" onClick={save}>{ LocalizeText('save') }</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DraggableWindow>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { RoomWidgetUpdateRentableBotChatEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoRentableBotChatViewProps
|
|
||||||
{
|
|
||||||
chatEvent: RoomWidgetUpdateRentableBotChatEvent;
|
|
||||||
close(): void;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { RoomWidgetUpdateInfostandRentableBotEvent } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoWidgetRentableBotViewProps
|
|
||||||
{
|
|
||||||
rentableBotData: RoomWidgetUpdateInfostandRentableBotEvent;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BotChatOptions
|
|
||||||
{
|
|
||||||
automaticChat: boolean;
|
|
||||||
chatDelay: number;
|
|
||||||
mixSentences: boolean;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { UseProductItem } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoUseProductConfirmViewProps
|
|
||||||
{
|
|
||||||
item: UseProductItem;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { UseProductItem } from '../../../../../../api';
|
|
||||||
|
|
||||||
export interface AvatarInfoUseProductViewProps
|
|
||||||
{
|
|
||||||
item: UseProductItem;
|
|
||||||
updateConfirmingProduct: (product: UseProductItem) => void;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -9,6 +9,11 @@
|
|||||||
z-index: $context-menu-zindex;
|
z-index: $context-menu-zindex;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
|
&.bot-chat {
|
||||||
|
max-width: 250px;
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
&.name-only {
|
&.name-only {
|
||||||
background-color: rgba($black, 0.5);
|
background-color: rgba($black, 0.5);
|
||||||
padding: 1px 8px;
|
padding: 1px 8px;
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import { Flex, FlexProps } from '../../../../common';
|
||||||
|
|
||||||
|
export const ContextMenuHeaderView: FC<FlexProps> = props =>
|
||||||
|
{
|
||||||
|
const { justifyContent = 'center', alignItems = 'center', classNames = [], ...rest } = props;
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'menu-header', 'p-1' ];
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ classNames ]);
|
||||||
|
|
||||||
|
return <Flex justifyContent={ justifyContent } alignItems={ alignItems } classNames={ getClassNames } { ...rest } />;
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
import { FC, MouseEvent, useMemo } from 'react';
|
||||||
|
import { Flex, FlexProps } from '../../../../common';
|
||||||
|
|
||||||
|
interface ContextMenuListItemViewProps extends FlexProps
|
||||||
|
{
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ContextMenuListItemView: FC<ContextMenuListItemViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { disabled = false, fullWidth = true, justifyContent = 'center', alignItems = 'center', classNames = [], onClick = null, ...rest } = props;
|
||||||
|
|
||||||
|
const handleClick = (event: MouseEvent<HTMLDivElement>) =>
|
||||||
|
{
|
||||||
|
if(disabled) return;
|
||||||
|
|
||||||
|
if(onClick) onClick(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'menu-item', 'list-item' ];
|
||||||
|
|
||||||
|
if(disabled) newClassNames.push('disabled');
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ disabled, classNames ]);
|
||||||
|
|
||||||
|
return <Flex fullWidth={ fullWidth } justifyContent={ justifyContent } alignItems={ alignItems } classNames={ getClassNames } onClick={ handleClick } { ...rest } />;
|
||||||
|
}
|
18
src/views/room/widgets/context-menu/ContextMenuListView.tsx
Normal file
18
src/views/room/widgets/context-menu/ContextMenuListView.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import { Column, ColumnProps } from '../../../../common';
|
||||||
|
|
||||||
|
export const ContextMenuListView: FC<ColumnProps> = props =>
|
||||||
|
{
|
||||||
|
const { classNames = [], ...rest } = props;
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'menu-list' ];
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ classNames ]);
|
||||||
|
|
||||||
|
return <Column classNames={ getClassNames } { ...rest } />
|
||||||
|
}
|
@ -1,7 +1,17 @@
|
|||||||
import { FixedSizeStack, NitroPoint, NitroRectangle, RoomObjectType } from '@nitrots/nitro-renderer';
|
import { FixedSizeStack, NitroPoint, NitroRectangle, RoomObjectType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
import { CSSProperties, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { GetNitroInstance, GetRoomEngine, GetRoomObjectBounds, GetRoomSession, GetTicker } from '../../../../api';
|
import { GetNitroInstance, GetRoomEngine, GetRoomObjectBounds, GetRoomSession, GetTicker } from '../../../../api';
|
||||||
import { ContextMenuViewProps } from './ContextMenuView.types';
|
import { Base, BaseProps } from '../../../../common';
|
||||||
|
import { BatchUpdates } from '../../../../hooks';
|
||||||
|
|
||||||
|
interface ContextMenuViewProps extends BaseProps<HTMLDivElement>
|
||||||
|
{
|
||||||
|
objectId: number;
|
||||||
|
category: number;
|
||||||
|
userType?: number;
|
||||||
|
fades?: boolean;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
const LOCATION_STACK_SIZE: number = 25;
|
const LOCATION_STACK_SIZE: number = 25;
|
||||||
const BUBBLE_DROP_SPEED: number = 3;
|
const BUBBLE_DROP_SPEED: number = 3;
|
||||||
@ -11,7 +21,7 @@ const SPACE_AROUND_EDGES = 10;
|
|||||||
|
|
||||||
export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { objectId = -1, category = -1, userType = -1, fades = false, className = '', close = null, children = null } = props;
|
const { objectId = -1, category = -1, userType = -1, fades = false, close = null, position = 'absolute', classNames = [], style = {}, ...rest } = 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 [ deltaYStack, setDeltaYStack ] = useState<FixedSizeStack>(null);
|
const [ deltaYStack, setDeltaYStack ] = useState<FixedSizeStack>(null);
|
||||||
const [ currentDeltaY, setCurrentDeltaY ] = useState(-1000000);
|
const [ currentDeltaY, setCurrentDeltaY ] = useState(-1000000);
|
||||||
@ -92,8 +102,11 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
|||||||
if(y < SPACE_AROUND_EDGES) y = SPACE_AROUND_EDGES;
|
if(y < SPACE_AROUND_EDGES) y = SPACE_AROUND_EDGES;
|
||||||
else if(y > maxTop) y = maxTop;
|
else if(y > maxTop) y = maxTop;
|
||||||
|
|
||||||
setCurrentDeltaY(maxStack);
|
BatchUpdates(() =>
|
||||||
setPos({ x, y });
|
{
|
||||||
|
setCurrentDeltaY(maxStack);
|
||||||
|
setPos({ x, y });
|
||||||
|
});
|
||||||
}, [ deltaYStack, currentDeltaY, getOffset ]);
|
}, [ deltaYStack, currentDeltaY, getOffset ]);
|
||||||
|
|
||||||
const update = useCallback((time: number) =>
|
const update = useCallback((time: number) =>
|
||||||
@ -106,10 +119,37 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
|||||||
updatePosition(bounds, location);
|
updatePosition(bounds, location);
|
||||||
}, [ objectId, category, updateFade, updatePosition ]);
|
}, [ objectId, category, updateFade, updatePosition ]);
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'nitro-context-menu' ];
|
||||||
|
|
||||||
|
newClassNames.push((pos.x !== null) ? 'visible' : 'invisible');
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ pos, classNames ]);
|
||||||
|
|
||||||
|
const getStyle = useMemo(() =>
|
||||||
|
{
|
||||||
|
let newStyle: CSSProperties = {};
|
||||||
|
|
||||||
|
newStyle.left = (pos.x || 0);
|
||||||
|
newStyle.top = (pos.y || 0);
|
||||||
|
newStyle.opacity = opacity;
|
||||||
|
|
||||||
|
if(Object.keys(style).length) newStyle = { ...newStyle, ...style };
|
||||||
|
|
||||||
|
return newStyle;
|
||||||
|
}, [ pos, opacity, style ]);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
setDeltaYStack(new FixedSizeStack(LOCATION_STACK_SIZE));
|
BatchUpdates(() =>
|
||||||
setCurrentDeltaY(-1000000);
|
{
|
||||||
|
setDeltaYStack(new FixedSizeStack(LOCATION_STACK_SIZE));
|
||||||
|
setCurrentDeltaY(-1000000);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
@ -135,15 +175,8 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
|||||||
|
|
||||||
const timeout = setTimeout(() => setIsFading(true), fadeDelay);
|
const timeout = setTimeout(() => setIsFading(true), fadeDelay);
|
||||||
|
|
||||||
return () =>
|
return () => clearTimeout(timeout);
|
||||||
{
|
|
||||||
clearTimeout(timeout);
|
|
||||||
}
|
|
||||||
}, [ fades ]);
|
}, [ fades ]);
|
||||||
|
|
||||||
return (
|
return <Base innerRef={ elementRef } position={ position } classNames={ getClassNames } style={ getStyle } { ...rest } />;
|
||||||
<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 }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
export interface ContextMenuViewProps
|
|
||||||
{
|
|
||||||
objectId: number;
|
|
||||||
category: number;
|
|
||||||
userType?: number;
|
|
||||||
fades?: boolean;
|
|
||||||
className?: string;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { FC } from 'react';
|
|
||||||
import { ContextMenuHeaderViewProps } from './ContextMenuHeaderView.types';
|
|
||||||
|
|
||||||
export const ContextMenuHeaderView: FC<ContextMenuHeaderViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { className = null, onClick = null, children = null } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ 'd-flex justify-content-center align-items-center menu-header p-1' + (className ? ' ' + className : '') } onClick={ onClick }>
|
|
||||||
{ children }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
export interface ContextMenuHeaderViewProps
|
|
||||||
{
|
|
||||||
className?: string;
|
|
||||||
onClick?: (e) => void;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { FC, MouseEvent, useCallback } from 'react';
|
|
||||||
import { ContextMenuListItemViewProps } from './ContextMenuListItemView.types';
|
|
||||||
|
|
||||||
export const ContextMenuListItemView: FC<ContextMenuListItemViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { className = '', canSelect = true, onClick = null, children = null } = props;
|
|
||||||
|
|
||||||
const handleClick = useCallback((event: MouseEvent<HTMLDivElement>) =>
|
|
||||||
{
|
|
||||||
if(!canSelect) return;
|
|
||||||
|
|
||||||
onClick(event);
|
|
||||||
}, [ canSelect, onClick ]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ `d-flex justify-content-center align-items-center w-100 menu-item list-item ${ !canSelect ? 'disabled ' : '' }${ className }` } onClick={ handleClick }>
|
|
||||||
{ children }
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { MouseEvent } from 'react';
|
|
||||||
|
|
||||||
export interface ContextMenuListItemViewProps
|
|
||||||
{
|
|
||||||
className?: string;
|
|
||||||
canSelect?: boolean;
|
|
||||||
onClick: (event: MouseEvent) => void;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { FC } from 'react';
|
|
||||||
import { ContextMenuListViewProps } from './ContextMenuListView.types';
|
|
||||||
|
|
||||||
export const ContextMenuListView: FC<ContextMenuListViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { columns = 1, children = null } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ 'd-flex flex-column menu-list' }>
|
|
||||||
{ children }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
export interface ContextMenuListViewProps
|
|
||||||
{
|
|
||||||
columns?: number;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user