diff --git a/src/api/inventory/unseen/IUnseenItemTracker.ts b/src/api/inventory/unseen/IUnseenItemTracker.ts index 51872a00..8a70a166 100644 --- a/src/api/inventory/unseen/IUnseenItemTracker.ts +++ b/src/api/inventory/unseen/IUnseenItemTracker.ts @@ -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[]; diff --git a/src/components/catalog/views/page/widgets/CatalogBadgeSelectorWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogBadgeSelectorWidgetView.tsx index ecbb95b5..b3c6c028 100644 --- a/src/components/catalog/views/page/widgets/CatalogBadgeSelectorWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogBadgeSelectorWidgetView.tsx @@ -14,9 +14,10 @@ interface CatalogBadgeSelectorWidgetViewProps extends AutoGridProps export const CatalogBadgeSelectorWidgetView: FC = props => { const { columnCount = 5, ...rest } = props; + const [ isVisible, setIsVisible ] = useState(false); const [ currentBadgeCode, setCurrentBadgeCode ] = useState(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 + { + if(!isVisible) return; + + const id = activate(); + + return () => deactivate(id); + }, [ isVisible, activate, deactivate ]); + + useEffect(() => + { + setIsVisible(true); + + return () => setIsVisible(false); + }, []); + return ( { badgeCodes && (badgeCodes.length > 0) && badgeCodes.map((badgeCode, index) => diff --git a/src/components/inventory/InventoryView.tsx b/src/components/inventory/InventoryView.tsx index c438e7cc..e23576bc 100644 --- a/src/components/inventory/InventoryView.tsx +++ b/src/components/inventory/InventoryView.tsx @@ -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(TABS[0]); const [ roomSession, setRoomSession ] = useState(null); const [ roomPreviewer, setRoomPreviewer ] = useState(null); @@ -130,10 +130,8 @@ export const InventoryView: FC<{}> = props => { TABS.map((name, index) => { - const unseenCount = getCount(UNSEEN_CATEGORIES[index]); - return ( - setCurrentTab(name) } count={ unseenCount }> + setCurrentTab(name) } count={ getCount(UNSEEN_CATEGORIES[index]) }> { LocalizeText(name) } ); diff --git a/src/components/inventory/views/badge/InventoryBadgeItemView.tsx b/src/components/inventory/views/badge/InventoryBadgeItemView.tsx new file mode 100644 index 00000000..4ec8c184 --- /dev/null +++ b/src/components/inventory/views/badge/InventoryBadgeItemView.tsx @@ -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 ( + setSelectedBadgeCode(badgeCode) } { ...rest }> + + { children } + + ); +} diff --git a/src/components/inventory/views/InventoryBadgeView.tsx b/src/components/inventory/views/badge/InventoryBadgeView.tsx similarity index 65% rename from src/components/inventory/views/InventoryBadgeView.tsx rename to src/components/inventory/views/badge/InventoryBadgeView.tsx index 5b183600..336899b6 100644 --- a/src/components/inventory/views/InventoryBadgeView.tsx +++ b/src/components/inventory/views/badge/InventoryBadgeView.tsx @@ -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 ( - - - { children } - - ); - } + useEffect(() => + { + setIsVisible(true); + + return () => setIsVisible(false); + }, []); return ( diff --git a/src/components/inventory/views/bot/InventoryBotItemView.tsx b/src/components/inventory/views/bot/InventoryBotItemView.tsx new file mode 100644 index 00000000..8f71e14e --- /dev/null +++ b/src/components/inventory/views/bot/InventoryBotItemView.tsx @@ -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 ( + + + { children } + + ); +} diff --git a/src/components/inventory/views/InventoryBotView.tsx b/src/components/inventory/views/bot/InventoryBotView.tsx similarity index 53% rename from src/components/inventory/views/InventoryBotView.tsx rename to src/components/inventory/views/bot/InventoryBotView.tsx index 254a739f..29a7db60 100644 --- a/src/components/inventory/views/InventoryBotView.tsx +++ b/src/components/inventory/views/bot/InventoryBotView.tsx @@ -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 = 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 = props => roomPreviewer.addAvatarIntoRoom(botData.figure, 0); }, [ roomPreviewer, selectedBot ]); - if(!botItems || !botItems.length) return ; - - 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 ( - - - - ); - } + useEffect(() => + { + setIsVisible(true); + + return () => setIsVisible(false); + }, []); + + if(!botItems || !botItems.length) return ; return ( diff --git a/src/components/inventory/views/furniture/InventoryFurnitureItemView.tsx b/src/components/inventory/views/furniture/InventoryFurnitureItemView.tsx new file mode 100644 index 00000000..f72c6ab5 --- /dev/null +++ b/src/components/inventory/views/furniture/InventoryFurnitureItemView.tsx @@ -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 ; +} diff --git a/src/components/inventory/views/InventoryFurnitureSearchView.tsx b/src/components/inventory/views/furniture/InventoryFurnitureSearchView.tsx similarity index 93% rename from src/components/inventory/views/InventoryFurnitureSearchView.tsx rename to src/components/inventory/views/furniture/InventoryFurnitureSearchView.tsx index d81d6060..a230f6d3 100644 --- a/src/components/inventory/views/InventoryFurnitureSearchView.tsx +++ b/src/components/inventory/views/furniture/InventoryFurnitureSearchView.tsx @@ -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 { diff --git a/src/components/inventory/views/InventoryFurnitureView.tsx b/src/components/inventory/views/furniture/InventoryFurnitureView.tsx similarity index 68% rename from src/components/inventory/views/InventoryFurnitureView.tsx rename to src/components/inventory/views/furniture/InventoryFurnitureView.tsx index 8833d2fd..01d364c5 100644 --- a/src/components/inventory/views/InventoryFurnitureView.tsx +++ b/src/components/inventory/views/furniture/InventoryFurnitureView.tsx @@ -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 = props => { const { roomSession = null, roomPreviewer = null } = props; + const [ isVisible, setIsVisible ] = useState(false); const [ filteredGroupItems, setFilteredGroupItems ] = useState([]); - 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 = 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 ; - 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 ; - } - return ( diff --git a/src/components/inventory/views/InventoryTradeView.tsx b/src/components/inventory/views/furniture/InventoryTradeView.tsx similarity index 98% rename from src/components/inventory/views/InventoryTradeView.tsx rename to src/components/inventory/views/furniture/InventoryTradeView.tsx index a43bfbe8..f9ce0e62 100644 --- a/src/components/inventory/views/InventoryTradeView.tsx +++ b/src/components/inventory/views/furniture/InventoryTradeView.tsx @@ -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 diff --git a/src/components/inventory/views/pet/InventoryPetItemView.tsx b/src/components/inventory/views/pet/InventoryPetItemView.tsx new file mode 100644 index 00000000..194b1a2b --- /dev/null +++ b/src/components/inventory/views/pet/InventoryPetItemView.tsx @@ -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 ( + + + { children } + + ); +} diff --git a/src/components/inventory/views/InventoryPetView.tsx b/src/components/inventory/views/pet/InventoryPetView.tsx similarity index 53% rename from src/components/inventory/views/InventoryPetView.tsx rename to src/components/inventory/views/pet/InventoryPetView.tsx index 5d9727f1..e8aadc79 100644 --- a/src/components/inventory/views/InventoryPetView.tsx +++ b/src/components/inventory/views/pet/InventoryPetView.tsx @@ -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 = 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 = props => roomPreviewer.addPetIntoRoom(petData.figureString); }, [ roomPreviewer, selectedPet ]); - if(!petItems || !petItems.length) return ; - - 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 ( - - - - ); - } + return () => deactivate(id); + }, [ isVisible, activate, deactivate ]); + + useEffect(() => + { + setIsVisible(true); + + return () => setIsVisible(false); + }, []); + + if(!petItems || !petItems.length) return ; return ( diff --git a/src/components/navigator/views/search/NavigatorSearchView.tsx b/src/components/navigator/views/search/NavigatorSearchView.tsx index c779c07a..2109a985 100644 --- a/src/components/navigator/views/search/NavigatorSearchView.tsx +++ b/src/components/navigator/views/search/NavigatorSearchView.tsx @@ -38,7 +38,7 @@ export const NavigatorSearchView: FC = props => useEffect(() => { - if(!searchResult) return null; + if(!searchResult) return; const split = searchResult.data.split(':'); diff --git a/src/hooks/inventory/useInventoryBadges.ts b/src/hooks/inventory/useInventoryBadges.ts index 70d59d14..6a349c5c 100644 --- a/src/hooks/inventory/useInventoryBadges.ts +++ b/src/hooks/inventory/useInventoryBadges.ts @@ -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([]); const [ badgeIds, setBadgeIds ] = useState([]); const [ activeBadgeCodes, setActiveBadgeCodes ] = useState([]); const [ selectedBadgeCode, setSelectedBadgeCode ] = useState(null); + const { isVisible = false, activate = null, deactivate = null } = useSharedVisibility(); + const { isUnseen = null, resetCategory = null } = useInventoryUnseenTracker(); const maxBadgeCount = GetConfiguration('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); diff --git a/src/hooks/inventory/useInventoryBots.ts b/src/hooks/inventory/useInventoryBots.ts index 2f13947a..86d299e2 100644 --- a/src/hooks/inventory/useInventoryBots.ts +++ b/src/hooks/inventory/useInventoryBots.ts @@ -8,13 +8,11 @@ import { useSharedVisibility } from '../useSharedVisibility'; const useInventoryBotsState = () => { - const [ isVisible, setIsVisible ] = useState(false); const [ needsUpdate, setNeedsUpdate ] = useState(true); const [ botItems, setBotItems ] = useState([]); const [ selectedBot, setSelectedBot ] = useState(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); diff --git a/src/hooks/inventory/useInventoryFurni.ts b/src/hooks/inventory/useInventoryFurni.ts index 471803aa..674ed136 100644 --- a/src/hooks/inventory/useInventoryFurni.ts +++ b/src/hooks/inventory/useInventoryFurni.ts @@ -11,18 +11,11 @@ let furniMsgFragments: Map[] = null; const useInventoryFurniState = () => { - const [ isVisible, setIsVisible ] = useState(false); const [ needsUpdate, setNeedsUpdate ] = useState(true); const [ groupItems, setGroupItems ] = useState([]); const [ selectedItem, setSelectedItem ] = useState(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); diff --git a/src/hooks/inventory/useInventoryPets.ts b/src/hooks/inventory/useInventoryPets.ts index bbd3506a..f6e71f47 100644 --- a/src/hooks/inventory/useInventoryPets.ts +++ b/src/hooks/inventory/useInventoryPets.ts @@ -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[] = null; const useInventoryPetsState = () => { - const [ isVisible, setIsVisible ] = useState(false); const [ needsUpdate, setNeedsUpdate ] = useState(true); const [ petItems, setPetItems ] = useState([]); const [ selectedPet, setSelectedPet ] = useState(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); diff --git a/src/hooks/inventory/useInventoryUnseenTracker.ts b/src/hooks/inventory/useInventoryUnseenTracker.ts index 86ac95eb..939a21a5 100644 --- a/src/hooks/inventory/useInventoryUnseenTracker.ts +++ b/src/hooks/inventory/useInventoryUnseenTracker.ts @@ -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);