Fix: Inventory Fixes

This commit is contained in:
DuckieTM 2024-03-31 23:33:42 +02:00
parent b41a110be8
commit ef023e67ee
14 changed files with 403 additions and 676 deletions

View File

@ -1,10 +1,7 @@
.nitro-inventory {
height: $inventory-height;
min-height: $inventory-height;
max-height: $inventory-height + 150px;
width: $inventory-width;
min-width: $inventory-width;
max-width: $inventory-width;
height: $inventory-height;
min-width: 326px;
color: #FFF;
input {
@ -14,79 +11,18 @@
&.trading {
width: 535px;
min-height: $inventory-height + 315px !important;
max-width: $inventory-width + 15px !important;
min-width: $inventory-width + 15px !important;
min-height: 505px;
.trading-inventory {
max-height: 240px;
}
.nitro-item-count {
top: 0px;
right: -2px;
background-color: white;
padding: 0px;
padding-left: 3px;
padding-right: 3px;
color: #306A83;
border: 1px solid #2F6982;
font-weight: normal !important;
font-family: Goldfish;
height: 200px;
}
}
.empty-image {
background: url("@/assets/images/inventory/empty.png");
background-repeat: no-repeat;
background: url('@/assets/images/inventory/empty.png') no-repeat;
width: 129px;
height: 181px;
}
.empty-petsimage {
background: url("@/assets/images/inventory/petsempty.png");
background-repeat: no-repeat;
width: 220px;
height: 220px;
}
.empty-furniimage {
background: url("@/assets/images/inventory/furniempty.png");
background-repeat: no-repeat;
width: 220px;
height: 220px;
}
.empty-botsimage {
background: url("@/assets/images/inventory/botsempty.png");
background-repeat: no-repeat;
width: 220px;
height: 220px;
}
.bubble-inventory {
position: relative;
font-family: sans-serif;
font-size: 14px;
line-height: 5px;
width: auto;
background: #fff;
border-radius: 15px;
padding: 5px;
text-align: left;
color: #000;
}
.bubble-inventory-bottom-left:after {
content: "";
position: absolute;
bottom: 0;
left: 15%;
width: 0;
height: 0;
border: 20px solid transparent;
border-top-color: #fff;
border-bottom: 0;
border-right: 0;
margin-left: -10px;
margin-bottom: -20px;
}
.trade-button {
min-height: 0;
@ -96,87 +32,8 @@
}
.trade-bg {
border-image-source: url('@/assets/images/inventory/trading_bg.png');
border-image-source: url(@/assets/images/inventory/trading_bg.png);
border-image-slice: 15 15 15 15 fill;
border-image-width: 15px 15px 15px 15px;
z-index: 1;
}
.credits-align {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 230px;
}
.quantity-input {
width: 49px;
}
.lock-design-left {
margin-left: 21px;
margin-right: 33px;
}
.lock-design-right {
margin-left: 21px;
}
.divisor {
height: 180px;
border-left: 2px solid #B4B4B4;
margin-top: 15px;
}
.inventory-items {
border-image-source: url(@/assets/images/inventory/item.png) !important;
border-image-slice: 6 6 6 6 fill !important;
border-image-width: 6px 6px 6px 6px !important;
&.active {
border-image-source: url(@/assets/images/inventory/selected_item.png) !important;
border-image-slice: 6 6 6 6 fill !important;
border-image-width: 6px 6px 6px 6px !important;
}
&.unseen {
background-color: #9BCA64;
}
.nitro-item-count {
top: 0px;
right: -2px;
background-color: white;
padding: 0px;
padding-left: 3px;
padding-right: 3px;
color: #306A83;
border: 1px solid #2F6982;
font-weight: normal !important;
font-family: Goldfish;
}
}
}
.calc-wrapper {
width: 96%;
height: calc(100% - 100px);
}
.size-list-badges {
width: 335px;
}
.size-badges {
width: 145px;
}
.nitro-inventory-category-filter {
background-color: #C9C9C9;
height: 25px;
}
.text-shadow-around-text {
text-shadow: -1px 0 white, 0 1px white, 1px 0 #ececec, 0 -1px white;
}

View File

@ -1,10 +1,8 @@
import { BadgePointLimitsEvent, ILinkEventTracker, IRoomSession, RoomEngineObjectEvent, RoomEngineObjectPlacedEvent, RoomPreviewer, RoomSessionEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { AddEventLinkTracker, GetLocalization, GetRoomEngine, GroupItem, LocalizeText, RemoveLinkEventTracker, isObjectMoverRequested, setObjectMoverRequested } from '../../api';
import { AddEventLinkTracker, GetLocalization, GetRoomEngine, isObjectMoverRequested, LocalizeText, RemoveLinkEventTracker, setObjectMoverRequested, UnseenItemCategory } from '../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
import { useInventoryBadges, useInventoryFurni, useInventoryTrade, useInventoryUnseenTracker, useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../hooks';
import { TABS, TAB_BADGES, TAB_BOTS, TAB_FURNITURE, TAB_PETS, UNSEEN_CATEGORIES } from './constants';
import { InventoryCategoryFilterView } from './views/InventoryCategoryFilterView';
import { useInventoryTrade, useInventoryUnseenTracker, useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../hooks';
import { InventoryBadgeView } from './views/badge/InventoryBadgeView';
import { InventoryBotView } from './views/bot/InventoryBotView';
import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView';
@ -12,6 +10,12 @@ import { InventoryTradeView } from './views/furniture/InventoryTradeView';
import { InventoryPetView } from './views/pet/InventoryPetView';
import { InventoryFurnitureDeleteView } from './views/furniture/InventoryFurnitureDeleteView';
const TAB_FURNITURE: string = 'inventory.furni';
const TAB_BOTS: string = 'inventory.bots';
const TAB_PETS: string = 'inventory.furni.tab.pets';
const TAB_BADGES: string = 'inventory.badges';
const TABS = [ TAB_FURNITURE, TAB_BOTS, TAB_PETS, TAB_BADGES ];
const UNSEEN_CATEGORIES = [ UnseenItemCategory.FURNI, UnseenItemCategory.BOT, UnseenItemCategory.PET, UnseenItemCategory.BADGE ];
export const InventoryView: FC<{}> = props =>
{
@ -19,12 +23,8 @@ export const InventoryView: FC<{}> = props =>
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>([]);
const [ filteredBadgeCodes, setFilteredBadgeCodes ] = useState<string[]>([]);
const { isTrading = false, stopTrading = null } = useInventoryTrade();
const { getCount = null } = useInventoryUnseenTracker();
const { groupItems = [] } = useInventoryFurni();
const { badgeCodes = [] } = useInventoryBadges();
const { getCount = null, resetCategory = null } = useInventoryUnseenTracker();
const onClose = () =>
{
@ -119,8 +119,9 @@ export const InventoryView: FC<{}> = props =>
if(!isVisible) return null;
return (
<NitroCardView uniqueKey={ 'inventory' } className={ `${ isTrading ? 'nitro-inventory trading no-resize' : 'nitro-inventory' }` } theme={ isTrading ? 'primary' : '' } >
<NitroCardView uniqueKey={ 'inventory' } className={ isTrading ? 'nitro-inventory trading' : 'nitro-inventory' } theme={ isTrading ? 'primary' : '' } >
<NitroCardHeaderView headerText={ LocalizeText('inventory.title') } onCloseClick={ onClose } />
{ !isTrading &&
<>
<NitroCardTabsView>
{ TABS.map((name, index) =>
@ -132,21 +133,22 @@ export const InventoryView: FC<{}> = props =>
);
}) }
</NitroCardTabsView>
<NitroCardContentView overflow="hidden">
{ (currentTab !== TAB_PETS && currentTab !== TAB_BOTS) && <InventoryCategoryFilterView currentTab={ currentTab } groupItems={ groupItems } setGroupItems={ setFilteredGroupItems } badgeCodes={ badgeCodes } setBadgeCodes={ setFilteredBadgeCodes } /> }
<NitroCardContentView>
{ (currentTab === TAB_FURNITURE ) &&
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } isTrading={ isTrading } filteredGroupItems={ filteredGroupItems } /> }
{ (currentTab === TAB_PETS ) &&
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } isTrading={ isTrading } /> }
{ (currentTab === TAB_BADGES ) &&
<InventoryBadgeView filteredBadgeCodes={ filteredBadgeCodes } /> }
<InventoryFurnitureView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
{ (currentTab === TAB_BOTS ) &&
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } isTrading={ isTrading } /> }
{ isTrading && <InventoryTradeView currentTab={ currentTab } setCurrentTab={ (e) => setCurrentTab(e) } cancelTrade={ onClose } /> }
<InventoryBotView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
{ (currentTab === TAB_PETS ) &&
<InventoryPetView roomSession={ roomSession } roomPreviewer={ roomPreviewer } /> }
{ (currentTab === TAB_BADGES ) &&
<InventoryBadgeView /> }
</NitroCardContentView>
</> }
{ isTrading &&
<NitroCardContentView>
<InventoryTradeView cancelTrade={ onClose } />
</NitroCardContentView> }
<InventoryFurnitureDeleteView />
</>
</NitroCardView>
);
}

