diff --git a/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx b/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx index 01616a57..ef613c85 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutVipBuyView.tsx @@ -13,9 +13,9 @@ import { CatalogEvent } from '../../../../../events/catalog/CatalogEvent'; import { useUiEvent } from '../../../../../hooks'; import { SendMessageHook } from '../../../../../hooks/messages/message-event'; import { LoadingSpinnerView } from '../../../../../layout/loading-spinner/LoadingSpinnerView'; -import { GetCurrencyAmount } from '../../../../../views/purse/common/CurrencyHelper'; -import { GLOBAL_PURSE } from '../../../../../views/purse/PurseView'; import { CurrencyIcon } from '../../../../../views/shared/currency-icon/CurrencyIcon'; +import { GetCurrencyAmount } from '../../../../purse/common/CurrencyHelper'; +import { GLOBAL_PURSE } from '../../../../purse/PurseView'; import { useCatalogContext } from '../../../CatalogContext'; import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState'; import { CatalogLayoutProps } from './CatalogLayout.types'; diff --git a/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx b/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx index 2ad20abb..4a4f4fb9 100644 --- a/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx +++ b/src/components/catalog/views/page/layout/marketplace/CatalogLayoutMarketplacePublicItemsView.tsx @@ -9,7 +9,7 @@ import { Text } from '../../../../../../common/Text'; import { BatchUpdates, CreateMessageHook, SendMessageHook } from '../../../../../../hooks'; import { NotificationAlertType } from '../../../../../../views/notification-center/common/NotificationAlertType'; import { NotificationUtilities } from '../../../../../../views/notification-center/common/NotificationUtilities'; -import { GetCurrencyAmount } from '../../../../../../views/purse/common/CurrencyHelper'; +import { GetCurrencyAmount } from '../../../../../purse/common/CurrencyHelper'; import { CatalogLayoutProps } from '../CatalogLayout.types'; import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView'; import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView'; diff --git a/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx b/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx index a9d4280a..9b05d88f 100644 --- a/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx +++ b/src/components/catalog/views/page/widgets/CatalogPurchaseWidgetView.tsx @@ -8,7 +8,7 @@ import { CatalogInitPurchaseEvent } from '../../../../../events/catalog/CatalogI import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent'; import { dispatchUiEvent, SendMessageHook, useUiEvent } from '../../../../../hooks'; import { LoadingSpinnerView } from '../../../../../layout'; -import { GetCurrencyAmount } from '../../../../../views/purse/common/CurrencyHelper'; +import { GetCurrencyAmount } from '../../../../purse/common/CurrencyHelper'; import { useCatalogContext } from '../../../CatalogContext'; import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState'; import { Offer } from '../../../common/Offer'; diff --git a/src/components/index.scss b/src/components/index.scss index 2409d2d6..bd580fb0 100644 --- a/src/components/index.scss +++ b/src/components/index.scss @@ -8,6 +8,7 @@ @import './inventory/InventoryView'; @import './mod-tools/ModToolsView'; @import './navigator/NavigatorView'; +@import './purse/PurseView'; @import './toolbar/ToolbarView'; @import './user-profile/UserProfileVew'; @import './user-settings/UserSettingsView'; diff --git a/src/views/purse/context/PurseContext.tsx b/src/components/purse/PurseContext.tsx similarity index 50% rename from src/views/purse/context/PurseContext.tsx rename to src/components/purse/PurseContext.tsx index b843f42c..1999abdd 100644 --- a/src/views/purse/context/PurseContext.tsx +++ b/src/components/purse/PurseContext.tsx @@ -1,11 +1,16 @@ -import { createContext, FC, useContext } from 'react'; -import { IPurseContext, PurseContextProps } from './PurseContext.types'; +import { createContext, FC, ProviderProps, useContext } from 'react'; +import { IPurse } from './common/IPurse'; + +interface IPurseContext +{ + purse: IPurse; +} const PurseContext = createContext({ purse: null }); -export const PurseContextProvider: FC = props => +export const PurseContextProvider: FC> = props => { return { props.children } } diff --git a/src/views/purse/PurseMessageHandler.tsx b/src/components/purse/PurseMessageHandler.tsx similarity index 92% rename from src/views/purse/PurseMessageHandler.tsx rename to src/components/purse/PurseMessageHandler.tsx index 07ca8f09..3002b26a 100644 --- a/src/views/purse/PurseMessageHandler.tsx +++ b/src/components/purse/PurseMessageHandler.tsx @@ -2,10 +2,9 @@ import { ActivityPointNotificationMessageEvent, UserCreditsEvent, UserCurrencyEv import { FC, useCallback } from 'react'; import { CREDITS, DUCKETS, PlaySound } from '../../api/utils/PlaySound'; import { CreateMessageHook } from '../../hooks/messages/message-event'; -import { usePurseContext } from './context/PurseContext'; -import { PurseMessageHandlerProps } from './PurseMessageHandler.types'; +import { usePurseContext } from './PurseContext'; -export const PurseMessageHandler: FC = props => +export const PurseMessageHandler: FC<{}> = props => { const { purse = null } = usePurseContext(); diff --git a/src/views/purse/PurseView.scss b/src/components/purse/PurseView.scss similarity index 60% rename from src/views/purse/PurseView.scss rename to src/components/purse/PurseView.scss index 30ac9bff..15add56a 100644 --- a/src/views/purse/PurseView.scss +++ b/src/components/purse/PurseView.scss @@ -3,7 +3,6 @@ font-size: $font-size-sm; pointer-events: all; margin-bottom: 5px; - padding: 6px 5px; box-shadow: inset 0px 5px lighten(rgba($dark, 0.6), 2.5), inset 0 -4px darken(rgba($dark, 0.6), 4); @@ -17,23 +16,30 @@ .nitro-purse-hc { background-color: rgba($light, 0.1); - margin: 0 5px; } .nitro-purse-button { - border-bottom: 1px solid rgba(0, 0, 0, 0.3); - padding: 2px 3px; - border-radius: $border-radius; - - &:last-child { - border-bottom: none; - } &:hover { background-color: rgba($light, 0.1); cursor: pointer; } } -} -@import "./views"; + .nitro-currency { + pointer-events: all; + position: relative; + } + + .nitro-seasonal-currency { + pointer-events: all; + background-color: rgba($dark,.95); + box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4); + font-size: $font-size-sm; + margin-bottom: 5px; + + .seasonal-text { + color: rgba($light,.5); + } + } +} diff --git a/src/components/purse/PurseView.tsx b/src/components/purse/PurseView.tsx new file mode 100644 index 00000000..1363b2f6 --- /dev/null +++ b/src/components/purse/PurseView.tsx @@ -0,0 +1,135 @@ +import { FriendlyTime, HabboClubLevelEnum, UserCurrencyComposer, UserSubscriptionComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import { CreateLinkEvent, GetConfiguration, LocalizeText } from '../../api'; +import { Column, Flex, Grid } from '../../common'; +import { HcCenterEvent } from '../../events/hc-center/HcCenterEvent'; +import { UserSettingsUIEvent } from '../../events/user-settings/UserSettingsUIEvent'; +import { dispatchUiEvent } from '../../hooks'; +import { SendMessageHook } from '../../hooks/messages/message-event'; +import { CurrencyIcon } from '../../views/shared/currency-icon/CurrencyIcon'; +import { IPurse } from './common/IPurse'; +import { Purse } from './common/Purse'; +import { PurseContextProvider } from './PurseContext'; +import { PurseMessageHandler } from './PurseMessageHandler'; +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 [ updateId, setUpdateId ] = useState(-1); + + const handleUserSettingsClick = () => dispatchUiEvent(new UserSettingsUIEvent(UserSettingsUIEvent.TOGGLE_USER_SETTINGS)); + + const handleHelpCenterClick = () => CreateLinkEvent('help/show'); + + const handleHcCenterClick = () => dispatchUiEvent(new HcCenterEvent(HcCenterEvent.TOGGLE_HC_CENTER)); + + const displayedCurrencies = useMemo(() => GetConfiguration('system.currency.types', []), []); + + const currencyDisplayNumberShort = useMemo(() => GetConfiguration('currency.display.number.short', false), []); + + const getClubText = useMemo(() => + { + const totalDays = ((purse.clubPeriods * 31) + purse.clubDays); + const minutesUntilExpiration = purse.minutesUntilExpiration; + + if(purse.clubLevel === HabboClubLevelEnum.NO_CLUB) return LocalizeText('purse.clubdays.zero.amount.text'); + + else if((minutesUntilExpiration > -1) && (minutesUntilExpiration < (60 * 24))) return FriendlyTime.shortFormat(minutesUntilExpiration * 60); + + else return FriendlyTime.shortFormat(totalDays * 86400); + }, [ purse ]); + + const getCurrencyElements = useCallback((offset: number, limit: number = -1, seasonal: boolean = false) => + { + if(!purse.activityPoints.size) return null; + + const types = Array.from(purse.activityPoints.keys()).filter(type => (displayedCurrencies.indexOf(type) >= 0)); + + let count = 0; + + while(count < offset) + { + types.shift(); + + count++; + } + + count = 0; + + const elements: JSX.Element[] = []; + + for(const type of types) + { + if((limit > -1) && (count === limit)) break; + + if(seasonal) elements.push(); + else elements.push(); + + count++; + } + + return elements; + }, [ purse, displayedCurrencies, currencyDisplayNumberShort ]); + + useEffect(() => + { + const purse = new Purse(); + + GLOBAL_PURSE = purse; + + purse.notifier = () => setUpdateId(prevValue => (prevValue + 1)); + + setPurse(purse); + + return () => (purse.notifier = null); + }, []); + + useEffect(() => + { + if(!purse) return; + + SendMessageHook(new UserCurrencyComposer()); + }, [ purse ]); + + useEffect(() => + { + SendMessageHook(new UserSubscriptionComposer('habbo_club')); + + const interval = setInterval(() => SendMessageHook(new UserSubscriptionComposer('habbo_club')), 50000); + + return () => clearInterval(interval); + }, [ purse ]); + + if(!purse) return null; + + return ( + + + + + + + { getCurrencyElements(0, 2) } + + + + { getClubText } + + + + + + + + + + + + { getCurrencyElements(2, -1, true) } + + ); +} diff --git a/src/views/purse/common/CurrencyHelper.ts b/src/components/purse/common/CurrencyHelper.ts similarity index 100% rename from src/views/purse/common/CurrencyHelper.ts rename to src/components/purse/common/CurrencyHelper.ts diff --git a/src/views/purse/common/IPurse.ts b/src/components/purse/common/IPurse.ts similarity index 100% rename from src/views/purse/common/IPurse.ts rename to src/components/purse/common/IPurse.ts diff --git a/src/views/purse/common/Purse.ts b/src/components/purse/common/Purse.ts similarity index 100% rename from src/views/purse/common/Purse.ts rename to src/components/purse/common/Purse.ts diff --git a/src/components/purse/views/CurrencyView.tsx b/src/components/purse/views/CurrencyView.tsx new file mode 100644 index 00000000..4204d444 --- /dev/null +++ b/src/components/purse/views/CurrencyView.tsx @@ -0,0 +1,40 @@ +import { FC, useMemo } from 'react'; +import { OverlayTrigger, Tooltip } from 'react-bootstrap'; +import { LocalizeFormattedNumber, LocalizeShortNumber } from '../../../api'; +import { Flex } from '../../../common'; +import { CurrencyIcon } from '../../../views/shared/currency-icon/CurrencyIcon'; + +interface CurrencyViewProps +{ + type: number; + amount: number; + short: boolean; +} + +export const CurrencyView: FC = props => +{ + const { type = -1, amount = -1, short = false } = props; + + const element = useMemo(() => + { + return ( + +
{ short ? LocalizeShortNumber(amount) : LocalizeFormattedNumber(amount) }
+ +
); + }, [ amount, short, type ]); + + if(!short) return element; + + return ( + + { LocalizeFormattedNumber(amount) } + + }> + { element } + + ); +} diff --git a/src/views/purse/views/seasonal/SeasonalView.tsx b/src/components/purse/views/SeasonalView.tsx similarity index 66% rename from src/views/purse/views/seasonal/SeasonalView.tsx rename to src/components/purse/views/SeasonalView.tsx index 804b15b4..d46f6f26 100644 --- a/src/views/purse/views/seasonal/SeasonalView.tsx +++ b/src/components/purse/views/SeasonalView.tsx @@ -1,14 +1,20 @@ import { FC } from 'react'; -import { LocalizeFormattedNumber, LocalizeText } from '../../../../api'; -import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon'; -import { SeasonalViewProps } from './SeasonalView.types'; +import { LocalizeFormattedNumber, LocalizeText } from '../../../api'; +import { Flex } from '../../../common'; +import { CurrencyIcon } from '../../../views/shared/currency-icon/CurrencyIcon'; + +interface SeasonalViewProps +{ + type: number; + amount: number; +} export const SeasonalView: FC = props => { const { type = -1, amount = -1 } = props; return ( -
+
{ LocalizeText(`purse.seasonal.currency.${ type }`) } { LocalizeFormattedNumber(amount) } @@ -16,6 +22,6 @@ export const SeasonalView: FC = props =>
-
+
); } diff --git a/src/views/Styles.scss b/src/views/Styles.scss index 197b1e05..c055e268 100644 --- a/src/views/Styles.scss +++ b/src/views/Styles.scss @@ -4,7 +4,6 @@ @import "./loading/LoadingView"; @import "./main/MainView"; @import "./notification-center/NotificationCenterView"; -@import "./purse/PurseView"; @import "./right-side/RightSideView"; @import "./room/RoomView"; @import "./room-host/RoomHostView"; diff --git a/src/views/purse/PurseMessageHandler.types.ts b/src/views/purse/PurseMessageHandler.types.ts deleted file mode 100644 index f9787398..00000000 --- a/src/views/purse/PurseMessageHandler.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface PurseMessageHandlerProps -{ - -} diff --git a/src/views/purse/PurseView.tsx b/src/views/purse/PurseView.tsx deleted file mode 100644 index 5fd95166..00000000 --- a/src/views/purse/PurseView.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { FriendlyTime, HabboClubLevelEnum, UserCurrencyComposer, UserSubscriptionComposer } from '@nitrots/nitro-renderer'; -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { CreateLinkEvent, GetConfiguration, LocalizeText } from '../../api'; -import { HcCenterEvent } from '../../events/hc-center/HcCenterEvent'; -import { UserSettingsUIEvent } from '../../events/user-settings/UserSettingsUIEvent'; -import { dispatchUiEvent } from '../../hooks'; -import { SendMessageHook } from '../../hooks/messages/message-event'; -import { CurrencyIcon } from '../shared/currency-icon/CurrencyIcon'; -import { IPurse } from './common/IPurse'; -import { Purse } from './common/Purse'; -import { PurseContextProvider } from './context/PurseContext'; -import { PurseMessageHandler } from './PurseMessageHandler'; -import { CurrencyView } from './views/currency/CurrencyView'; -import { SeasonalView } from './views/seasonal/SeasonalView'; - -export let GLOBAL_PURSE: IPurse = null; - -export const PurseView: FC<{}> = props => -{ - const [ purse, setPurse ] = useState(new Purse()); - const [ updateId, setUpdateId ] = useState(-1); - - const handleUserSettingsClick = useCallback(() => - { - dispatchUiEvent(new UserSettingsUIEvent(UserSettingsUIEvent.TOGGLE_USER_SETTINGS)); - }, []); - - const handleHelpCenterClick = useCallback(() => - { - CreateLinkEvent('help/show'); - }, []); - - const handleHcCenterClick = useCallback(() => - { - dispatchUiEvent(new HcCenterEvent(HcCenterEvent.TOGGLE_HC_CENTER)); - }, []); - - const displayedCurrencies = useMemo(() => - { - return GetConfiguration('system.currency.types', []); - }, []); - - const currencyDisplayNumberShort = useMemo(() => - { - return GetConfiguration('currency.display.number.short', false); - }, []); - - const getCurrencyElements = useCallback((offset: number, limit: number = -1, seasonal: boolean = false) => - { - if(!purse.activityPoints.size) return null; - - const types = Array.from(purse.activityPoints.keys()).filter(type => (displayedCurrencies.indexOf(type) >= 0)); - - let count = 0; - - while(count < offset) - { - types.shift(); - - count++; - } - - count = 0; - - const elements: JSX.Element[] = []; - - for(const type of types) - { - if((limit > -1) && (count === limit)) break; - - if(seasonal) elements.push(); - else elements.push(); - - count++; - } - - return elements; - }, [ purse, displayedCurrencies, currencyDisplayNumberShort ]); - - const getClubText = useCallback(() => - { - const totalDays = ((purse.clubPeriods * 31) + purse.clubDays); - const minutesUntilExpiration = purse.minutesUntilExpiration; - - if(purse.clubLevel === HabboClubLevelEnum.NO_CLUB) - { - return LocalizeText('purse.clubdays.zero.amount.text'); - } - - else if((minutesUntilExpiration > -1) && (minutesUntilExpiration < (60 * 24))) - { - return FriendlyTime.shortFormat(minutesUntilExpiration * 60); - } - - else - { - return FriendlyTime.shortFormat(totalDays * 86400); - } - }, [ purse ]); - - useEffect(() => - { - const purse = new Purse(); - - GLOBAL_PURSE = purse; - - purse.notifier = () => setUpdateId(prevValue => (prevValue + 1)); - - setPurse(purse); - - return () => (purse.notifier = null); - }, []); - - useEffect(() => - { - if(!purse) return; - - SendMessageHook(new UserCurrencyComposer()); - }, [ purse ]); - - useEffect(() => - { - SendMessageHook(new UserSubscriptionComposer('habbo_club')); - - const interval = setInterval(() => - { - SendMessageHook(new UserSubscriptionComposer('habbo_club')); - }, 50000); - - return () => clearInterval(interval); - }, [ purse ]); - - if(!purse) return null; - - return ( - - -
-
-
-
- - { getCurrencyElements(0, 2) } -
-
-
-
- - { getClubText() } -
-
-
-
-
-
-
-
-
- {/*
- -
*/} -
- { getCurrencyElements(2, -1, true) } -
- ); -} diff --git a/src/views/purse/context/PurseContext.types.ts b/src/views/purse/context/PurseContext.types.ts deleted file mode 100644 index 7470b465..00000000 --- a/src/views/purse/context/PurseContext.types.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ProviderProps } from 'react'; -import { IPurse } from '../common/IPurse'; - -export interface IPurseContext -{ - purse: IPurse; -} - -export interface PurseContextProps extends ProviderProps -{ - -} diff --git a/src/views/purse/views/currency/CurrencyView.scss b/src/views/purse/views/currency/CurrencyView.scss deleted file mode 100644 index eb77390d..00000000 --- a/src/views/purse/views/currency/CurrencyView.scss +++ /dev/null @@ -1,4 +0,0 @@ -.nitro-currency { - pointer-events: all; - position: relative; -} diff --git a/src/views/purse/views/currency/CurrencyView.tsx b/src/views/purse/views/currency/CurrencyView.tsx deleted file mode 100644 index 589eb03e..00000000 --- a/src/views/purse/views/currency/CurrencyView.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { FC, useMemo } from 'react'; -import { OverlayTrigger, Tooltip } from 'react-bootstrap'; -import { LocalizeFormattedNumber, LocalizeShortNumber } from '../../../../api'; -import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon'; -import { CurrencyViewProps } from './CurrencyView.types'; - -export const CurrencyView: FC = props => -{ - const { type = -1, amount = -1, short = false } = props; - - const element = useMemo(() => - { - return (
-
{ short ? LocalizeShortNumber(amount) : LocalizeFormattedNumber(amount) }
- -
); - }, [ amount, short, type ]); - - if(!short) return element; - - return ( - - { LocalizeFormattedNumber(amount) } - - }> - { element } - - ); -} diff --git a/src/views/purse/views/currency/CurrencyView.types.ts b/src/views/purse/views/currency/CurrencyView.types.ts deleted file mode 100644 index fc6684f8..00000000 --- a/src/views/purse/views/currency/CurrencyView.types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface CurrencyViewProps -{ - type: number; - amount: number; - short: boolean; -} diff --git a/src/views/purse/views/index.scss b/src/views/purse/views/index.scss deleted file mode 100644 index 52330b9e..00000000 --- a/src/views/purse/views/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "./currency/CurrencyView"; -@import "./seasonal/SeasonalView"; diff --git a/src/views/purse/views/seasonal/SeasonalView.scss b/src/views/purse/views/seasonal/SeasonalView.scss deleted file mode 100644 index 901c0d8d..00000000 --- a/src/views/purse/views/seasonal/SeasonalView.scss +++ /dev/null @@ -1,12 +0,0 @@ -.nitro-seasonal-currency { - pointer-events: all; - padding: 6px 5px; - background-color: rgba($dark,.95); - box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4); - font-size: $font-size-sm; - margin-bottom: 5px; - - .seasonal-text { - color: rgba($light,.5); - } -} diff --git a/src/views/purse/views/seasonal/SeasonalView.types.ts b/src/views/purse/views/seasonal/SeasonalView.types.ts deleted file mode 100644 index c7b8db5a..00000000 --- a/src/views/purse/views/seasonal/SeasonalView.types.ts +++ /dev/null @@ -1,6 +0,0 @@ - -export interface SeasonalViewProps -{ - type: number; - amount: number; -} diff --git a/src/views/right-side/RightSideView.tsx b/src/views/right-side/RightSideView.tsx index 49b4ebca..7c8bff44 100644 --- a/src/views/right-side/RightSideView.tsx +++ b/src/views/right-side/RightSideView.tsx @@ -1,7 +1,7 @@ import { FC } from 'react'; import { GroupRoomInformationView } from '../../components/groups/views/room-information/GroupRoomInformationView'; +import { PurseView } from '../../components/purse/PurseView'; import { NotificationCenterView } from '../notification-center/NotificationCenterView'; -import { PurseView } from '../purse/PurseView'; import { RightSideProps } from './RightSideView.types'; export const RightSideView: FC = props =>