Inventory changes

This commit is contained in:
Bill 2022-04-02 01:33:29 -04:00
parent 6b2b868a91
commit 855d9f2f0d
19 changed files with 384 additions and 362 deletions

View File

@ -3,7 +3,6 @@ export interface IUnseenItemTracker
dispose(): void;
resetCategory(category: number): boolean;
resetItems(category: number, itemIds: number[]): boolean;
resetCategoryIfEmpty(category: number): boolean;
isUnseen(category: number, itemId: number): boolean;
removeUnseen(category: number, itemId: number): boolean;
getIds(category: number): number[];

View File

@ -14,9 +14,10 @@ interface CatalogBadgeSelectorWidgetViewProps extends AutoGridProps
export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewProps> = props =>
{
const { columnCount = 5, ...rest } = props;
const [ isVisible, setIsVisible ] = useState(false);
const [ currentBadgeCode, setCurrentBadgeCode ] = useState<string>(null);
const { currentOffer = null, setPurchaseOptions = null } = useCatalogContext();
const { badgeCodes = [] } = useInventoryBadges();
const { badgeCodes = [], activate = null, deactivate = null } = useInventoryBadges();
const previewStuffData = useMemo(() =>
{
@ -45,6 +46,22 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
});
}, [ currentOffer, previewStuffData, setPurchaseOptions ]);
useEffect(() =>
{
if(!isVisible) return;
const id = activate();
return () => deactivate(id);
}, [ isVisible, activate, deactivate ]);
useEffect(() =>
{
setIsVisible(true);
return () => setIsVisible(false);
}, []);
return (
<AutoGrid columnCount={ columnCount } { ...rest }>
{ badgeCodes && (badgeCodes.length > 0) && badgeCodes.map((badgeCode, index) =>

View File

@ -4,11 +4,11 @@ import { AddEventLinkTracker, GetLocalization, GetRoomEngine, LocalizeText, Remo
import { isObjectMoverRequested, setObjectMoverRequested } from '../../api/inventory/InventoryUtilities';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../common';
import { useInventoryTrade, useInventoryUnseenTracker, UseMessageEventHook, UseRoomEngineEvent, UseRoomSessionManagerEvent } from '../../hooks';
import { InventoryBadgeView } from './views/InventoryBadgeView';
import { InventoryBotView } from './views/InventoryBotView';
import { InventoryFurnitureView } from './views/InventoryFurnitureView';
import { InventoryPetView } from './views/InventoryPetView';
import { InventoryTradeView } from './views/InventoryTradeView';
import { InventoryBadgeView } from './views/badge/InventoryBadgeView';
import { InventoryBotView } from './views/bot/InventoryBotView';
import { InventoryFurnitureView } from './views/furniture/InventoryFurnitureView';
import { InventoryTradeView } from './views/furniture/InventoryTradeView';
import { InventoryPetView } from './views/pet/InventoryPetView';
const TAB_FURNITURE: string = 'inventory.furni';
const TAB_BOTS: string = 'inventory.bots';
@ -19,7 +19,7 @@ const UNSEEN_CATEGORIES = [ UnseenItemCategory.FURNI, UnseenItemCategory.BOT, Un
export const InventoryView: FC<{}> = props =>
{
const [ isVisible, setIsVisible ] = useState(false);
const [ isVisible, setIsVisible ] = useState(false);
const [ currentTab, setCurrentTab ] = useState<string>(TABS[0]);
const [ roomSession, setRoomSession ] = useState<IRoomSession>(null);
const [ roomPreviewer, setRoomPreviewer ] = useState<RoomPreviewer>(null);
@ -130,10 +130,8 @@ export const InventoryView: FC<{}> = props =>
<NitroCardTabsView>
{ TABS.map((name, index) =>
{
const unseenCount = getCount(UNSEEN_CATEGORIES[index]);
return (
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => setCurrentTab(name) } count={ unseenCount }>
<NitroCardTabsItemView key={ index } isActive={ (currentTab === name) } onClick={ event => setCurrentTab(name) } count={ getCount(UNSEEN_CATEGORIES[index]) }>
{ LocalizeText(name) }
</NitroCardTabsItemView>
);

View File

@ -0,0 +1,19 @@
import { FC } from 'react';
import { UnseenItemCategory } from '../../../../api';
import { LayoutBadgeImageView, LayoutGridItem } from '../../../../common';
import { useInventoryBadges, useInventoryUnseenTracker } from '../../../../hooks';
export const InventoryBadgeItemView: FC<{ badgeCode: string }> = props =>
{
const { badgeCode = null, children = null, ...rest } = props;
const { selectedBadgeCode = null, setSelectedBadgeCode = null, getBadgeId = null } = useInventoryBadges();
const { isUnseen = null } = useInventoryUnseenTracker();
const unseen = isUnseen(UnseenItemCategory.BADGE, getBadgeId(badgeCode));
return (
<LayoutGridItem itemActive={ (selectedBadgeCode === badgeCode) } itemUnseen={ unseen } onMouseDown={ event => setSelectedBadgeCode(badgeCode) } { ...rest }>
<LayoutBadgeImageView badgeCode={ badgeCode } />
{ children }
</LayoutGridItem>
);
}

View File

@ -1,47 +1,37 @@
import { FC, useEffect } from 'react';
import { LocalizeBadgeName, LocalizeText, UnseenItemCategory } from '../../../api';
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, LayoutGridItem, Text } from '../../../common';
import { useInventoryBadges, useInventoryUnseenTracker } from '../../../hooks';
import { FC, useEffect, useState } from 'react';
import { LocalizeBadgeName, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Flex, Grid, LayoutBadgeImageView, Text } from '../../../../common';
import { useInventoryBadges, useInventoryUnseenTracker } from '../../../../hooks';
import { InventoryBadgeItemView } from './InventoryBadgeItemView';
export const InventoryBadgeView: FC<{}> = props =>
{
const { badgeCodes = [], activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, selectBadge = null, getBadgeId = null } = useInventoryBadges();
const [ isVisible, setIsVisible ] = useState(false);
const { badgeCodes = [], activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, getBadgeId = null, activate = null, deactivate = null } = useInventoryBadges();
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
useEffect(() =>
{
if(!badgeCodes || !badgeCodes.length) return;
return () =>
{
const count = getCount(UnseenItemCategory.BADGE);
if(!selectedBadgeCode || !isUnseen(UnseenItemCategory.BADGE, getBadgeId(selectedBadgeCode))) return;
if(!count) return;
removeUnseen(UnseenItemCategory.BADGE, getBadgeId(selectedBadgeCode));
}, [ selectedBadgeCode, isUnseen, removeUnseen, getBadgeId ]);
resetCategory(UnseenItemCategory.BADGE);
}
}, [ badgeCodes, getCount, resetCategory ]);
const InventoryBadgeItemView: FC<{ badgeCode: string }> = props =>
useEffect(() =>
{
const { badgeCode = null, children = null, ...rest } = props;
const badgeId = getBadgeId(badgeCode);
const unseen = isUnseen(UnseenItemCategory.BADGE, badgeId);
if(!isVisible) return;
const select = () =>
{
selectBadge(badgeCode);
const id = activate();
if(unseen) removeUnseen(UnseenItemCategory.BADGE, badgeId);
}
return () => deactivate(id);
}, [ isVisible, activate, deactivate ]);
return (
<LayoutGridItem itemActive={ (selectedBadgeCode === badgeCode) } itemUnseen={ unseen } onMouseDown={ select } { ...rest }>
<LayoutBadgeImageView badgeCode={ badgeCode } />
{ children }
</LayoutGridItem>
);
}
useEffect(() =>
{
setIsVisible(true);
return () => setIsVisible(false);
}, []);
return (
<Grid>

View File

@ -0,0 +1,40 @@
import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useState } from 'react';
import { attemptBotPlacement, IBotItem, UnseenItemCategory } from '../../../../api';
import { LayoutAvatarImageView, LayoutGridItem } from '../../../../common';
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
export const InventoryBotItemView: FC<{ 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)
{
case MouseEventType.MOUSE_DOWN:
setSelectedBot(botItem);
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || (selectedBot !== botItem)) return;
attemptBotPlacement(botItem);
return;
}
}
return (
<LayoutGridItem itemActive={ (selectedBot === botItem) } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } { ...rest }>
<LayoutAvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
{ children }
</LayoutGridItem>
);
}

View File

@ -1,9 +1,10 @@
import { IRoomSession, MouseEventType, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useEffect, useState } from 'react';
import { attemptBotPlacement, GetRoomEngine, IBotItem, LocalizeText, UnseenItemCategory } from '../../../api';
import { AutoGrid, Button, Column, Grid, LayoutAvatarImageView, LayoutGridItem, LayoutRoomPreviewerView, Text } from '../../../common';
import { useInventoryBots, useInventoryUnseenTracker } from '../../../hooks';
import { InventoryCategoryEmptyView } from './InventoryCategoryEmptyView';
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { attemptBotPlacement, GetRoomEngine, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
import { useInventoryBots, useInventoryUnseenTracker } from '../../../../hooks';
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
import { InventoryBotItemView } from './InventoryBotItemView';
interface InventoryBotViewProps
{
@ -14,22 +15,9 @@ interface InventoryBotViewProps
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
{
const { roomSession = null, roomPreviewer = null } = props;
const { botItems = [], selectedBot = null, selectBot = null } = useInventoryBots();
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
useEffect(() =>
{
if(!botItems || !botItems.length) return;
return () =>
{
const count = getCount(UnseenItemCategory.BOT);
if(!count) return;
resetCategory(UnseenItemCategory.BOT);
}
}, [ botItems, getCount, resetCategory ]);
const [ isVisible, setIsVisible ] = useState(false);
const { botItems = [], selectedBot = null, activate = null, deactivate = null } = useInventoryBots();
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
useEffect(() =>
{
@ -53,43 +41,30 @@ export const InventoryBotView: FC<InventoryBotViewProps> = props =>
roomPreviewer.addAvatarIntoRoom(botData.figure, 0);
}, [ roomPreviewer, selectedBot ]);
if(!botItems || !botItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } />;
const InventoryBotItemView: FC<{ botItem: IBotItem }> = props =>
useEffect(() =>
{
const { botItem = null } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const isActive = (botItem === selectedBot);
const unseen = isUnseen(UnseenItemCategory.BOT, botItem.botData.id);
if(!selectedBot || !isUnseen(UnseenItemCategory.BOT, selectedBot.botData.id)) return;
const onMouseEvent = (event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
selectBot(botItem);
removeUnseen(UnseenItemCategory.BOT, selectedBot.botData.id);
}, [ selectedBot, isUnseen, removeUnseen ]);
if(unseen) removeUnseen(UnseenItemCategory.BOT, botItem.botData.id);
useEffect(() =>
{
if(!isVisible) return;
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !isActive) return;
const id = activate();
attemptBotPlacement(botItem);
return;
}
}
return () => deactivate(id);
}, [ isVisible, activate, deactivate ]);
return (
<LayoutGridItem itemActive={ isActive } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
<LayoutAvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
</LayoutGridItem>
);
}
useEffect(() =>
{
setIsVisible(true);
return () => setIsVisible(false);
}, []);
if(!botItems || !botItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.bots.title') } desc={ LocalizeText('inventory.empty.bots.desc') } />;
return (
<Grid>

View File

@ -0,0 +1,35 @@
import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useState } from 'react';
import { attemptItemPlacement, GroupItem } from '../../../../api';
import { LayoutGridItem } from '../../../../common';
import { useInventoryFurni } from '../../../../hooks';
export const InventoryFurnitureItemView: FC<{ groupItem: GroupItem }> = props =>
{
const { groupItem = null, ...rest } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const { selectedItem = null, setSelectedItem = null } = useInventoryFurni();
const onMouseEvent = (event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
setSelectedItem(groupItem);
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !(groupItem === selectedItem)) return;
attemptItemPlacement(groupItem);
return;
}
}
const count = groupItem.getUnlockedCount();
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 } { ...rest } />;
}