View File

@ -1,41 +1,26 @@
import { FC } from 'react';
import { CreateLinkEvent, LocalizeText } from '../../../api';
import { Button, Column, Flex, Grid, GridProps, Text } from '../../../common';
import { Column, Grid, GridProps, Text } from '../../../common';
export interface InventoryCategoryEmptyViewProps extends GridProps
{
title: string;
desc: string;
isTrading?: boolean;
}
export const InventoryCategoryEmptyView: FC<InventoryCategoryEmptyViewProps> = props =>
{
const { title = '', desc = '', isTrading = false, children = null, ...rest } = props;
const { title = '', desc = '', children = null, ...rest } = props;
return (
<Grid { ...rest }>
<Column justifyContent="start" center size={6} overflow="hidden">
<div className="empty-furniimage" />
</Column>
<Column justifyContent="center" size={6} overflow="hidden">
<div className="bubble-inventory bubble-inventory-bottom-left">
<Text fontSize={6} overflow="unset" truncate>
{title}
</Text>
<Text overflow="auto" fontSize={6}>
{" "}
{desc}
</Text>
</div>
<Column center size={ 5 } overflow="hidden">
<div className="empty-image" />
{ !isTrading &&
<Flex gap={ 2 } position="absolute" className="bottom-2">
<Button className="py-1" onClick={ () => CreateLinkEvent('catalog/open') }>{ LocalizeText('inventory.open.catalog') }</Button>
</Flex>
}
</Column>
<Column justifyContent="center" size={ 7 } overflow="hidden">
<Text bold fontSize={ 5 } overflow="unset" truncate>{ title }</Text>
<Text overflow="auto">{ desc }</Text>
</Column>
{ children }
</Grid>
);
};
}

View File

@ -1,40 +0,0 @@
import { FC } from 'react';
import { CreateLinkEvent, LocalizeText } from '../../../api';
import { Button, Column, Flex, Grid, GridProps, Text } from '../../../common';
export interface InventoryCategoryEmptyViewBots extends GridProps
{
title: string;
desc: string;
isTrading?: boolean;
}
export const InventoryCategoryEmptyViewBots: FC< InventoryCategoryEmptyViewBotsProps> = (props) => {
const { title = '', desc = '', isTrading = false, children = null, ...rest } = props;
return (
<Grid {...rest}>
<Column justifyContent="start" center size={6} overflow="hidden">
<div className="empty-botsimage" />
</Column>
<Column justifyContent="center" size={6} overflow="hidden">
<div className="bubble-inventory bubble-inventory-bottom-left">
<Text fontSize={6} overflow="unset" truncate>
{title}
</Text>
<Text overflow="auto" fontSize={6}>
{" "}
{desc}
</Text>
</div>
<div className="empty-image" />
{ !isTrading &&
<Flex gap={ 2 } position="absolute" className="bottom-2">
<Button className="py-1" onClick={ () => CreateLinkEvent('catalog/open') }>{ LocalizeText('inventory.open.catalog') }</Button>
</Flex>
}
</Column>
{children}
</Grid>
);
};

