mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 14:40:50 +01:00
Purse updates
This commit is contained in:
parent
410fffc9be
commit
45179a8eda
@ -13,9 +13,9 @@ import { CatalogEvent } from '../../../../../events/catalog/CatalogEvent';
|
|||||||
import { useUiEvent } from '../../../../../hooks';
|
import { useUiEvent } from '../../../../../hooks';
|
||||||
import { SendMessageHook } from '../../../../../hooks/messages/message-event';
|
import { SendMessageHook } from '../../../../../hooks/messages/message-event';
|
||||||
import { LoadingSpinnerView } from '../../../../../layout/loading-spinner/LoadingSpinnerView';
|
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 { CurrencyIcon } from '../../../../../views/shared/currency-icon/CurrencyIcon';
|
||||||
|
import { GetCurrencyAmount } from '../../../../purse/common/CurrencyHelper';
|
||||||
|
import { GLOBAL_PURSE } from '../../../../purse/PurseView';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalogContext } from '../../../CatalogContext';
|
||||||
import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
|
import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
|
||||||
import { CatalogLayoutProps } from './CatalogLayout.types';
|
import { CatalogLayoutProps } from './CatalogLayout.types';
|
||||||
|
@ -9,7 +9,7 @@ import { Text } from '../../../../../../common/Text';
|
|||||||
import { BatchUpdates, CreateMessageHook, SendMessageHook } from '../../../../../../hooks';
|
import { BatchUpdates, CreateMessageHook, SendMessageHook } from '../../../../../../hooks';
|
||||||
import { NotificationAlertType } from '../../../../../../views/notification-center/common/NotificationAlertType';
|
import { NotificationAlertType } from '../../../../../../views/notification-center/common/NotificationAlertType';
|
||||||
import { NotificationUtilities } from '../../../../../../views/notification-center/common/NotificationUtilities';
|
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 { CatalogLayoutProps } from '../CatalogLayout.types';
|
||||||
import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView';
|
import { CatalogLayoutMarketplaceItemView, PUBLIC_OFFER } from './CatalogLayoutMarketplaceItemView';
|
||||||
import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView';
|
import { SearchFormView } from './CatalogLayoutMarketplaceSearchFormView';
|
||||||
|
@ -8,7 +8,7 @@ import { CatalogInitPurchaseEvent } from '../../../../../events/catalog/CatalogI
|
|||||||
import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent';
|
import { CatalogWidgetEvent } from '../../../../../events/catalog/CatalogWidgetEvent';
|
||||||
import { dispatchUiEvent, SendMessageHook, useUiEvent } from '../../../../../hooks';
|
import { dispatchUiEvent, SendMessageHook, useUiEvent } from '../../../../../hooks';
|
||||||
import { LoadingSpinnerView } from '../../../../../layout';
|
import { LoadingSpinnerView } from '../../../../../layout';
|
||||||
import { GetCurrencyAmount } from '../../../../../views/purse/common/CurrencyHelper';
|
import { GetCurrencyAmount } from '../../../../purse/common/CurrencyHelper';
|
||||||
import { useCatalogContext } from '../../../CatalogContext';
|
import { useCatalogContext } from '../../../CatalogContext';
|
||||||
import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
|
import { CatalogPurchaseState } from '../../../common/CatalogPurchaseState';
|
||||||
import { Offer } from '../../../common/Offer';
|
import { Offer } from '../../../common/Offer';
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
@import './inventory/InventoryView';
|
@import './inventory/InventoryView';
|
||||||
@import './mod-tools/ModToolsView';
|
@import './mod-tools/ModToolsView';
|
||||||
@import './navigator/NavigatorView';
|
@import './navigator/NavigatorView';
|
||||||
|
@import './purse/PurseView';
|
||||||
@import './toolbar/ToolbarView';
|
@import './toolbar/ToolbarView';
|
||||||
@import './user-profile/UserProfileVew';
|
@import './user-profile/UserProfileVew';
|
||||||
@import './user-settings/UserSettingsView';
|
@import './user-settings/UserSettingsView';
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import { createContext, FC, useContext } from 'react';
|
import { createContext, FC, ProviderProps, useContext } from 'react';
|
||||||
import { IPurseContext, PurseContextProps } from './PurseContext.types';
|
import { IPurse } from './common/IPurse';
|
||||||
|
|
||||||
|
interface IPurseContext
|
||||||
|
{
|
||||||
|
purse: IPurse;
|
||||||
|
}
|
||||||
|
|
||||||
const PurseContext = createContext<IPurseContext>({
|
const PurseContext = createContext<IPurseContext>({
|
||||||
purse: null
|
purse: null
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PurseContextProvider: FC<PurseContextProps> = props =>
|
export const PurseContextProvider: FC<ProviderProps<IPurseContext>> = props =>
|
||||||
{
|
{
|
||||||
return <PurseContext.Provider value={ props.value }>{ props.children }</PurseContext.Provider>
|
return <PurseContext.Provider value={ props.value }>{ props.children }</PurseContext.Provider>
|
||||||
}
|
}
|
@ -2,10 +2,9 @@ import { ActivityPointNotificationMessageEvent, UserCreditsEvent, UserCurrencyEv
|
|||||||
import { FC, useCallback } from 'react';
|
import { FC, useCallback } from 'react';
|
||||||
import { CREDITS, DUCKETS, PlaySound } from '../../api/utils/PlaySound';
|
import { CREDITS, DUCKETS, PlaySound } from '../../api/utils/PlaySound';
|
||||||
import { CreateMessageHook } from '../../hooks/messages/message-event';
|
import { CreateMessageHook } from '../../hooks/messages/message-event';
|
||||||
import { usePurseContext } from './context/PurseContext';
|
import { usePurseContext } from './PurseContext';
|
||||||
import { PurseMessageHandlerProps } from './PurseMessageHandler.types';
|
|
||||||
|
|
||||||
export const PurseMessageHandler: FC<PurseMessageHandlerProps> = props =>
|
export const PurseMessageHandler: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { purse = null } = usePurseContext();
|
const { purse = null } = usePurseContext();
|
||||||
|
|
@ -3,7 +3,6 @@
|
|||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
padding: 6px 5px;
|
|
||||||
box-shadow: inset 0px 5px lighten(rgba($dark, 0.6), 2.5),
|
box-shadow: inset 0px 5px lighten(rgba($dark, 0.6), 2.5),
|
||||||
inset 0 -4px darken(rgba($dark, 0.6), 4);
|
inset 0 -4px darken(rgba($dark, 0.6), 4);
|
||||||
|
|
||||||
@ -17,23 +16,30 @@
|
|||||||
|
|
||||||
.nitro-purse-hc {
|
.nitro-purse-hc {
|
||||||
background-color: rgba($light, 0.1);
|
background-color: rgba($light, 0.1);
|
||||||
margin: 0 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-purse-button {
|
.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 {
|
&:hover {
|
||||||
background-color: rgba($light, 0.1);
|
background-color: rgba($light, 0.1);
|
||||||
cursor: pointer;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
135
src/components/purse/PurseView.tsx
Normal file
135
src/components/purse/PurseView.tsx
Normal file
@ -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<IPurse>(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<number[]>('system.currency.types', []), []);
|
||||||
|
|
||||||
|
const currencyDisplayNumberShort = useMemo(() => GetConfiguration<boolean>('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(<SeasonalView key={ type } type={ type } amount={ purse.activityPoints.get(type) } />);
|
||||||
|
else elements.push(<CurrencyView key={ type } type={ type } amount={ purse.activityPoints.get(type) } short={ currencyDisplayNumberShort } />);
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<PurseContextProvider value={ { purse } }>
|
||||||
|
<PurseMessageHandler />
|
||||||
|
<Flex className="nitro-purse rounded-bottom p-1">
|
||||||
|
<Grid gap={ 1 }>
|
||||||
|
<Column justifyContent="center" size={ 6 } gap={ 1 } className="nitro-currencies">
|
||||||
|
<CurrencyView type={ -1 } amount={ purse.credits } short={ currencyDisplayNumberShort } />
|
||||||
|
{ getCurrencyElements(0, 2) }
|
||||||
|
</Column>
|
||||||
|
<Column center size={ 4 } gap={ 1 } className="nitro-purse-hc nitro-purse-button rounded" onClick={ handleHcCenterClick }>
|
||||||
|
<CurrencyIcon className="flex-shrink-0" type="hc" />
|
||||||
|
<span>{ getClubText }</span>
|
||||||
|
</Column>
|
||||||
|
<Column justifyContent="center" size={ 2 } gap={ 1 } className="nitro-purse-buttons">
|
||||||
|
<Flex center pointer fullHeight className="nitro-purse-button text-white text-center p-1 rounded" onClick={ handleHelpCenterClick }>
|
||||||
|
<i className="icon icon-help"/>
|
||||||
|
</Flex>
|
||||||
|
<Flex center pointer fullHeight className="nitro-purse-button text-white text-center p-1 rounded" onClick={ handleUserSettingsClick } >
|
||||||
|
<i className="icon icon-cog"/>
|
||||||
|
</Flex>
|
||||||
|
</Column>
|
||||||
|
</Grid>
|
||||||
|
</Flex>
|
||||||
|
{ getCurrencyElements(2, -1, true) }
|
||||||
|
</PurseContextProvider>
|
||||||
|
);
|
||||||
|
}
|
40
src/components/purse/views/CurrencyView.tsx
Normal file
40
src/components/purse/views/CurrencyView.tsx
Normal file
@ -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<CurrencyViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { type = -1, amount = -1, short = false } = props;
|
||||||
|
|
||||||
|
const element = useMemo(() =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<Flex justifyContent="end" className="nitro-currency nitro-purse-button rounded">
|
||||||
|
<div className="px-1 text-end text-truncate nitro-currency-text align-self-center">{ short ? LocalizeShortNumber(amount) : LocalizeFormattedNumber(amount) }</div>
|
||||||
|
<CurrencyIcon className="flex-shrink-0" type={ type } />
|
||||||
|
</Flex>);
|
||||||
|
}, [ amount, short, type ]);
|
||||||
|
|
||||||
|
if(!short) return element;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OverlayTrigger
|
||||||
|
placement="left"
|
||||||
|
overlay={
|
||||||
|
<Tooltip id={ `tooltip-${ type }` }>
|
||||||
|
{ LocalizeFormattedNumber(amount) }
|
||||||
|
</Tooltip>
|
||||||
|
}>
|
||||||
|
{ element }
|
||||||
|
</OverlayTrigger>
|
||||||
|
);
|
||||||
|
}
|
@ -1,14 +1,20 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { LocalizeFormattedNumber, LocalizeText } from '../../../../api';
|
import { LocalizeFormattedNumber, LocalizeText } from '../../../api';
|
||||||
import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
|
import { Flex } from '../../../common';
|
||||||
import { SeasonalViewProps } from './SeasonalView.types';
|
import { CurrencyIcon } from '../../../views/shared/currency-icon/CurrencyIcon';
|
||||||
|
|
||||||
|
interface SeasonalViewProps
|
||||||
|
{
|
||||||
|
type: number;
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
export const SeasonalView: FC<SeasonalViewProps> = props =>
|
export const SeasonalView: FC<SeasonalViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { type = -1, amount = -1 } = props;
|
const { type = -1, amount = -1 } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="nitro-seasonal-currency rounded d-flex justify-content-end">
|
<Flex justifyContent="end" className="nitro-seasonal-currency rounded">
|
||||||
<div className="nitro-currency-text w-100 px-1 d-flex justify-content-between">
|
<div className="nitro-currency-text w-100 px-1 d-flex justify-content-between">
|
||||||
<span className="seasonal-text">{ LocalizeText(`purse.seasonal.currency.${ type }`) }</span>
|
<span className="seasonal-text">{ LocalizeText(`purse.seasonal.currency.${ type }`) }</span>
|
||||||
<span>{ LocalizeFormattedNumber(amount) }</span>
|
<span>{ LocalizeFormattedNumber(amount) }</span>
|
||||||
@ -16,6 +22,6 @@ export const SeasonalView: FC<SeasonalViewProps> = props =>
|
|||||||
<div>
|
<div>
|
||||||
<CurrencyIcon type={ type } />
|
<CurrencyIcon type={ type } />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -4,7 +4,6 @@
|
|||||||
@import "./loading/LoadingView";
|
@import "./loading/LoadingView";
|
||||||
@import "./main/MainView";
|
@import "./main/MainView";
|
||||||
@import "./notification-center/NotificationCenterView";
|
@import "./notification-center/NotificationCenterView";
|
||||||
@import "./purse/PurseView";
|
|
||||||
@import "./right-side/RightSideView";
|
@import "./right-side/RightSideView";
|
||||||
@import "./room/RoomView";
|
@import "./room/RoomView";
|
||||||
@import "./room-host/RoomHostView";
|
@import "./room-host/RoomHostView";
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export interface PurseMessageHandlerProps
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@ -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<IPurse>(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<number[]>('system.currency.types', []);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const currencyDisplayNumberShort = useMemo(() =>
|
|
||||||
{
|
|
||||||
return GetConfiguration<boolean>('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(<SeasonalView key={ type } type={ type } amount={ purse.activityPoints.get(type) } />);
|
|
||||||
else elements.push(<CurrencyView key={ type } type={ type } amount={ purse.activityPoints.get(type) } short={ currencyDisplayNumberShort } />);
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<PurseContextProvider value={ { purse } }>
|
|
||||||
<PurseMessageHandler />
|
|
||||||
<div className="nitro-purse rounded-bottom d-flex flex-row justify-content-between">
|
|
||||||
<div className="row mx-0 w-100">
|
|
||||||
<div className="col-6 px-0">
|
|
||||||
<div className="d-flex flex-column nitro-currencies">
|
|
||||||
<CurrencyView type={ -1 } amount={ purse.credits } short={ currencyDisplayNumberShort } />
|
|
||||||
{ getCurrencyElements(0, 2) }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-4 px-0">
|
|
||||||
<div className="nitro-purse-hc nitro-purse-button rounded mx-1 p-1 d-flex flex-column justify-content-center align-items-center h-100"
|
|
||||||
onClick={ handleHcCenterClick }>
|
|
||||||
<CurrencyIcon className="flex-shrink-0" type="hc" />
|
|
||||||
<span>{ getClubText() }</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-2 px-0">
|
|
||||||
<div className="d-flex flex-column nitro-purse-buttons h-100 justify-content-center">
|
|
||||||
<div className="nitro-purse-button text-white h-100 text-center d-flex align-items-center justify-content-center cursor-pointer" onClick={ handleHelpCenterClick }><i className="icon icon-help"/></div>
|
|
||||||
<div className="nitro-purse-button text-white h-100 text-center d-flex align-items-center justify-content-center cursor-pointer" onClick={ handleUserSettingsClick } ><i className="fas fa-cogs"/></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/*<div className="notification-button px-2" onClick={toggleNotificationCenter}>
|
|
||||||
<i className="fas fa-bars" />
|
|
||||||
</div>*/}
|
|
||||||
</div>
|
|
||||||
{ getCurrencyElements(2, -1, true) }
|
|
||||||
</PurseContextProvider>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { ProviderProps } from 'react';
|
|
||||||
import { IPurse } from '../common/IPurse';
|
|
||||||
|
|
||||||
export interface IPurseContext
|
|
||||||
{
|
|
||||||
purse: IPurse;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PurseContextProps extends ProviderProps<IPurseContext>
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
.nitro-currency {
|
|
||||||
pointer-events: all;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
@ -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<CurrencyViewProps> = props =>
|
|
||||||
{
|
|
||||||
const { type = -1, amount = -1, short = false } = props;
|
|
||||||
|
|
||||||
const element = useMemo(() =>
|
|
||||||
{
|
|
||||||
return (<div className="nitro-currency d-flex justify-content-end nitro-purse-button">
|
|
||||||
<div className="px-1 text-end text-truncate nitro-currency-text align-self-center">{ short ? LocalizeShortNumber(amount) : LocalizeFormattedNumber(amount) }</div>
|
|
||||||
<CurrencyIcon className="flex-shrink-0" type={ type } />
|
|
||||||
</div>);
|
|
||||||
}, [ amount, short, type ]);
|
|
||||||
|
|
||||||
if(!short) return element;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<OverlayTrigger
|
|
||||||
placement="left"
|
|
||||||
overlay={
|
|
||||||
<Tooltip id={`tooltip-${ type }`}>
|
|
||||||
{ LocalizeFormattedNumber(amount) }
|
|
||||||
</Tooltip>
|
|
||||||
}>
|
|
||||||
{ element }
|
|
||||||
</OverlayTrigger>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
export interface CurrencyViewProps
|
|
||||||
{
|
|
||||||
type: number;
|
|
||||||
amount: number;
|
|
||||||
short: boolean;
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
@import "./currency/CurrencyView";
|
|
||||||
@import "./seasonal/SeasonalView";
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
export interface SeasonalViewProps
|
|
||||||
{
|
|
||||||
type: number;
|
|
||||||
amount: number;
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { GroupRoomInformationView } from '../../components/groups/views/room-information/GroupRoomInformationView';
|
import { GroupRoomInformationView } from '../../components/groups/views/room-information/GroupRoomInformationView';
|
||||||
|
import { PurseView } from '../../components/purse/PurseView';
|
||||||
import { NotificationCenterView } from '../notification-center/NotificationCenterView';
|
import { NotificationCenterView } from '../notification-center/NotificationCenterView';
|
||||||
import { PurseView } from '../purse/PurseView';
|
|
||||||
import { RightSideProps } from './RightSideView.types';
|
import { RightSideProps } from './RightSideView.types';
|
||||||
|
|
||||||
export const RightSideView: FC<RightSideProps> = props =>
|
export const RightSideView: FC<RightSideProps> = props =>
|
||||||
|
Loading…
Reference in New Issue
Block a user