View File

@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
import { GroupItem, LocalizeText } from '../../../api';
import { Button, Flex } from '../../../common';
import { GroupItem, LocalizeText } from '../../../../api';
import { Button, Flex } from '../../../../common';
export interface InventoryFurnitureSearchViewProps
{

View File

@ -1,10 +1,11 @@
import { IRoomSession, MouseEventType, RoomObjectVariable, RoomPreviewer, Vector3d } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useEffect, useState } from 'react';
import { attemptItemPlacement, FurniCategory, GetRoomEngine, GetSessionDataManager, GroupItem, LocalizeText, UnseenItemCategory } from '../../../api';
import { AutoGrid, Button, Column, Grid, LayoutGridItem, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomPreviewerView, Text } from '../../../common';
import { useInventoryFurni, useInventoryUnseenTracker } from '../../../hooks';
import { attemptPlaceMarketplaceOffer } from '../../../hooks/inventory/common';
import { InventoryCategoryEmptyView } from './InventoryCategoryEmptyView';
import { IRoomSession, RoomObjectVariable, RoomPreviewer, Vector3d } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { attemptItemPlacement, FurniCategory, GetRoomEngine, GetSessionDataManager, GroupItem, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Grid, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomPreviewerView, Text } from '../../../../common';
import { useInventoryFurni, useInventoryUnseenTracker } from '../../../../hooks';
import { attemptPlaceMarketplaceOffer } from '../../../../hooks/inventory/common';
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
import { InventoryFurnitureItemView } from './InventoryFurnitureItemView';
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
interface InventoryFurnitureViewProps
@ -16,9 +17,10 @@ interface InventoryFurnitureViewProps
export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
{
const { roomSession = null, roomPreviewer = null } = props;
const [ isVisible, setIsVisible ] = useState(false);
const [ filteredGroupItems, setFilteredGroupItems ] = useState<GroupItem[]>([]);
const { groupItems = [], selectedItem = null, selectItem = null, activate = null, deactivate = null } = useInventoryFurni();
const { getCount = null, resetCategory = null } = useInventoryUnseenTracker();
const { groupItems = [], selectedItem = null, activate = null, deactivate = null } = useInventoryFurni();
const { resetItems = null } = useInventoryUnseenTracker();
useEffect(() =>
{
@ -72,66 +74,31 @@ export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
useEffect(() =>
{
if(!groupItems || !groupItems.length) return;
return () =>
{
const count = getCount(UnseenItemCategory.FURNI);
if(!selectedItem || !selectedItem.hasUnseenItems) return;
if(!count) return;
resetItems(UnseenItemCategory.FURNI, selectedItem.items.map(item => item.id));
resetCategory(UnseenItemCategory.FURNI);
for(const groupItem of groupItems) groupItem.hasUnseenItems = false;
}
}, [ groupItems, getCount, resetCategory ]);
selectedItem.hasUnseenItems = false;
}, [ selectedItem, resetItems ]);
useEffect(() =>
{
if(!isVisible) return;
const id = activate();
return () => deactivate(id);
}, [ activate, deactivate ]);
}, [ isVisible, activate, deactivate ]);
useEffect(() =>
{
setIsVisible(true);
return () => setIsVisible(false);
}, []);
if(!groupItems || !groupItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.title') } desc={ LocalizeText('inventory.empty.desc') } />;
const InventoryFurnitureItemView: FC<{ groupItem: GroupItem }> = props =>
{
const { groupItem = null } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const isActive = (groupItem === selectedItem);
const onMouseEvent = (event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
selectItem(groupItem);
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !isActive) return;
attemptItemPlacement(groupItem);
return;
}
}
useEffect(() =>
{
if(!isActive) return;
groupItem.hasUnseenItems = false;
}, [ isActive, groupItem ]);
const count = groupItem.getUnlockedCount();
return <LayoutGridItem className={ !count ? 'opacity-0-5 ' : '' } itemImage={ groupItem.iconUrl } itemCount={ count } itemActive={ isActive } itemUniqueNumber={ groupItem.stuffData.uniqueNumber } itemUnseen={ groupItem.hasUnseenItems } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } />;
}
return (
<Grid>
<Column size={ 7 } overflow="hidden">

View File

@ -1,10 +1,10 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { FurniCategory, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../api';
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
import { useInventoryTrade } from '../../../hooks';
import { getGuildFurniType } from '../../../hooks/inventory/common/TradingUtilities';
import { FurniCategory, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../../api';
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
import { useInventoryTrade } from '../../../../hooks';
import { getGuildFurniType } from '../../../../hooks/inventory/common/TradingUtilities';
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
interface InventoryTradeViewProps

View File

@ -0,0 +1,40 @@
import { MouseEventType } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useState } from 'react';
import { attemptPetPlacement, IPetItem, UnseenItemCategory } from '../../../../api';
import { LayoutGridItem, LayoutPetImageView } from '../../../../common';
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
export const InventoryPetItemView: FC<{ 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)
{
case MouseEventType.MOUSE_DOWN:
setSelectedPet(petItem);
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !(petItem === selectedPet)) return;
attemptPetPlacement(petItem);
return;
}
}
return (
<LayoutGridItem itemActive={ (petItem === selectedPet) } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent } { ...rest }>
<LayoutPetImageView figure={ petItem.petData.figureData.figuredata } direction={ 3 } headOnly={ true } />
{ children }
</LayoutGridItem>
);
}