View File

@ -1,40 +0,0 @@
import { FC } from 'react';
import { CreateLinkEvent, LocalizeText } from '../../../api';
import { Button, Column, Flex, Grid, GridProps, Text } from '../../../common';
export interface InventoryCategoryEmptyViewPets extends GridProps
{
title: string;
desc: string;
isTrading?: boolean;
}
export const InventoryCategoryEmptyViewPets: FC< InventoryCategoryEmptyViewBotsProps> = (props) => {
const { title = '', desc = '', isTrading = false, children = null, ...rest } = props;
return (
<Grid {...rest}>
<Column justifyContent="start" center size={6} overflow="hidden">
<div className="empty-petsimage" />
</Column>
<Column justifyContent="center" size={6} overflow="hidden">
<div className="bubble-inventory bubble-inventory-bottom-left">
<Text fontSize={6} overflow="unset" truncate>
{title}
</Text>
<Text overflow="auto" fontSize={6}>
{" "}
{desc}
</Text>
</div>
<div className="empty-image" />
{ !isTrading &&
<Flex gap={ 2 } position="absolute" className="bottom-2">
<Button className="py-1" onClick={ () => CreateLinkEvent('catalog/open') }>{ LocalizeText('inventory.open.catalog') }</Button>
</Flex>
}
</Column>
{children}
</Grid>
);
};

View File

@ -1,107 +0,0 @@
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
import { GroupItem, LocalizeBadgeName, LocalizeText } from '../../../api';
import { Flex } from '../../../common';
import { InventoryFilterType, TAB_BADGES, TAB_FURNITURE } from '../constants';
export interface InventoryCategoryFilterViewProps
{
currentTab: string;
groupItems: GroupItem[];
badgeCodes: string[];
setGroupItems: Dispatch<SetStateAction<GroupItem[]>>;
setBadgeCodes: Dispatch<SetStateAction<string[]>>;
}
export const InventoryCategoryFilterView: FC<InventoryCategoryFilterViewProps> = props =>
{
const { currentTab = null, groupItems = [], badgeCodes = [], setGroupItems = null, setBadgeCodes = null } = props;
const [ filterType, setFilterType ] = useState<string>(InventoryFilterType.EVERYTHING);
const [ filterPlace, setFilterPlace ] = useState<string>(InventoryFilterType.IN_INVENTORY);
const [ searchValue, setSearchValue ] = useState('');
useEffect(() =>
{
if (currentTab !== TAB_BADGES) return;
let filteredBadgeCodes = [ ...badgeCodes ];
const filteredBadges = badgeCodes.filter( badge => badge.startsWith('ACH_') );
const numberMap = {};
filteredBadges.forEach(badge =>
{
const name = badge.split(/[\d]+/)[0];
const number = Number(badge.replace(name, ''));
if (numberMap[name] === undefined || number > numberMap[name])
{
numberMap[name] = number;
}
});
const allBadges = Object.keys(numberMap).map( name => `${ name }${ numberMap[name] }` ).concat( badgeCodes.filter( badge => !badge.startsWith('ACH_') ) );
filteredBadgeCodes = allBadges.filter(badgeCode =>
{
return LocalizeBadgeName(badgeCode).toLocaleLowerCase().includes(searchValue?.toLocaleLowerCase().replace(' ', ''));
});
setBadgeCodes(filteredBadgeCodes);
}, [ badgeCodes, currentTab, searchValue, setBadgeCodes ]);
useEffect(() =>
{
if (currentTab !== TAB_FURNITURE) return;
let filteredGroupItems = [ ...groupItems ];
const comparison = searchValue.toLocaleLowerCase();
if (filterType === InventoryFilterType.EVERYTHING) return setGroupItems(groupItems.filter( item => item.name.toLocaleLowerCase().includes(comparison) ));
filteredGroupItems = groupItems.filter(item =>
{
const isWallFilter = (filterType === InventoryFilterType.WALL) ? item.isWallItem : false;
const isFloorFilter = (filterType === InventoryFilterType.FLOOR) ? !item.isWallItem : false;
const isSearchFilter = (item.name.toLocaleLowerCase().includes(comparison)) ? true : false;
return comparison && comparison.length ? (isSearchFilter && (isWallFilter || isFloorFilter)) : isWallFilter || isFloorFilter;
});
setGroupItems(filteredGroupItems);
}, [ groupItems, setGroupItems, searchValue, filterType, currentTab ]);
useEffect(() =>
{
setFilterType(InventoryFilterType.EVERYTHING);
setFilterPlace(InventoryFilterType.IN_INVENTORY);
setSearchValue('');
}, [ currentTab ]);
return (
<Flex className="nitro-inventory-category-filter rounded p-1 mt-n1" style={ { width: currentTab === TAB_BADGES ? '320px' : '100%' } }>
<Flex className="position-relative">
<Flex fullWidth alignItems="center" position="relative">
<input type="text" className="form-control form-control-sm" value={ searchValue } onChange={ event => setSearchValue(event.target.value) } />
</Flex>
{ (searchValue && !!searchValue.length) && <i className="icon icon-clear position-absolute cursor-pointer end-1 top-1" onClick={ event => setSearchValue('') } /> }
</Flex>
{ (currentTab !== TAB_BADGES) &&
<>
<Flex alignItems="center" position="relative" className="ms-2">
<select className="form-select form-select-sm" value={ filterType } onChange={ event => setFilterType(event.target.value) }>
{ [ InventoryFilterType.EVERYTHING, InventoryFilterType.FLOOR, InventoryFilterType.WALL ].map((type, index) => <option key={ index } value={ type }>{ LocalizeText(type) }</option>) }
</select>
</Flex>
<Flex alignItems="center" position="relative" className="ms-2">
<select className="form-select form-select-sm" value={ filterPlace } onChange={ event => setFilterPlace(event.target.value) } disabled={ currentTab === TAB_FURNITURE }>
{ [ InventoryFilterType.ANYWHERE, InventoryFilterType.IN_ROOM, InventoryFilterType.IN_INVENTORY ].map((type, index) => <option key={ index } value={ type }>{ LocalizeText(type) }</option>) }
</select>
</Flex>
</>
}
</Flex>
);
}

