From 1abadf1b551a2dd79523986c7cbd038a49451525 Mon Sep 17 00:00:00 2001 From: Bill Date: Sun, 3 Apr 2022 20:27:30 -0400 Subject: [PATCH] Start updates --- .../common => api/hc-center}/ClubStatus.ts | 0 src/api/hc-center/GetClubBadge.ts | 11 ++ src/api/hc-center/index.ts | 2 + src/api/index.ts | 2 + .../purse/common => api/purse}/IPurse.ts | 0 .../purse/common => api/purse}/Purse.ts | 2 +- src/api/purse/index.ts | 2 + .../catalog/CatalogMessageHandler.tsx | 21 +-- .../catalog/common/ICatalogOptions.ts | 2 - .../page/layout/CatalogLayoutVipBuyView.tsx | 25 ++- ...atalogLayoutMarketplacePublicItemsView.tsx | 10 +- .../vip-gifts/CatalogLayoutVipGiftsView.tsx | 8 +- .../widgets/CatalogPurchaseWidgetView.tsx | 8 +- src/components/hc-center/HcCenterView.tsx | 168 ++++++------------ .../hc-center/common/BadgeResolver.ts | 23 --- src/components/purse/PurseView.tsx | 117 +----------- src/components/purse/common/CurrencyHelper.ts | 17 -- src/hooks/index.ts | 1 + src/hooks/purse/index.ts | 1 + src/hooks/purse/usePurse.ts | 134 ++++++++++++++ 20 files changed, 241 insertions(+), 313 deletions(-) rename src/{components/hc-center/common => api/hc-center}/ClubStatus.ts (100%) create mode 100644 src/api/hc-center/GetClubBadge.ts create mode 100644 src/api/hc-center/index.ts rename src/{components/purse/common => api/purse}/IPurse.ts (100%) rename src/{components/purse/common => api/purse}/Purse.ts (98%) create mode 100644 src/api/purse/index.ts delete mode 100644 src/components/hc-center/common/BadgeResolver.ts delete mode 100644 src/components/purse/common/CurrencyHelper.ts create mode 100644 src/hooks/purse/index.ts create mode 100644 src/hooks/purse/usePurse.ts diff --git a/src/components/hc-center/common/ClubStatus.ts b/src/api/hc-center/ClubStatus.ts similarity index 100% rename from src/components/hc-center/common/ClubStatus.ts rename to src/api/hc-center/ClubStatus.ts diff --git a/src/api/hc-center/GetClubBadge.ts b/src/api/hc-center/GetClubBadge.ts new file mode 100644 index 00000000..6b779e0f --- /dev/null +++ b/src/api/hc-center/GetClubBadge.ts @@ -0,0 +1,11 @@ +const DEFAULT_BADGE: string = 'HC1'; +const BADGES: string[] = [ 'ACH_VipHC1', 'ACH_VipHC2', 'ACH_VipHC3', 'ACH_VipHC4', 'ACH_VipHC5', 'HC1', 'HC2', 'HC3', 'HC4', 'HC5' ]; + +export const GetClubBadge = (badgeCodes: string[]) => +{ + let badgeCode: string = null; + + BADGES.forEach(badge => ((badgeCodes.indexOf(badge) > -1) && (badgeCode = badge))); + + return (badgeCode || DEFAULT_BADGE); +} diff --git a/src/api/hc-center/index.ts b/src/api/hc-center/index.ts new file mode 100644 index 00000000..cee8f692 --- /dev/null +++ b/src/api/hc-center/index.ts @@ -0,0 +1,2 @@ +export * from './ClubStatus'; +export * from './GetClubBadge'; diff --git a/src/api/index.ts b/src/api/index.ts index 92da5d94..d3473996 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -6,6 +6,7 @@ export * from './friends'; export * from './GetRendererVersion'; export * from './GetUIVersion'; export * from './groups'; +export * from './hc-center'; export * from './inventory'; export * from './inventory/unseen'; export * from './navigator'; @@ -19,6 +20,7 @@ export * from './nitro/room/widgets/handlers'; export * from './nitro/room/widgets/messages'; export * from './nitro/session'; export * from './notification'; +export * from './purse'; export * from './user'; export * from './utils'; export * from './wired'; diff --git a/src/components/purse/common/IPurse.ts b/src/api/purse/IPurse.ts similarity index 100% rename from src/components/purse/common/IPurse.ts rename to src/api/purse/IPurse.ts diff --git a/src/components/purse/common/Purse.ts b/src/api/purse/Purse.ts similarity index 98% rename from src/components/purse/common/Purse.ts rename to src/api/purse/Purse.ts index f9ea045a..a0a54b4c 100644 --- a/src/components/purse/common/Purse.ts +++ b/src/api/purse/Purse.ts @@ -1,5 +1,5 @@ import { HabboClubLevelEnum } from '@nitrots/nitro-renderer'; -import { GetNitroInstance } from '../../../api'; +import { GetNitroInstance } from '..'; import { IPurse } from './IPurse'; export class Purse implements IPurse diff --git a/src/api/purse/index.ts b/src/api/purse/index.ts new file mode 100644 index 00000000..ed344804 --- /dev/null +++ b/src/api/purse/index.ts @@ -0,0 +1,2 @@ +export * from './IPurse'; +export * from './Purse'; diff --git a/src/components/catalog/CatalogMessageHandler.tsx b/src/components/catalog/CatalogMessageHandler.tsx index dfbf89d2..e01cbb4a 100644 --- a/src/components/catalog/CatalogMessageHandler.tsx +++ b/src/components/catalog/CatalogMessageHandler.tsx @@ -1,4 +1,4 @@ -import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, ClubGiftInfoEvent, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, SellablePetPalettesMessageEvent, UserSubscriptionEvent } from '@nitrots/nitro-renderer'; +import { ApproveNameMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, ClubGiftInfoEvent, GiftReceiverNotFoundEvent, GiftWrappingConfigurationEvent, HabboClubOffersMessageEvent, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, SellablePetPalettesMessageEvent } from '@nitrots/nitro-renderer'; import { GuildMembershipsMessageEvent } from '@nitrots/nitro-renderer/src/nitro/communication/messages/incoming/user/GuildMembershipsMessageEvent'; import { FC, useCallback } from 'react'; import { GetFurnitureData, GetProductDataForLocalization, LocalizeText, NotificationAlertType, NotificationUtilities, ProductTypeEnum } from '../../api'; @@ -15,7 +15,6 @@ import { IPurchasableOffer } from './common/IPurchasableOffer'; import { Offer } from './common/Offer'; import { PageLocalization } from './common/PageLocalization'; import { Product } from './common/Product'; -import { SubscriptionInfo } from './common/SubscriptionInfo'; export const CatalogMessageHandler: FC<{}> = props => { @@ -227,23 +226,6 @@ export const CatalogMessageHandler: FC<{}> = props => }); }, [ setCatalogOptions ]); - const onUserSubscriptionEvent = useCallback((event: UserSubscriptionEvent) => - { - const parser = event.getParser(); - - setCatalogOptions(prevValue => - { - const subscriptionInfo = new SubscriptionInfo( - Math.max(0, parser.daysToPeriodEnd), - Math.max(0, parser.periodsSubscribedAhead), - parser.isVip, - parser.pastClubDays, - parser.pastVipDays); - - return { ...prevValue, subscriptionInfo }; - }); - }, [ setCatalogOptions ]); - const onGiftWrappingConfigurationEvent = useCallback((event: GiftWrappingConfigurationEvent) => { const parser = event.getParser(); @@ -301,7 +283,6 @@ export const CatalogMessageHandler: FC<{}> = props => UseMessageEventHook(ApproveNameMessageEvent, onApproveNameMessageEvent); UseMessageEventHook(GiftReceiverNotFoundEvent, onGiftReceiverNotFoundEvent); UseMessageEventHook(HabboClubOffersMessageEvent, onHabboClubOffersMessageEvent); - UseMessageEventHook(UserSubscriptionEvent, onUserSubscriptionEvent); UseMessageEventHook(GiftWrappingConfigurationEvent, onGiftWrappingConfigurationEvent); UseMessageEventHook(ClubGiftInfoEvent, onClubGiftInfoEvent); UseMessageEventHook(MarketplaceMakeOfferResult, onMarketplaceMakeOfferResult); diff --git a/src/components/catalog/common/ICatalogOptions.ts b/src/components/catalog/common/ICatalogOptions.ts index 49ed1737..20356947 100644 --- a/src/components/catalog/common/ICatalogOptions.ts +++ b/src/components/catalog/common/ICatalogOptions.ts @@ -1,7 +1,6 @@ import { ClubGiftInfoParser, ClubOfferData, HabboGroupEntryData, MarketplaceConfigurationMessageParser } from '@nitrots/nitro-renderer'; import { CatalogPetPalette } from './CatalogPetPalette'; import { GiftWrappingConfiguration } from './GiftWrappingConfiguration'; -import { SubscriptionInfo } from './SubscriptionInfo'; export interface ICatalogOptions { @@ -9,7 +8,6 @@ export interface ICatalogOptions petPalettes?: CatalogPetPalette[]; clubOffers?: ClubOfferData[]; clubGifts?: ClubGiftInfoParser; - subscriptionInfo?: SubscriptionInfo; giftConfiguration?: GiftWrappingConfiguration; marketplaceConfiguration?: MarketplaceConfigurationMessageParser; } diff --git a/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx b/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx index f32db617..3597e54d 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx @@ -3,9 +3,7 @@ import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { LocalizeText, SendMessageComposer } from '../../../../../api'; import { AutoGrid, Button, Column, Flex, Grid, LayoutCurrencyIcon, LayoutGridItem, LayoutLoadingSpinnerView, Text } from '../../../../../common'; import { CatalogEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent } from '../../../../../events'; -import { UseUiEvent } from '../../../../../hooks'; -import { GetCurrencyAmount } from '../../../../purse/common/CurrencyHelper'; -import { GLOBAL_PURSE } from '../../../../purse/PurseView'; +import { usePurse, UseUiEvent } from '../../../../../hooks'; import { useCatalogContext } from '../../../CatalogContext'; import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState'; import { CatalogLayoutProps } from './CatalogLayout.types'; @@ -15,7 +13,8 @@ export const CatalogLayoutVipBuyView: FC = props => const [ pendingOffer, setPendingOffer ] = useState(null); const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE); const { currentPage = null, catalogOptions = null } = useCatalogContext(); - const { clubOffers = null, subscriptionInfo = null } = catalogOptions; + const { purse = null, getCurrencyAmount = null } = usePurse(); + const { clubOffers = null } = catalogOptions; const onCatalogEvent = useCallback((event: CatalogEvent) => { @@ -54,8 +53,6 @@ export const CatalogLayoutVipBuyView: FC = props => const getPurchaseHeader = useCallback(() => { - const purse = GLOBAL_PURSE; - if(!purse) return ''; const extensionOrSubscription = (purse.clubDays > 0 || purse.clubPeriods > 0) ? 'extension.' : 'subscription.'; @@ -64,7 +61,7 @@ export const CatalogLayoutVipBuyView: FC = props => const locale = LocalizeText('catalog.vip.buy.confirm.' + extensionOrSubscription + daysOrMonths); return locale.replace('%NUM_' + daysOrMonths.toUpperCase() + '%', daysOrMonthsText.toString()); - }, [ pendingOffer ]); + }, [ pendingOffer, purse ]); const getPurchaseValidUntil = useCallback(() => { @@ -79,14 +76,12 @@ export const CatalogLayoutVipBuyView: FC = props => const getSubscriptionDetails = useMemo(() => { - if(!subscriptionInfo) return ''; - - const clubDays = subscriptionInfo.clubDays; - const clubPeriods = subscriptionInfo.clubPeriods; + const clubDays = purse.clubDays; + const clubPeriods = purse.clubPeriods; const totalDays = (clubPeriods * 31) + clubDays; return LocalizeText('catalog.vip.extend.info', [ 'days' ], [ totalDays.toString() ]); - }, [ subscriptionInfo ]); + }, [ purse ]); const purchaseSubscription = useCallback(() => { @@ -106,12 +101,12 @@ export const CatalogLayoutVipBuyView: FC = props => { if(!pendingOffer) return null; - if(pendingOffer.priceCredits > GetCurrencyAmount(-1)) + if(pendingOffer.priceCredits > getCurrencyAmount(-1)) { return ; } - if(pendingOffer.priceActivityPoints > GetCurrencyAmount(pendingOffer.priceActivityPointsType)) + if(pendingOffer.priceActivityPoints > getCurrencyAmount(pendingOffer.priceActivityPointsType)) { return ; } @@ -128,7 +123,7 @@ export const CatalogLayoutVipBuyView: FC = props => default: return ; } - }, [ pendingOffer, purchaseState, purchaseSubscription ]); + }, [ pendingOffer, purchaseState, purchaseSubscription, getCurrencyAmount ]); useEffect(() => { diff --git a/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx b/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx index ae6b5fff..2ef982e9 100644 --- a/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx +++ b/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx @@ -2,8 +2,7 @@ import { BuyMarketplaceOfferMessageComposer, GetMarketplaceOffersMessageComposer import { FC, useCallback, useMemo, useState } from 'react'; import { LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer } from '../../../../../../api'; import { Button, ButtonGroup, Column, Text } from '../../../../../../common'; -import { UseMessageEventHook } from '../../../../../../hooks'; -import { GetCurrencyAmount } from '../../../../../purse/common/CurrencyHelper'; +import { UseMessageEventHook, usePurse } from '../../../../../../hooks'; import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView'; import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView'; @@ -25,6 +24,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC()); const [ lastSearch, setLastSearch ] = useState({ minPrice: -1, maxPrice: -1, query: '', type: 3 }); + const { getCurrencyAmount = null } = usePurse(); const requestOffers = useCallback((options: IMarketplaceSearchOptions) => { @@ -48,18 +48,20 @@ export const CatalogLayoutMarketplacePublicItemsView: FC { - if(offerData.price > GetCurrencyAmount(-1)) + if(offerData.price > getCurrencyAmount(-1)) { NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.notenough.credits.description'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.alert.notenough.title')); return; } + const offerId = offerData.offerId; + NotificationUtilities.confirm(LocalizeText('catalog.marketplace.confirm_header'), () => { SendMessageComposer(new BuyMarketplaceOfferMessageComposer(offerId)); }, null, null, null, LocalizeText('catalog.marketplace.confirm_title')); - },[]); + }, [ getCurrencyAmount ]); const onMarketPlaceOffersEvent = useCallback( (event: MarketPlaceOffersEvent) => { diff --git a/src/components/catalog/views/page/layout/vip-gifts/CatalogLayoutVipGiftsView.tsx b/src/components/catalog/views/page/layout/vip-gifts/CatalogLayoutVipGiftsView.tsx index 4c90be62..3b760d27 100644 --- a/src/components/catalog/views/page/layout/vip-gifts/CatalogLayoutVipGiftsView.tsx +++ b/src/components/catalog/views/page/layout/vip-gifts/CatalogLayoutVipGiftsView.tsx @@ -2,14 +2,16 @@ import { SelectClubGiftComposer } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; import { LocalizeText, NotificationUtilities, SendMessageComposer } from '../../../../../../api'; import { AutoGrid, Text } from '../../../../../../common'; +import { usePurse } from '../../../../../../hooks'; import { useCatalogContext } from '../../../../CatalogContext'; import { CatalogLayoutProps } from '../CatalogLayout.types'; import { VipGiftItem } from './VipGiftItemView'; export const CatalogLayoutVipGiftsView: FC = props => { + const { purse = null } = usePurse(); const { catalogOptions = null, setCatalogOptions = null } = useCatalogContext(); - const { clubGifts = null, subscriptionInfo = null } = catalogOptions; + const { clubGifts = null } = catalogOptions; const giftsAvailable = useCallback(() => { @@ -19,10 +21,10 @@ export const CatalogLayoutVipGiftsView: FC = props => if(clubGifts.daysUntilNextGift > 0) return LocalizeText('catalog.club_gift.days_until_next', [ 'days' ], [ clubGifts.daysUntilNextGift.toString() ]); - if(subscriptionInfo.isVip) return LocalizeText('catalog.club_gift.not_available'); + if(purse.isVip) return LocalizeText('catalog.club_gift.not_available'); return LocalizeText('catalog.club_gift.no_club'); - }, [ clubGifts, subscriptionInfo ]); + }, [ clubGifts, purse ]); const selectGift = useCallback((localizationId: string) => { diff --git a/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx index 7ed446aa..7a874acc 100644 --- a/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx @@ -3,8 +3,7 @@ import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { CreateLinkEvent, GetClubMemberLevel, LocalizeText, SendMessageComposer } from '../../../../../api'; import { Button, LayoutLoadingSpinnerView } from '../../../../../common'; import { CatalogEvent, CatalogInitGiftEvent, CatalogInitPurchaseEvent, CatalogPurchasedEvent, CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent, CatalogWidgetEvent } from '../../../../../events'; -import { DispatchUiEvent, UseUiEvent } from '../../../../../hooks'; -import { GetCurrencyAmount } from '../../../../purse/common/CurrencyHelper'; +import { DispatchUiEvent, usePurse, UseUiEvent } from '../../../../../hooks'; import { useCatalogContext } from '../../../CatalogContext'; import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState'; import { Offer } from '../../../common/Offer'; @@ -21,6 +20,7 @@ export const CatalogPurchaseWidgetView: FC = pro const [ purchaseWillBeGift, setPurchaseWillBeGift ] = useState(false); const [ purchaseState, setPurchaseState ] = useState(CatalogPurchaseState.NONE); const { currentOffer = null, currentPage = null, purchaseOptions = null, setPurchaseOptions = null } = useCatalogContext(); + const { getCurrencyAmount = null } = usePurse(); const onCatalogInitPurchaseEvent = useCallback((event: CatalogInitPurchaseEvent) => { @@ -148,9 +148,9 @@ export const CatalogPurchaseWidgetView: FC = pro if(isLimitedSoldOut) return ; - if(priceCredits > GetCurrencyAmount(-1)) return ; + if(priceCredits > getCurrencyAmount(-1)) return ; - if(pricePoints > GetCurrencyAmount(currentOffer.activityPointType)) return ; + if(pricePoints > getCurrencyAmount(currentOffer.activityPointType)) return ; switch(purchaseState) { diff --git a/src/components/hc-center/HcCenterView.tsx b/src/components/hc-center/HcCenterView.tsx index 94f70260..2d4ea5b6 100644 --- a/src/components/hc-center/HcCenterView.tsx +++ b/src/components/hc-center/HcCenterView.tsx @@ -1,42 +1,31 @@ -import { BadgesEvent, ClubGiftInfoEvent, FriendlyTime, GetClubGiftInfo, ILinkEventTracker, RequestBadgesComposer, ScrGetKickbackInfoMessageComposer, ScrKickbackData, ScrSendKickbackInfoMessageEvent, UserSubscriptionEvent } from '@nitrots/nitro-renderer'; +import { ClubGiftInfoEvent, FriendlyTime, GetClubGiftInfo, ILinkEventTracker, ScrGetKickbackInfoMessageComposer, ScrKickbackData, ScrSendKickbackInfoMessageEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useState } from 'react'; import { OverlayTrigger, Popover } from 'react-bootstrap'; -import { AddEventLinkTracker, CreateLinkEvent, GetConfiguration, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api'; +import { AddEventLinkTracker, ClubStatus, CreateLinkEvent, GetClubBadge, GetConfiguration, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api'; import { Base, Button, Column, Flex, LayoutAvatarImageView, LayoutBadgeImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common'; -import { UseMessageEventHook, useSessionInfo } from '../../hooks'; -import { BadgeResolver } from './common/BadgeResolver'; -import { ClubStatus } from './common/ClubStatus'; +import { useInventoryBadges, UseMessageEventHook, usePurse, useSessionInfo } from '../../hooks'; export const HcCenterView: FC<{}> = props => { const [ isVisible, setIsVisible ] = useState(false); const [ kickbackData, setKickbackData ] = useState(null); - const [ clubDays, setClubDays ] = useState(0); - const [ pastClubDays, setPastClubDays ] = useState(0); - const [ clubPeriods, setPastClubPeriods ] = useState(0); - const [ minsTillExpire, setMinsTillExpire ] = useState(0); - const [ clubStatus, setClubStatus ] = useState(ClubStatus.NONE); const [ unclaimedGifts, setUnclaimedGifts ] = useState(0); - const [ badgeCode, setBadgeCode ] = useState(BadgeResolver.default_badge); + const [ badgeCode, setBadgeCode ] = useState(null); const { userFigure = null } = useSessionInfo(); + const { purse = null, clubStatus = null } = usePurse(); + const { badgeCodes = [], activate = null, deactivate = null } = useInventoryBadges(); const getClubText = () => { - const totalDays = ((clubPeriods * 31) + clubDays); - const minutesUntilExpiration = minsTillExpire; - - if(clubStatus !== ClubStatus.ACTIVE) + if(purse.clubDays <= 0) return LocalizeText('purse.clubdays.zero.amount.text'); + + if((purse.minutesUntilExpiration > -1) && (purse.minutesUntilExpiration < (60 * 24))) { - return LocalizeText('purse.clubdays.zero.amount.text'); + return FriendlyTime.shortFormat(purse.minutesUntilExpiration * 60); } - if((minutesUntilExpiration > -1) && (minutesUntilExpiration < (60 * 24))) - { - return FriendlyTime.shortFormat(minutesUntilExpiration * 60); - } - - return FriendlyTime.shortFormat(totalDays * 86400); + return FriendlyTime.shortFormat(((purse.clubPeriods * 31) + purse.clubDays) * 86400); } const getInfoText = () => @@ -52,16 +41,8 @@ export const HcCenterView: FC<{}> = props => } } - const getHcPaydayTime = () => - { - if(kickbackData.timeUntilPayday < 60) return LocalizeText('hccenter.special.time.soon'); - return FriendlyTime.shortFormat(kickbackData.timeUntilPayday * 60); - } - - const getHcPaydayAmount = () => - { - return LocalizeText('hccenter.special.sum', [ 'credits' ], [ (kickbackData.creditRewardForStreakBonus + kickbackData.creditRewardForMonthlySpent).toString() ]); - } + const getHcPaydayTime = () => (kickbackData.timeUntilPayday < 60) ? LocalizeText('hccenter.special.time.soon') : FriendlyTime.shortFormat(kickbackData.timeUntilPayday * 60); + const getHcPaydayAmount = () => LocalizeText('hccenter.special.sum', [ 'credits' ], [ (kickbackData.creditRewardForStreakBonus + kickbackData.creditRewardForMonthlySpent).toString() ]); const onClubGiftInfoEvent = useCallback((event: ClubGiftInfoEvent) => { @@ -81,87 +62,56 @@ export const HcCenterView: FC<{}> = props => UseMessageEventHook(ScrSendKickbackInfoMessageEvent, onScrSendKickbackInfo); - const onBadges = useCallback((event: BadgesEvent) => - { - const parser = event.getParser(); - - setBadgeCode(BadgeResolver.getClubBadge(parser.getAllBadgeCodes())); - }, []); - - UseMessageEventHook(BadgesEvent, onBadges); - - const onUserSubscriptionEvent = useCallback((event: UserSubscriptionEvent) => - { - const parser = event.getParser(); - - const productName = parser.productName; - - if((productName !== 'club_habbo') && (productName !== 'habbo_club')) return; - - setClubDays(Math.max(0, parser.daysToPeriodEnd)); - setPastClubPeriods(Math.max(0, parser.periodsSubscribedAhead)); - setPastClubDays(Math.max(0, parser.pastClubDays)); - setMinsTillExpire(Math.max(0, parser.minutesUntilExpiration)); - }, []); - - UseMessageEventHook(UserSubscriptionEvent, onUserSubscriptionEvent); - - const linkReceived = useCallback((url: string) => - { - const parts = url.split('/'); - - if(parts.length < 2) return; - - switch(parts[1]) - { - case 'open': - if(parts.length > 2) - { - switch(parts[2]) - { - case 'hccenter': - setIsVisible(true); - break; - } - } - return; - } - }, []); - useEffect(() => { const linkTracker: ILinkEventTracker = { - linkReceived, + linkReceived: (url: string) => + { + const parts = url.split('/'); + + if(parts.length < 2) return; + + switch(parts[1]) + { + case 'open': + if(parts.length > 2) + { + switch(parts[2]) + { + case 'hccenter': + setIsVisible(true); + break; + } + } + return; + } + }, eventUrlPrefix: 'habboUI/' }; AddEventLinkTracker(linkTracker); return () => RemoveLinkEventTracker(linkTracker); - }, [ linkReceived ]); + }, []); useEffect(() => { - if(clubDays > 0) - { - setClubStatus(ClubStatus.ACTIVE); + setBadgeCode(GetClubBadge(badgeCodes)); + }, [ badgeCodes ]); - return; - } + useEffect(() => + { + if(!isVisible) return; - if(pastClubDays > 0) - { - setClubStatus(ClubStatus.EXPIRED); + const id = activate(); - return; - } - }, [ clubDays, pastClubDays ]); + return () => deactivate(id); + }, [ isVisible, activate, deactivate ]); useEffect(() => { SendMessageComposer(new GetClubGiftInfo()); SendMessageComposer(new ScrGetKickbackInfoMessageComposer()); - SendMessageComposer(new RequestBadgesComposer()); }, []); if(!isVisible) return null; @@ -176,10 +126,10 @@ export const HcCenterView: FC<{}> = props =>
{LocalizeText('hccenter.breakdown.total', [ 'credits', 'actual' ], [ getHcPaydayAmount(), ((((kickbackData.kickbackPercentage * kickbackData.totalCreditsSpent) + kickbackData.creditRewardForStreakBonus) * 100) / 100).toString() ])}
-
+
{ CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage']) - }}>{ + } }>{ LocalizeText('hccenter.special.infolink')}
@@ -193,10 +143,7 @@ export const HcCenterView: FC<{}> = props =>
- @@ -207,10 +154,10 @@ export const HcCenterView: FC<{}> = props => - + { LocalizeText('hccenter.status.' + clubStatus) } - + { GetConfiguration('hc.center')['payday.info'] && @@ -218,10 +165,7 @@ export const HcCenterView: FC<{}> = props =>

{LocalizeText('hccenter.special.title')}

{LocalizeText('hccenter.special.info')}
-
- { - CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage']) - }}>{LocalizeText('hccenter.special.infolink')}
+
CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage']) }>{LocalizeText('hccenter.special.infolink')}
{LocalizeText('hccenter.special.time.title')}
@@ -234,7 +178,7 @@ export const HcCenterView: FC<{}> = props =>
{LocalizeText('hccenter.special.amount.title')}
{getHcPaydayAmount()}
- +
{LocalizeText('hccenter.breakdown.infolink')}
@@ -249,22 +193,22 @@ export const HcCenterView: FC<{}> = props =>

{LocalizeText('hccenter.gift.title')}

-
0 ? LocalizeText('hccenter.unclaimedgifts', [ 'unclaimedgifts' ], [ unclaimedGifts.toString() ]) : LocalizeText('hccenter.gift.info') }}>
+
0 ? LocalizeText('hccenter.unclaimedgifts', [ 'unclaimedgifts' ], [ unclaimedGifts.toString() ]) : LocalizeText('hccenter.gift.info') } }>
- + } }>{LocalizeText(clubStatus === ClubStatus.ACTIVE ? 'hccenter.btn.gifts.redeem' : 'hccenter.btn.gifts.view')}
} {GetConfiguration('hc.center')['benefits.info'] &&
{LocalizeText('hccenter.general.title')}
-
- + } }>{LocalizeText('hccenter.general.infolink')}
} diff --git a/src/components/hc-center/common/BadgeResolver.ts b/src/components/hc-center/common/BadgeResolver.ts deleted file mode 100644 index e334b6e8..00000000 --- a/src/components/hc-center/common/BadgeResolver.ts +++ /dev/null @@ -1,23 +0,0 @@ - -export class BadgeResolver -{ - public static default_badge: string = 'HC1'; - public static badges: string[] = [ 'ACH_VipHC1', 'ACH_VipHC2', 'ACH_VipHC3', 'ACH_VipHC4', 'ACH_VipHC5', 'HC1', 'HC2', 'HC3', 'HC4', 'HC5' ]; - - - public static getClubBadge(k: string[]): string - { - var badgeCode: string = null; - - this.badges.forEach(badge => - { - if (k.indexOf(badge) > -1) - { - badgeCode = badge; - } - }); - - return badgeCode || this.default_badge; - } - -} diff --git a/src/components/purse/PurseView.tsx b/src/components/purse/PurseView.tsx index 7004096c..667c5841 100644 --- a/src/components/purse/PurseView.tsx +++ b/src/components/purse/PurseView.tsx @@ -1,21 +1,15 @@ -import { ActivityPointNotificationMessageEvent, FriendlyTime, HabboClubLevelEnum, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserSubscriptionParser } from '@nitrots/nitro-renderer'; -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { CreateLinkEvent, GetConfiguration, LocalizeText, PlaySound, SendMessageComposer, SoundNames } from '../../api'; +import { FriendlyTime, HabboClubLevelEnum } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useMemo } from 'react'; +import { CreateLinkEvent, GetConfiguration, LocalizeText } from '../../api'; import { Column, Flex, Grid, LayoutCurrencyIcon, Text } from '../../common'; -import { UseMessageEventHook } from '../../hooks'; -import { IPurse } from './common/IPurse'; -import { Purse } from './common/Purse'; +import { usePurse } from '../../hooks'; import { PurseContextProvider } from './PurseContext'; import { CurrencyView } from './views/CurrencyView'; import { SeasonalView } from './views/SeasonalView'; -export let GLOBAL_PURSE: IPurse = null; - export const PurseView: FC<{}> = props => { - const [ purse, setPurse ] = useState(new Purse()); - - const hcDisabled = useMemo(() => GetConfiguration('hc.disabled', false), []); + const { purse = null, hcDisabled = false } = usePurse(); const displayedCurrencies = useMemo(() => GetConfiguration('system.currency.types', []), []); const currencyDisplayNumberShort = useMemo(() => GetConfiguration('currency.display.number.short', false), []); @@ -65,107 +59,6 @@ export const PurseView: FC<{}> = props => return elements; }, [ purse, displayedCurrencies, currencyDisplayNumberShort ]); - const onUserCreditsEvent = useCallback((event: UserCreditsEvent) => - { - const parser = event.getParser(); - - setPurse(prevValue => - { - const newValue = Purse.from(prevValue as Purse); - - newValue.credits = parseFloat(parser.credits); - - if(prevValue.credits !== newValue.credits) PlaySound(SoundNames.CREDITS); - - return newValue; - }); - }, []); - - UseMessageEventHook(UserCreditsEvent, onUserCreditsEvent); - - const onUserCurrencyEvent = useCallback((event: UserCurrencyEvent) => - { - const parser = event.getParser(); - - setPurse(prevValue => - { - const newValue = Purse.from(prevValue as Purse); - - newValue.activityPoints = parser.currencies; - - return newValue; - }); - }, []); - - UseMessageEventHook(UserCurrencyEvent, onUserCurrencyEvent); - - const onActivityPointNotificationMessageEvent = useCallback((event: ActivityPointNotificationMessageEvent) => - { - const parser = event.getParser(); - - setPurse(prevValue => - { - const newValue = Purse.from(prevValue as Purse); - - newValue.activityPoints = new Map(newValue.activityPoints); - - newValue.activityPoints.set(parser.type, parser.amount); - - if(parser.type === 0) PlaySound(SoundNames.DUCKETS) - - return newValue; - }); - }, []); - - UseMessageEventHook(ActivityPointNotificationMessageEvent, onActivityPointNotificationMessageEvent); - - const onUserSubscriptionEvent = useCallback((event: UserSubscriptionEvent) => - { - const parser = event.getParser(); - const productName = parser.productName; - - if((productName !== 'club_habbo') && (productName !== 'habbo_club')) return; - - setPurse(prevValue => - { - const newValue = Purse.from(prevValue as Purse); - - newValue.clubDays = Math.max(0, parser.daysToPeriodEnd); - newValue.clubPeriods = Math.max(0, parser.periodsSubscribedAhead); - newValue.isVip = parser.isVip; - newValue.pastClubDays = parser.pastClubDays; - newValue.pastVipDays = parser.pastVipDays; - newValue.isExpiring = ((parser.responseType === UserSubscriptionParser.RESPONSE_TYPE_DISCOUNT_AVAILABLE) ? true : false); - newValue.minutesUntilExpiration = parser.minutesUntilExpiration; - newValue.minutesSinceLastModified = parser.minutesSinceLastModified; - - return newValue; - }); - }, []); - - UseMessageEventHook(UserSubscriptionEvent, onUserSubscriptionEvent); - - useEffect(() => - { - GLOBAL_PURSE = purse; - }, [ purse ]); - - useEffect(() => - { - if(hcDisabled) return; - - SendMessageComposer(new UserSubscriptionComposer('habbo_club')); - - const interval = setInterval(() => SendMessageComposer(new UserSubscriptionComposer('habbo_club')), 50000); - - return () => clearInterval(interval); - }, [ hcDisabled ]); - - useEffect(() => - { - SendMessageComposer(new UserCurrencyComposer()); - }, []); - if(!purse) return null; return ( diff --git a/src/components/purse/common/CurrencyHelper.ts b/src/components/purse/common/CurrencyHelper.ts deleted file mode 100644 index f9a6c3dd..00000000 --- a/src/components/purse/common/CurrencyHelper.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { GLOBAL_PURSE } from '../PurseView'; - -export function GetCurrencyAmount(type: number): number -{ - const purse = GLOBAL_PURSE; - - if(type === -1) return purse.credits; - - for(const [ key, value ] of purse.activityPoints.entries()) - { - if(key !== type) continue; - - return value; - } - - return 0; -} diff --git a/src/hooks/index.ts b/src/hooks/index.ts index f072b824..a78a216d 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -7,6 +7,7 @@ export * from './friends'; export * from './inventory'; export * from './messages'; export * from './navigator'; +export * from './purse'; export * from './session'; export * from './UseMountEffect'; export * from './useSharedVisibility'; diff --git a/src/hooks/purse/index.ts b/src/hooks/purse/index.ts new file mode 100644 index 00000000..d9d1ff70 --- /dev/null +++ b/src/hooks/purse/index.ts @@ -0,0 +1 @@ +export * from './usePurse'; diff --git a/src/hooks/purse/usePurse.ts b/src/hooks/purse/usePurse.ts new file mode 100644 index 00000000..42f70e94 --- /dev/null +++ b/src/hooks/purse/usePurse.ts @@ -0,0 +1,134 @@ +import { ActivityPointNotificationMessageEvent, UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserSubscriptionComposer, UserSubscriptionEvent, UserSubscriptionParser } from '@nitrots/nitro-renderer'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useBetween } from 'use-between'; +import { CloneObject, ClubStatus, GetConfiguration, IPurse, PlaySound, Purse, SendMessageComposer, SoundNames } from '../../api'; +import { UseMessageEventHook } from '../messages'; + +const usePurseState = () => +{ + const [ purse, setPurse ] = useState(new Purse()); + const hcDisabled = useMemo(() => GetConfiguration('hc.disabled', false), []); + + const clubStatus = useMemo(() => + { + if(hcDisabled || (purse.clubDays > 0)) return ClubStatus.ACTIVE; + + if((purse.pastVipDays > 0) || (purse.pastVipDays > 0)) return ClubStatus.EXPIRED; + + return ClubStatus.NONE; + }, [ purse, hcDisabled ]); + + const getCurrencyAmount = (type: number) => + { + if(type === -1) return purse.credits; + + for(const [ key, value ] of purse.activityPoints.entries()) + { + if(key !== type) continue; + + return value; + } + + return 0; + } + + const onUserCreditsEvent = useCallback((event: UserCreditsEvent) => + { + const parser = event.getParser(); + + setPurse(prevValue => + { + const newValue = CloneObject(prevValue); + + newValue.credits = parseFloat(parser.credits); + + if(prevValue.credits !== newValue.credits) PlaySound(SoundNames.CREDITS); + + return newValue; + }); + }, []); + + UseMessageEventHook(UserCreditsEvent, onUserCreditsEvent); + + const onUserCurrencyEvent = useCallback((event: UserCurrencyEvent) => + { + const parser = event.getParser(); + + setPurse(prevValue => + { + const newValue = CloneObject(prevValue); + + newValue.activityPoints = parser.currencies; + + return newValue; + }); + }, []); + + UseMessageEventHook(UserCurrencyEvent, onUserCurrencyEvent); + + const onActivityPointNotificationMessageEvent = useCallback((event: ActivityPointNotificationMessageEvent) => + { + const parser = event.getParser(); + + setPurse(prevValue => + { + const newValue = CloneObject(prevValue); + + newValue.activityPoints = new Map(newValue.activityPoints); + + newValue.activityPoints.set(parser.type, parser.amount); + + if(parser.type === 0) PlaySound(SoundNames.DUCKETS) + + return newValue; + }); + }, []); + + UseMessageEventHook(ActivityPointNotificationMessageEvent, onActivityPointNotificationMessageEvent); + + const onUserSubscriptionEvent = useCallback((event: UserSubscriptionEvent) => + { + const parser = event.getParser(); + const productName = parser.productName; + + if((productName !== 'club_habbo') && (productName !== 'habbo_club')) return; + + setPurse(prevValue => + { + const newValue = CloneObject(prevValue); + + newValue.clubDays = Math.max(0, parser.daysToPeriodEnd); + newValue.clubPeriods = Math.max(0, parser.periodsSubscribedAhead); + newValue.isVip = parser.isVip; + newValue.pastClubDays = parser.pastClubDays; + newValue.pastVipDays = parser.pastVipDays; + newValue.isExpiring = ((parser.responseType === UserSubscriptionParser.RESPONSE_TYPE_DISCOUNT_AVAILABLE) ? true : false); + newValue.minutesUntilExpiration = parser.minutesUntilExpiration; + newValue.minutesSinceLastModified = parser.minutesSinceLastModified; + + return newValue; + }); + }, []); + + UseMessageEventHook(UserSubscriptionEvent, onUserSubscriptionEvent); + + useEffect(() => + { + if(hcDisabled) return; + + SendMessageComposer(new UserSubscriptionComposer('habbo_club')); + + const interval = setInterval(() => SendMessageComposer(new UserSubscriptionComposer('habbo_club')), 50000); + + return () => clearInterval(interval); + }, [ hcDisabled ]); + + useEffect(() => + { + SendMessageComposer(new UserCurrencyComposer()); + }, []); + + return { purse, hcDisabled, clubStatus, getCurrencyAmount }; +} + +export const usePurse = () => useBetween(usePurseState);