View File

@ -1,9 +1,10 @@
import { IRoomSession, MouseEventType, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
import { FC, MouseEvent, useEffect, useState } from 'react';
import { attemptPetPlacement, GetRoomEngine, IPetItem, LocalizeText, UnseenItemCategory } from '../../../api';
import { AutoGrid, Button, Column, Grid, LayoutGridItem, LayoutPetImageView, LayoutRoomPreviewerView, Text } from '../../../common';
import { useInventoryPets, useInventoryUnseenTracker } from '../../../hooks';
import { InventoryCategoryEmptyView } from './InventoryCategoryEmptyView';
import { IRoomSession, RoomObjectVariable, RoomPreviewer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { attemptPetPlacement, GetRoomEngine, LocalizeText, UnseenItemCategory } from '../../../../api';
import { AutoGrid, Button, Column, Grid, LayoutRoomPreviewerView, Text } from '../../../../common';
import { useInventoryPets, useInventoryUnseenTracker } from '../../../../hooks';
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
import { InventoryPetItemView } from './InventoryPetItemView';
interface InventoryPetViewProps
{
@ -14,22 +15,9 @@ interface InventoryPetViewProps
export const InventoryPetView: FC<InventoryPetViewProps> = props =>
{
const { roomSession = null, roomPreviewer = null } = props;
const { petItems = null, selectedPet = null, selectPet = null } = useInventoryPets();
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
useEffect(() =>
{
if(!petItems || !petItems.length) return;
return () =>
{
const count = getCount(UnseenItemCategory.PET);
if(!count) return;
resetCategory(UnseenItemCategory.PET);
}
}, [ petItems, getCount, resetCategory ]);
const [ isVisible, setIsVisible ] = useState(false);
const { petItems = null, selectedPet = null, activate = null, deactivate = null } = useInventoryPets();
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
useEffect(() =>
{
@ -52,43 +40,30 @@ export const InventoryPetView: FC<InventoryPetViewProps> = props =>
roomPreviewer.addPetIntoRoom(petData.figureString);
}, [ roomPreviewer, selectedPet ]);
if(!petItems || !petItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } />;
const InventoryPetItemView: FC<{ petItem: IPetItem }> = props =>
useEffect(() =>
{
const { petItem = null } = props;
const [ isMouseDown, setMouseDown ] = useState(false);
const isActive = (petItem === selectedPet);
const unseen = isUnseen(UnseenItemCategory.PET, petItem.petData.id);
if(!selectedPet || !isUnseen(UnseenItemCategory.PET, selectedPet.petData.id)) return;
const onMouseEvent = (event: MouseEvent) =>
{
switch(event.type)
{
case MouseEventType.MOUSE_DOWN:
selectPet(petItem);
removeUnseen(UnseenItemCategory.PET, selectedPet.petData.id);
}, [ selectedPet, isUnseen, removeUnseen ]);
if(unseen) removeUnseen(UnseenItemCategory.PET, petItem.petData.id);
useEffect(() =>
{
if(!isVisible) return;
setMouseDown(true);
return;
case MouseEventType.MOUSE_UP:
setMouseDown(false);
return;
case MouseEventType.ROLL_OUT:
if(!isMouseDown || !isActive) return;
const id = activate();
attemptPetPlacement(petItem);
return;
}
}
return (
<LayoutGridItem itemActive={ isActive } itemUnseen={ unseen } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
<LayoutPetImageView figure={ petItem.petData.figureData.figuredata } direction={ 3 } headOnly={ true } />
</LayoutGridItem>
);
}
return () => deactivate(id);
}, [ isVisible, activate, deactivate ]);
useEffect(() =>
{
setIsVisible(true);
return () => setIsVisible(false);
}, []);
if(!petItems || !petItems.length) return <InventoryCategoryEmptyView title={ LocalizeText('inventory.empty.pets.title') } desc={ LocalizeText('inventory.empty.pets.desc') } />;
return (
<Grid>

View File

@ -38,7 +38,7 @@ export const NavigatorSearchView: FC<NavigatorSearchViewProps> = props =>
useEffect(() =>
{
if(!searchResult) return null;
if(!searchResult) return;
const split = searchResult.data.split(':');

View File

@ -2,17 +2,19 @@ import { BadgeReceivedEvent, BadgesEvent, RequestBadgesComposer, SetActivatedBad
import { useCallback, useEffect, useState } from 'react';
import { useBetween } from 'use-between';
import { UseMessageEventHook } from '..';
import { GetConfiguration, SendMessageComposer } from '../../api';
import { GetConfiguration, SendMessageComposer, UnseenItemCategory } from '../../api';
import { useSharedVisibility } from '../useSharedVisibility';
import { useInventoryUnseenTracker } from './useInventoryUnseenTracker';
const useInventoryBadgesState = () =>
{
const [ isVisible, setIsVisible ] = useState(false);
const [ needsUpdate, setNeedsUpdate ] = useState(true);
const [ badgeCodes, setBadgeCodes ] = useState<string[]>([]);
const [ badgeIds, setBadgeIds ] = useState<number[]>([]);
const [ activeBadgeCodes, setActiveBadgeCodes ] = useState<string[]>([]);
const [ selectedBadgeCode, setSelectedBadgeCode ] = useState<string>(null);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
const { isUnseen = null, resetCategory = null } = useInventoryUnseenTracker();
const maxBadgeCount = GetConfiguration<number>('user.badges.max.slots', 5);
const isWearingBadge = (badgeCode: string) => (activeBadgeCodes.indexOf(badgeCode) >= 0);
@ -47,13 +49,6 @@ const useInventoryBadgesState = () =>
});
}
const selectBadge = (badgeCode: string) =>
{
if(badgeCodes.indexOf(badgeCode) === -1) return;
setSelectedBadgeCode(badgeCode);
}
const getBadgeId = (badgeCode: string) =>
{
const index = badgeCodes.indexOf(badgeCode);
@ -81,12 +76,14 @@ const useInventoryBadgesState = () =>
const onBadgeReceivedEvent = useCallback((event: BadgeReceivedEvent) =>
{
const parser = event.getParser();
const unseen = isUnseen(UnseenItemCategory.BADGE, parser.badgeId);
setBadgeCodes(prevValue =>
{
const newValue = [ ...prevValue ];
newValue.push(parser.badgeCode);
if(unseen) newValue.unshift(parser.badgeCode)
else newValue.push(parser.badgeCode);
return newValue;
});
@ -95,11 +92,12 @@ const useInventoryBadgesState = () =>
{
const newValue = [ ...prevValue ];
newValue.push(parser.badgeId);
if(unseen) newValue.unshift(parser.badgeId)
else newValue.push(parser.badgeId);
return newValue;
});
}, []);
}, [ isUnseen ]);
UseMessageEventHook(BadgeReceivedEvent, onBadgeReceivedEvent);
@ -119,6 +117,16 @@ const useInventoryBadgesState = () =>
});
}, [ badgeCodes ]);
useEffect(() =>
{
if(!isVisible) return;
return () =>
{
resetCategory(UnseenItemCategory.BADGE);
}
}, [ isVisible, resetCategory ]);
useEffect(() =>
{
if(!isVisible || !needsUpdate) return;
@ -128,25 +136,7 @@ const useInventoryBadgesState = () =>
setNeedsUpdate(false);
}, [ isVisible, needsUpdate ]);
return { badgeCodes, activeBadgeCodes, selectedBadgeCode, isWearingBadge, canWearBadges, toggleBadge, selectBadge, getBadgeId, setIsVisible };
return { badgeCodes, activeBadgeCodes, selectedBadgeCode, setSelectedBadgeCode, isWearingBadge, canWearBadges, toggleBadge, getBadgeId, activate, deactivate };
}
export const useInventoryBadges = () =>
{
const { setIsVisible, ...rest } = useBetween(useInventoryBadgesState);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
useEffect(() =>
{
const id = activate();
return () => deactivate(id);
}, [ activate, deactivate ]);
useEffect(() =>
{
setIsVisible(isVisible);
}, [ isVisible, setIsVisible ]);
return { ...rest };
}
export const useInventoryBadges = () => useBetween(useInventoryBadgesState);