View File

@ -11,7 +11,7 @@ export const InventoryBadgeItemView: FC<PropsWithChildren<{ badgeCode: string }>
const unseen = isUnseen(UnseenItemCategory.BADGE, getBadgeId(badgeCode));
return (
<LayoutGridItem className="badge-container" itemActive={ (selectedBadgeCode === badgeCode) } itemUnseen={ unseen } onMouseDown={ event => setSelectedBadgeCode(badgeCode) } onDoubleClick={ event => toggleBadge(selectedBadgeCode) } { ...rest }>
<LayoutGridItem itemActive={ (selectedBadgeCode === badgeCode) } itemUnseen={ unseen } onMouseDown={ event => setSelectedBadgeCode(badgeCode) } onDoubleClick={ event => toggleBadge(selectedBadgeCode) } { ...rest }>
<LayoutBadgeImageView badgeCode={ badgeCode } />
{ children }
</LayoutGridItem>

View File

@ -1,21 +1,14 @@
import { FC, useEffect, useState } from 'react';
import { LocalizeBadgeName, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, Text } from '../../../../common';
import { useAchievements, useInventoryBadges, useInventoryUnseenTracker } from '../../../../hooks';
import { useInventoryBadges, useInventoryUnseenTracker } from '../../../../hooks';
import { InventoryBadgeItemView } from './InventoryBadgeItemView';
interface InventoryBadgeViewProps
export const InventoryBadgeView: FC<{}> = props =>
{
filteredBadgeCodes: string[];
}
export const InventoryBadgeView: FC<InventoryBadgeViewProps> = props =>
{
const { filteredBadgeCodes = [] } = props;
const [ isVisible, setIsVisible ] = useState(false);
const { activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, getBadgeId = null, activate = null, deactivate = null } = useInventoryBadges();
const { badgeCodes = [], activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, getBadgeId = null, activate = null, deactivate = null } = useInventoryBadges();
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
const { achievementScore = 0 } = useAchievements();
useEffect(() =>
{
@ -41,41 +34,33 @@ export const InventoryBadgeView: FC<InventoryBadgeViewProps> = props =>
}, []);
return (
<div className="badge-wrapper calc-wrapper mt-n2">
<Grid gap={ 1 }>
<Column overflow="hidden" className="size-list-badges mt-1">
<AutoGrid gap={ 1 } columnCount={ 5 }>
{ filteredBadgeCodes && filteredBadgeCodes.length > 0 && filteredBadgeCodes.map((badgeCode, index) =>
<Grid>
<Column size={ 7 } overflow="hidden">
<AutoGrid columnCount={ 4 }>
{ badgeCodes && (badgeCodes.length > 0) && badgeCodes.map((badgeCode, index) =>
{
if(isWearingBadge(badgeCode)) return null;
return <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />;
return <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />
}) }
</AutoGrid>
</Column>
<Column className="justify-content-between size-badges position-absolute end-2 mt-n4" overflow="auto">
<Column overflow="hidden">
<Text center bold>{ LocalizeText('inventory.badges.activebadges') }</Text>
<AutoGrid gap={ 1 } columnCount={ 5 }>
<Column className="justify-content-between" size={ 5 } overflow="auto">
<Column overflow="hidden" gap={ 2 }>
<Text>{ LocalizeText('inventory.badges.activebadges') }</Text>
<AutoGrid columnCount={ 3 }>
{ activeBadgeCodes && (activeBadgeCodes.length > 0) && activeBadgeCodes.map((badgeCode, index) => <InventoryBadgeItemView key={ index } badgeCode={ badgeCode } />) }
</AutoGrid>
</Column>
{ !!selectedBadgeCode &&
<Column grow justifyContent="end" gap={ 2 }>
<Flex alignItems="center" gap={ 2 }>
<LayoutBadgeImageView shrink badgeCode={ selectedBadgeCode } />
<Text>{ LocalizeBadgeName(selectedBadgeCode) }</Text>
</Flex>
<Button disabled={ !isWearingBadge(selectedBadgeCode) && !canWearBadges() } onClick={ event => toggleBadge(selectedBadgeCode) }>{ LocalizeText(isWearingBadge(selectedBadgeCode) ? 'inventory.badges.clearbadge' : 'inventory.badges.wearbadge') }</Button>
</Column> }
</Column>
</Grid>
<Column gap={ 0 } position="absolute" className="bottom-2" style={ { width: '96%' } }>
{ !!selectedBadgeCode &&
<Flex className="bg-white pb-1 px-2 rounded mt-2" style={ { height: '50px' } } justifyContent={ 'between' } alignItems={ 'end' } gap={ 2 }>
<Flex alignItems="start" gap={ 2 }>
<LayoutBadgeImageView shrink badgeCode={ selectedBadgeCode } />
<Text className="font-bold mt-2">{ LocalizeBadgeName(selectedBadgeCode) }</Text>
</Flex>
<Button className="btn btn-primary mb-1" style={ { fontSize: '12px' } } disabled={ !isWearingBadge(selectedBadgeCode) && !canWearBadges() } onClick={ event => toggleBadge(selectedBadgeCode) }>{ LocalizeText(isWearingBadge(selectedBadgeCode) ? 'inventory.badges.clearbadge' : 'inventory.badges.wearbadge') }</Button>
</Flex>
}
<div className="nitro-progress-bar text-white mt-1">
<Text small center style={ { marginTop: '-1px' } }>{ LocalizeText('achievements.categories.score', [ 'score' ], [ achievementScore.toString() ]) }</Text>
</div>
</Column>
</div>
);
}

View File

@ -1,24 +1,21 @@
import { MouseEventType } from "@nitrots/nitro-renderer";
import { FC, MouseEvent, PropsWithChildren, useState } from "react";
import {
attemptBotPlacement,
IBotItem,
UnseenItemCategory,
} from "../../../../api";
import { LayoutAvatarImageView, LayoutGridItem } from "../../../../common";
import { useInventoryBots, useInventoryUnseenTracker } from "../../../../hooks";
import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, PropsWithChildren, useState } from 'react';
import { attemptBotPlacement, IBotItem, UnseenItemCategory } from '../../../../api';
import { LayoutAvatarImageView, LayoutGridItem } from '../../../../common';
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
export const InventoryBotItemView: FC<
PropsWithChildren<{ botItem: IBotItem }>
> = (props) => {
export const InventoryBotItemView: FC<PropsWithChildren<{ botItem: IBotItem }>> = props =>
{
const { botItem = null, children = null, ...rest } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const { selectedBot = null, setSelectedBot = null } = useInventoryBots();
const { isUnseen = null } = useInventoryUnseenTracker();
const unseen = isUnseen(UnseenItemCategory.BOT, botItem.botData.id);
const onMouseEvent = (event: MouseEvent) => {
switch (event.type) {
const onMouseEvent = (event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
setSelectedBot(botItem);
setMouseDown(true);
@ -27,32 +24,20 @@ export const InventoryBotItemView: FC<
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if (!isMouseDown || selectedBot !== botItem) return;
if(!isMouseDown || (selectedBot !== botItem)) return;
attemptBotPlacement(botItem);
return;
case "dblclick":
case 'dblclick':
attemptBotPlacement(botItem);
return;
}
};
}
return (
<LayoutGridItem
itemActive={selectedBot === botItem}
itemUnseen={unseen}
onMouseDown={onMouseEvent}
onMouseUp={onMouseEvent}
onMouseOut={onMouseEvent}
onDoubleClick={onMouseEvent}
{...rest}
>
<LayoutAvatarImageView
figure={botItem.botData.figure}
direction={3}
headOnly={true}
/>
<LayoutGridItem itemActive={ (selectedBot === botItem) } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest }>
<LayoutAvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
{ children }
</LayoutGridItem>
);
};
}

View File

@ -1,21 +1,20 @@
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { GetRoomEngine, LocalizeText, UnseenItemCategory, attemptBotPlacement } from '../../../../api';
import { attemptBotPlacement, GetRoomEngine, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
import { InventoryCategoryEmptyViewBots } from '../InventoryCategoryEmptyViewBots';
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
import { InventoryBotItemView } from './InventoryBotItemView';
interface InventoryBotViewProps
{
roomSession: IRoomSession;
roomPreviewer: RoomPreviewer;
isTrading: boolean;
}
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
{
const { roomSession = null, roomPreviewer = null, isTrading = false } = props;
const { roomSession = null, roomPreviewer = null } = props;
const [ isVisible, setIsVisible ] = useState(false);
const { botItems = [], selectedBot = null, activate = null, deactivate = null } = useInventoryBots();
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
@ -65,7 +64,7 @@ export const InventoryBotView: FC<InventoryBotViewProps> = props =>
return () => setIsVisible(false);
}, []);
if(!botItems || !botItems.length) return <InventoryCategoryEmptyViewBots title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } isTrading={ isTrading } />;
if(!botItems || !botItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } />;
return (
<Grid>
@ -82,7 +81,7 @@ export const InventoryBotView: FC<InventoryBotViewProps> = props =>
<Column grow justifyContent="between" gap={ 2 }>
<Text grow truncate>{ selectedBot.botData.name }</Text>
{ !!roomSession &&
<Button variant="success" onClick={ event => attemptBotPlacement(selectedBot) }>
<Button onClick={ event => attemptBotPlacement(selectedBot) }>
{ LocalizeText('inventory.furni.placetoroom') }
</Button> }
</Column> }