View File

@ -8,13 +8,11 @@ import { useSharedVisibility } from '../useSharedVisibility';
const useInventoryBotsState = () =>
{
const [ isVisible, setIsVisible ] = useState(false);
const [ needsUpdate, setNeedsUpdate ] = useState(true);
const [ botItems, setBotItems ] = useState<IBotItem[]>([]);
const [ selectedBot, setSelectedBot ] = useState<IBotItem>(null);
const { isUnseen = null } = useInventoryUnseenTracker();
const selectBot = (bot: IBotItem) => setSelectedBot(bot);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
const { isUnseen = null, resetCategory = null } = useInventoryUnseenTracker();
const onBotInventoryMessageEvent = useCallback((event: BotInventoryMessageEvent) =>
{
@ -65,7 +63,7 @@ const useInventoryBotsState = () =>
const unseen = isUnseen(UnseenItemCategory.BOT, botData.id);
if(unseen) newValue.unshift(botItem);
newValue.push(botItem);
else newValue.push(botItem);
}
return newValue;
@ -87,12 +85,14 @@ const useInventoryBotsState = () =>
if(index >= 0) return prevValue;
const botItem = { botData: parser.item } as IBotItem;
const unseen = isUnseen(UnseenItemCategory.BOT, botItem.botData.id);
newValue.push(botItem);
if(unseen) newValue.unshift(botItem);
else newValue.push(botItem);
return newValue;
});
}, []);
}, [ isUnseen ]);
UseMessageEventHook(BotAddedToInventoryEvent, onBotAddedToInventoryEvent);
@ -139,6 +139,16 @@ const useInventoryBotsState = () =>
});
}, [ botItems ]);
useEffect(() =>
{
if(!isVisible) return;
return () =>
{
resetCategory(UnseenItemCategory.BOT);
}
}, [ isVisible, resetCategory ]);
useEffect(() =>
{
if(!isVisible || !needsUpdate) return;
@ -148,25 +158,7 @@ const useInventoryBotsState = () =>
setNeedsUpdate(false);
}, [ isVisible, needsUpdate ]);
return { botItems, selectedBot, selectBot, setIsVisible };
return { botItems, selectedBot, setSelectedBot, activate, deactivate };
}
export const useInventoryBots = () =>
{
const { setIsVisible, ...rest } = useBetween(useInventoryBotsState);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
useEffect(() =>
{
const id = activate();
return () => deactivate(id);
}, [ activate, deactivate ]);
useEffect(() =>
{
setIsVisible(isVisible);
}, [ isVisible, setIsVisible ]);
return { ...rest };
}
export const useInventoryBots = () => useBetween(useInventoryBotsState);