View File

@ -1,12 +1,12 @@
import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useState } from 'react';
import { GroupItem, attemptItemPlacement } from '../../../../api';
import { attemptItemPlacement, GroupItem } from '../../../../api';
import { LayoutGridItem } from '../../../../common';
import { useInventoryFurni } from '../../../../hooks';
export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem, isTrading: boolean, attemptItemOffer: (count: number) => void, setGroupItem: (item: GroupItem) => void }> = props =>
export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem }> = props =>
{
const { groupItem = null, isTrading = null, attemptItemOffer = null, setGroupItem = null, ...rest } = props;
const { groupItem = null, ...rest } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const { selectedItem = null, setSelectedItem = null } = useInventoryFurni();
@ -24,16 +24,15 @@ export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem, isTrading: b
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !(groupItem === selectedItem)) return;
if (!isTrading) attemptItemPlacement(groupItem);
attemptItemPlacement(groupItem);
return;
case 'dblclick':
if (!isTrading) attemptItemPlacement(groupItem);
if (isTrading) (setGroupItem(groupItem), attemptItemOffer(1))
attemptItemPlacement(groupItem);
return;
}
}
const count = groupItem.getUnlockedCount();
return <LayoutGridItem className={ !count ? 'inventory-items opacity-0-5 ' : 'inventory-items' } itemImage={ groupItem.iconUrl } itemCount={ groupItem.getUnlockedCount() } itemActive={ (groupItem === selectedItem) } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onClick={ event => (count && setGroupItem(groupItem)) } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest } />;
return <LayoutGridItem className={ !count ? 'opacity-0-5 ' : '' } itemImage={ groupItem.iconUrl } itemCount={ groupItem.getUnlockedCount() } itemActive={ (groupItem === selectedItem) } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest } />;
}