View File

@ -11,18 +11,11 @@ let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
const useInventoryFurniState = () =>
{
const [ isVisible, setIsVisible ] = useState(false);
const [ needsUpdate, setNeedsUpdate ] = useState(true);
const [ groupItems, setGroupItems ] = useState<GroupItem[]>([]);
const [ selectedItem, setSelectedItem ] = useState<GroupItem>(null);
const { isUnseen = null, removeUnseen = null, resetCategory = null, getCount = null } = useInventoryUnseenTracker();
const selectItem = (item: GroupItem) =>
{
//removeUnseen(UnseenItemCategory.FURNI, item.id);
setSelectedItem(item);
}
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
const { isUnseen = null, resetCategory = null } = useInventoryUnseenTracker();
const onFurnitureListAddOrUpdateEvent = useCallback((event: FurnitureListAddOrUpdateEvent) =>
{
@ -241,6 +234,26 @@ const useInventoryFurniState = () =>
});
}, [ groupItems ]);
useEffect(() =>
{
if(!isVisible) return;
return () =>
{
if(resetCategory(UnseenItemCategory.FURNI))
{
setGroupItems(prevValue =>
{
const newValue = [ ...prevValue ];
for(const newGroup of newValue) newGroup.hasUnseenItems = false;
return newValue;
});
}
}
}, [ isVisible, resetCategory ]);
useEffect(() =>
{
if(!isVisible || !needsUpdate) return;
@ -250,18 +263,7 @@ const useInventoryFurniState = () =>
setNeedsUpdate(false);
}, [ isVisible, needsUpdate ]);
return { groupItems, setGroupItems, selectedItem, selectItem, setIsVisible };
return { groupItems, setGroupItems, selectedItem, setSelectedItem, activate, deactivate };
}
export const useInventoryFurni = () =>
{
const { setIsVisible, ...rest } = useBetween(useInventoryFurniState);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
useEffect(() =>
{
setIsVisible(isVisible);
}, [ isVisible, setIsVisible ]);
return { activate, deactivate, ...rest };
}
export const useInventoryFurni = () => useBetween(useInventoryFurniState);

View File

@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from 'react';
import { useBetween } from 'use-between';
import { useInventoryUnseenTracker } from '.';
import { UseMessageEventHook } from '..';
import { SendMessageComposer } from '../../api';
import { SendMessageComposer, UnseenItemCategory } from '../../api';
import { IPetItem } from '../../api/inventory/IPetItem';
import { useSharedVisibility } from '../useSharedVisibility';
import { addSinglePetItem, mergePetFragments, processPetFragment, removePetItemById } from './common';
@ -12,13 +12,11 @@ let petMsgFragments: Map<number, PetData>[] = null;
const useInventoryPetsState = () =>
{
const [ isVisible, setIsVisible ] = useState(false);
const [ needsUpdate, setNeedsUpdate ] = useState(true);
const [ petItems, setPetItems ] = useState<IPetItem[]>([]);
const [ selectedPet, setSelectedPet ] = useState<IPetItem>(null);
const { isUnseen = null } = useInventoryUnseenTracker();
const selectPet = (pet: IPetItem) => setSelectedPet(pet);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
const { isUnseen = null, resetCategory = null } = useInventoryUnseenTracker();
const onPetInventoryEvent = useCallback((event: PetInventoryEvent) =>
{
@ -52,11 +50,11 @@ const useInventoryPetsState = () =>
{
const newValue = [ ...prevValue ];
addSinglePetItem(parser.pet, newValue, true);
addSinglePetItem(parser.pet, newValue, isUnseen(UnseenItemCategory.PET, parser.pet.id));
return newValue;
});
}, []);
}, [ isUnseen ]);
UseMessageEventHook(PetAddedToInventoryEvent, onPetAddedToInventoryEvent);
@ -92,6 +90,16 @@ const useInventoryPetsState = () =>
});
}, [ petItems ]);
useEffect(() =>
{
if(!isVisible) return;
return () =>
{
resetCategory(UnseenItemCategory.PET);
}
}, [ isVisible, resetCategory ]);
useEffect(() =>
{
if(!isVisible || !needsUpdate) return;
@ -101,25 +109,7 @@ const useInventoryPetsState = () =>
setNeedsUpdate(false);
}, [ isVisible, needsUpdate ]);
return { petItems, selectedPet, selectPet, setIsVisible };
return { petItems, selectedPet, setSelectedPet, activate, deactivate };
}
export const useInventoryPets = () =>
{
const { setIsVisible, ...rest } = useBetween(useInventoryPetsState);
const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility();
useEffect(() =>
{
const id = activate();
return () => deactivate(id);
}, [ activate, deactivate ]);
useEffect(() =>
{
setIsVisible(isVisible);
}, [ isVisible, setIsVisible ]);
return { ...rest };
}
export const useInventoryPets = () => useBetween(useInventoryPetsState);