View File

@ -1,49 +1,158 @@
import { AdvancedMap } from '@nitrots/nitro-renderer';
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { GroupItem, LocalizeText, TradeState } from '../../../../api';
import { FaChevronLeft, FaChevronRight, FaLock, FaUnlock } from 'react-icons/fa';
import { FurniCategory, getGuildFurniType, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, SendMessageComposer, TradeState } from '../../../../api';
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
import { useInventoryTrade } from '../../../../hooks';
import { MAX_ITEMS_TO_TRADE, TABS, TAB_FURNITURE } from '../../constants';
import { useInventoryTrade, useNotification } from '../../../../hooks';
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
interface InventoryTradeViewProps
{
currentTab: string;
setCurrentTab: (value: string) => void;
cancelTrade: () => void;
}
const MAX_ITEMS_TO_TRADE: number = 9;
export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
{
const { currentTab = null, setCurrentTab = null, cancelTrade = null } = props;
const { cancelTrade = null } = props;
const [ groupItem, setGroupItem ] = useState<GroupItem>(null);
const [ ownGroupItem, setOwnGroupItem ] = useState<GroupItem>(null);
const [ otherGroupItem, setOtherGroupItem ] = useState<GroupItem>(null);
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>(null);
const [ countdownTick, setCountdownTick ] = useState(3);
const { ownUser = null, otherUser = null, tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useInventoryTrade();
const [ quantity, setQuantity ] = useState<number>(1);
const { ownUser = null, otherUser = null, groupItems = [], tradeState = TradeState.TRADING_STATE_READY, progressTrade = null, removeItem = null, setTradeState = null } = useInventoryTrade();
const { simpleAlert = null } = useNotification();
const canTradeItem = (isWallItem: boolean, spriteId: number, category: number, groupable: boolean, stuffData: IObjectData) =>
{
if(!ownUser || ownUser.accepts || !ownUser.userItems) return false;
if(ownUser.userItems.length < MAX_ITEMS_TO_TRADE) return true;
if(!groupable) return false;
let type = spriteId.toString();
if(category === FurniCategory.POSTER)
{
type = ((type + 'poster') + stuffData.getLegacyString());
}
else
{
if(category === FurniCategory.GUILD_FURNI)
{
type = getGuildFurniType(spriteId, stuffData);
}
else
{
type = (((isWallItem) ? 'I' : 'S') + type);
}
}
return !!ownUser.userItems.getValue(type);
}
const attemptItemOffer = (count: number) =>
{
if(!groupItem) return;
const tradeItems = groupItem.getTradeItems(count);
if(!tradeItems || !tradeItems.length) return;
let coreItem: IFurnitureItem = null;
const itemIds: number[] = [];
for(const item of tradeItems)
{
itemIds.push(item.id);
if(!coreItem) coreItem = item;
}
const ownItemCount = ownUser.userItems.length;
if((ownItemCount + itemIds.length) <= 1500)
{
if(!coreItem.isGroupable && (itemIds.length))
{
SendMessageComposer(new TradingListAddItemComposer(itemIds.pop()));
}
else
{
const tradeIds: number[] = [];
for(const itemId of itemIds)
{
if(canTradeItem(coreItem.isWallItem, coreItem.type, coreItem.category, coreItem.isGroupable, coreItem.stuffData))
{
tradeIds.push(itemId);
}
}
if(tradeIds.length)
{
if(tradeIds.length === 1)
{
SendMessageComposer(new TradingListAddItemComposer(tradeIds.pop()));
}
else
{
SendMessageComposer(new TradingListAddItemsComposer(...tradeIds));
}
}
}
}
else
{
simpleAlert(LocalizeText('trading.items.too_many_items.desc'), NotificationAlertType.DEFAULT, null, null, LocalizeText('trading.items.too_many_items.title'));
}
}
const getLockIcon = (accepts: boolean) =>
{
if(accepts)
{
return <Base className="mt-auto mb-5 pb-5 icon icon-lock-locked" />
return <FaLock className="mt-auto pb-5 text-success fa-icon" />
}
else
{
return <Base className="mt-auto mb-5 pb-5 icon icon-lock-open" />
return <FaUnlock className="mt-auto pb-5 text-danger fa-icon" />
}
}
const getTotalCredits = (items: AdvancedMap<string, GroupItem>): number =>
const updateQuantity = (value: number, totalItemCount: number) =>
{
return items.getValues().map( item => Number(item.iconUrl.split('/')[item.iconUrl.split('/').length - 1]?.split('_')[1]) * item.items.length ).reduce((acc, cur) => acc + (isNaN(cur) ? 0 : cur), 0);
if(isNaN(Number(value)) || Number(value) < 0 || !value) value = 1;
value = Math.max(Number(value), 1);
value = Math.min(Number(value), totalItemCount);
if(value === quantity) return;
setQuantity(value);
}
const changeCount = (totalItemCount: number) =>
{
updateQuantity(quantity, totalItemCount);
attemptItemOffer(quantity);
}
useEffect(() =>
{
setQuantity(1);
}, [ groupItem ]);
useEffect(() =>
{
if(tradeState !== TradeState.TRADING_STATE_COUNTDOWN) return;
setCountdownTick(3);
const interval = window.setInterval(() =>
const interval = setInterval(() =>
{
setCountdownTick(prevValue =>
{
@ -69,17 +178,49 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
return (
<Column>
<Column fullWidth size={ 12 } overflow="hidden" className="trade-bg p-2 text-black">
{ currentTab === TAB_FURNITURE &&
<>
<Text small>{ LocalizeText('inventory.trading.info.add') }</Text>
<Grid gap={ 0 } overflow="hidden" className="px-2">
<Column size={ 4 } overflow="hidden">
<Flex>
{ (ownUser.accepts) && <Base className="icon icon-confirmed" /> }
<small className={ ownUser.accepts ? 'px-2' : '' }><b>{ LocalizeText('inventory.trading.you') }</b> { LocalizeText('inventory.trading.areoffering') }</small>
<Column size={ 4 } fullWidth overflow="hidden" className="trading-inventory">
<InventoryFurnitureSearchView groupItems={ groupItems } setGroupItems={ setFilteredGroupItems } />
<Flex column fullHeight fullWidth justifyContent="between" overflow="hidden" gap={ 2 }>
<AutoGrid columnCount={ 3 }>
{ filteredGroupItems && (filteredGroupItems.length > 0) && filteredGroupItems.map((item, index) =>
{
const count = item.getUnlockedCount();
return (
<LayoutGridItem key={ index } className={ !count ? 'opacity-0-5 ' : '' } itemImage={ item.iconUrl } itemCount={ count } itemActive={ (groupItem === item) } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => (count && setGroupItem(item)) } onDoubleClick={ event => attemptItemOffer(1) }>
{ ((count > 0) && (groupItem === item)) &&
<Button position="absolute" variant="success" className="trade-button bottom-1 end-1" onClick={ event => attemptItemOffer(1) }>
<FaChevronRight className="fa-icon" />
</Button>
}
</LayoutGridItem>
);
}) }
</AutoGrid>
<Column gap={ 1 } alignItems="end">
<Grid overflow="hidden">
<Column size={ 6 } overflow="hidden">
<input type="number" className="form-control form-control-sm quantity-input" placeholder={ LocalizeText('catalog.bundlewidget.spinner.select.amount') } disabled={ !groupItem } value={ quantity } onChange={ event => setQuantity(event.target.valueAsNumber) } />
</Column>
<Column size={ 6 } overflow="hidden">
<Button variant="secondary" disabled={ !groupItem } onClick={ event => changeCount(groupItem.getUnlockedCount()) }>{ LocalizeText('inventory.trading.areoffering') }</Button>
</Column>
</Grid>
<Base fullWidth className="badge bg-muted">
{ groupItem ? groupItem.name : LocalizeText('catalog_selectproduct') }
</Base>
</Column>
</Flex>
<AutoGrid columnCount={ 3 } columnMinWidth={ 35 } columnMinHeight={ 35 }>
</Column>
</Flex>
<Column fullWidth size={ 8 } overflow="hidden" className="trade-bg p-2">
<Grid overflow="hidden">
<Column size={ 4 } overflow="hidden">
<Flex justifyContent="between" alignItems="center">
<Text>{ LocalizeText('inventory.trading.you') } { LocalizeText('inventory.trading.areoffering') }:</Text>
</Flex>
<AutoGrid columnCount={ 3 }>
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
{
const item = (ownUser.userItems.getWithIndex(i) || null);
@ -89,26 +230,23 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
return (
<LayoutGridItem key={ i } itemActive={ (ownGroupItem === item) } itemImage={ item.iconUrl } itemCount={ item.getTotalCount() } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => setOwnGroupItem(item) } onDoubleClick={ event => removeItem(item) }>
{ (ownGroupItem === item) &&
<Base position="absolute" onClick={ event => removeItem(item) } /> }
<Button position="absolute" variant="danger" className="trade-button bottom-1 start-1" onClick={ event => removeItem(item) }>
<FaChevronLeft className="fa-icon" />
</Button> }
</LayoutGridItem>
);
}) }
</AutoGrid>
<Column gap={ 0 } fullWidth>
<small>{ LocalizeText('inventory.trading.info.itemcount', [ 'value' ], [ ownUser.itemCount.toString() ]) }</small>
<small className="credits-align">{ LocalizeText('inventory.trading.info.creditvalue.own', [ 'value' ], [ getTotalCredits(ownUser.userItems).toString() ]) }</small>
<Base fullWidth className="badge bg-muted">
{ ownGroupItem ? ownGroupItem.name : LocalizeText('catalog_selectproduct') }
</Base>
</Column>
</Column>
<Flex className="lock-design-left">
{ getLockIcon(ownUser.accepts) }
</Flex>
<Flex className="divisor"></Flex>
<Column size={ 4 } overflow="hidden">
<Flex>
{ (otherUser.accepts) && <Base className="icon icon-confirmed" /> }
<small className={ otherUser.accepts ? 'px-2' : '' }><b>{ otherUser.userName }</b> { LocalizeText('inventory.trading.isoffering') }</small>
<Flex justifyContent="between" alignItems="center">
<Text>{ otherUser.userName } { LocalizeText('inventory.trading.isoffering') }:</Text>
</Flex>
<AutoGrid columnCount={ 3 } columnMinWidth={ 35 } columnMinHeight={ 35 }>
<AutoGrid columnCount={ 3 }>
{ Array.from(Array(MAX_ITEMS_TO_TRADE), (e, i) =>
{
const item = (otherUser.userItems.getWithIndex(i) || null);
@ -118,28 +256,14 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
return <LayoutGridItem key={ i } itemActive={ (otherGroupItem === item) } itemImage={ item.iconUrl } itemCount={ item.getTotalCount() } itemUniqueNumber={ item.stuffData.uniqueNumber } onClick={ event => setOtherGroupItem(item) } />;
}) }
</AutoGrid>
<Column gap={ 0 } fullWidth>
<small>{ LocalizeText('inventory.trading.info.itemcount', [ 'value' ], [ otherUser.itemCount.toString() ]) }</small>
<small>{ LocalizeText('inventory.trading.info.creditvalue', [ 'value' ], [ getTotalCredits(otherUser.userItems).toString() ]) }</small>
<Base fullWidth className="badge bg-muted w-100">
{ otherGroupItem ? otherGroupItem.name : LocalizeText('catalog_selectproduct') }
</Base>
</Column>
</Column>
<Flex className="lock-design-right">
{ getLockIcon(otherUser.accepts) }
</Flex>
</Grid>
</>
}
{ currentTab !== TAB_FURNITURE &&
<>
<Flex className="px-2">
<Base className="flex-shrink-0 icon icon-report-room" />
<Text bold>{ LocalizeText('inventory.trading.minimized.trade_in_progress') }</Text>
</Flex>
</>
}
<Flex grow justifyContent="between">
{ (currentTab === TAB_FURNITURE) &&
<>
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
{ (tradeState === TradeState.TRADING_STATE_READY) &&
<Button variant="secondary" disabled={ (!ownUser.itemCount && !otherUser.itemCount) } onClick={ progressTrade }>{ LocalizeText('inventory.trading.accept') }</Button> }
{ (tradeState === TradeState.TRADING_STATE_RUNNING) &&
@ -150,12 +274,6 @@ export const InventoryTradeView: FC<InventoryTradeViewProps> = props =>
<Button variant="secondary" onClick={ progressTrade }>{ LocalizeText('inventory.trading.button.restore') }</Button> }
{ (tradeState === TradeState.TRADING_STATE_CONFIRMED) &&
<Button variant="secondary">{ LocalizeText('inventory.trading.info.waiting') }</Button> }
</>
}
{ (currentTab !== TAB_FURNITURE) &&
<Button variant="secondary" onClick={ () => setCurrentTab(TABS[0]) }>{ LocalizeText('inventory.trading.minimized.continue_trade') }</Button>
}
<Button variant="danger" onClick={ cancelTrade }>{ LocalizeText('generic.cancel') }</Button>
</Flex>
</Column>
</Column>

View File

@ -1,24 +1,21 @@
import { MouseEventType } from "@nitrots/nitro-renderer";
import { FC, MouseEvent, PropsWithChildren, useState } from "react";
import {
attemptPetPlacement,
IPetItem,
UnseenItemCategory,
} from "../../../../api";
import { LayoutGridItem, LayoutPetImageView } from "../../../../common";
import { useInventoryPets, useInventoryUnseenTracker } from "../../../../hooks";
import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, PropsWithChildren, useState } from 'react';
import { attemptPetPlacement, IPetItem, UnseenItemCategory } from '../../../../api';
import { LayoutGridItem, LayoutPetImageView } from '../../../../common';
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
export const InventoryPetItemView: FC<
PropsWithChildren<{ petItem: IPetItem }>
> = (props) => {
export const InventoryPetItemView: FC<PropsWithChildren<{ petItem: IPetItem }>> = props =>
{
const { petItem = null, children = null, ...rest } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const { selectedPet = null, setSelectedPet = null } = useInventoryPets();
const { isUnseen } = useInventoryUnseenTracker();
const unseen = isUnseen(UnseenItemCategory.PET, petItem.petData.id);
const onMouseEvent = (event: MouseEvent) => {
switch (event.type) {
const onMouseEvent = (event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
setSelectedPet(petItem);
setMouseDown(true);
@ -31,28 +28,16 @@ export const InventoryPetItemView: FC<
attemptPetPlacement(petItem);
return;
case "dblclick":
case 'dblclick':
attemptPetPlacement(petItem);
return;
}
};
}
return (
<LayoutGridItem
itemActive={petItem === selectedPet}
itemUnseen={unseen}
onMouseDown={onMouseEvent}
onMouseUp={onMouseEvent}
onMouseOut={onMouseEvent}
onDoubleClick={onMouseEvent}
{...rest}
>
<LayoutPetImageView
figure={petItem.petData.figureData.figuredata}
direction={3}
headOnly={true}
/>
<LayoutGridItem itemActive={ (petItem === selectedPet) } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } onDoubleClick={ onMouseEvent } { ...rest }>
<LayoutPetImageView figure={ petItem.petData.figureData.figuredata } direction={ 3 } headOnly={ true } />
{ children }
</LayoutGridItem>
);
};
}

View File

@ -1,21 +1,20 @@
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { GetRoomEngine, LocalizeText, UnseenItemCategory, attemptPetPlacement } from '../../../../api';
import { attemptPetPlacement, GetRoomEngine, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
import { InventoryCategoryEmptyViewPets } from '../InventoryCategoryEmptyViewPets';
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
import { InventoryPetItemView } from './InventoryPetItemView';
interface InventoryPetViewProps
{
roomSession: IRoomSession;
roomPreviewer: RoomPreviewer;
isTrading: boolean;
}
export const InventoryPetView: FC<InventoryPetViewProps> = props =>
{
const { roomSession = null, roomPreviewer = null, isTrading = false } = props;
const { roomSession = null, roomPreviewer = null } = props;
const [ isVisible, setIsVisible ] = useState(false);
const { petItems = null, selectedPet = null, activate = null, deactivate = null } = useInventoryPets();
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
@ -64,7 +63,7 @@ export const InventoryPetView: FC<InventoryPetViewProps> = props =>
return () => setIsVisible(false);
}, []);
if(!petItems || !petItems.length) return <InventoryCategoryEmptyViewPets title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } isTrading={ isTrading } />;
if(!petItems || !petItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } />;
return (
<Grid>
@ -81,7 +80,7 @@ export const InventoryPetView: FC<InventoryPetViewProps> = props =>
<Column grow justifyContent="between" gap={ 2 }>
<Text grow truncate>{ selectedPet.petData.name }</Text>
{ !!roomSession &&
<Button variant="success" onClick={ event => attemptPetPlacement(selectedPet) }>
<Button onClick={ event => attemptPetPlacement(selectedPet) }>
{ LocalizeText('inventory.furni.placetoroom') }
</Button> }
</Column> }