View File

@ -22,88 +22,81 @@ const useInventoryUnseenTrackerState = () =>
return count;
}
const resetCategory = (category: number) =>
const resetCategory = useCallback((category: number) =>
{
if(!getCount(category)) return false;
let didReset = true;
setUnseenItems(prevValue =>
{
if(!prevValue.has(category))
{
didReset = false;
return prevValue;
}
const newValue = new Map(prevValue);
newValue.delete(category);
return newValue;
});
sendResetCategoryMessage(category);
return true;
}
const resetCategoryIfEmpty = (category: number) =>
{
if(getCount(category)) return false;
setUnseenItems(prevValue =>
{
const newValue = new Map(prevValue);
newValue.delete(category);
sendResetCategoryMessage(category);
return newValue;
});
sendResetCategoryMessage(category);
return didReset;
}, []);
return true;
}
const resetItems = (category: number, itemIds: number[]) =>
const resetItems = useCallback((category: number, itemIds: number[]) =>
{
if(!getCount(category)) return false;
let didReset = true;
setUnseenItems(prevValue =>
{
if(!prevValue.has(category))
{
didReset = false;
return prevValue;
}
const newValue = new Map(prevValue);
const existing = newValue.get(category);
if(existing) for(const itemId of itemIds) existing.splice(existing.indexOf(itemId), 1);
sendResetItemsMessage(category, itemIds);
return newValue;
});
sendResetItemsMessage(category, itemIds);
return didReset;
}, []);
return true;
}
const isUnseen = (category: number, itemId: number) =>
const isUnseen = useCallback((category: number, itemId: number) =>
{
if(!unseenItems.has(category)) return false;
const items = unseenItems.get(category);
return (items.indexOf(itemId) >= 0);
}
}, [ unseenItems ]);
const removeUnseen = (category: number, itemId: number) =>
const removeUnseen = useCallback((category: number, itemId: number) =>
{
if(!unseenItems.has(category)) return false;
setUnseenItems(prevValue =>
{
if(!prevValue.has(category)) return prevValue;
const newValue = new Map(prevValue);
const items = newValue.get(category);
const index = items.indexOf(itemId);
if(index >= 0)
{
items.splice(index, 1);
}
if(index >= 0) items.splice(index, 1);
return newValue;
});
}
}, []);
const onUnseenItemsEvent = useCallback((event: UnseenItemsEvent) =>
{
@ -135,7 +128,7 @@ const useInventoryUnseenTrackerState = () =>
UseMessageEventHook(UnseenItemsEvent, onUnseenItemsEvent);
return { getIds, getCount, getFullCount, resetCategory, resetCategoryIfEmpty, resetItems, isUnseen, removeUnseen };
return { getIds, getCount, getFullCount, resetCategory, resetItems, isUnseen, removeUnseen };
}
export const useInventoryUnseenTracker = () => useBetween(useInventoryUnseenTrackerState);