diff --git a/src/views/purse/PurseMessageHandler.tsx b/src/views/purse/PurseMessageHandler.tsx new file mode 100644 index 00000000..1e141bfe --- /dev/null +++ b/src/views/purse/PurseMessageHandler.tsx @@ -0,0 +1,56 @@ +import { UserCreditsEvent, UserCurrencyEvent, UserCurrencyUpdateEvent } from 'nitro-renderer'; +import { FC, useCallback } from 'react'; +import { CreateMessageHook } from '../../hooks/messages/message-event'; +import { usePurseContext } from './context/PurseContext'; +import { PurseMessageHandlerProps } from './PurseMessageHandler.types'; +import { PurseActions } from './reducers/PurseReducer'; +import { Currency } from './utils/Currency'; + +export const PurseMessageHandler: FC = props => +{ + const { dispatchPurseState = null } = usePurseContext(); + + const onUserCreditsEvent = useCallback((event: UserCreditsEvent) => + { + const parser = event.getParser(); + + dispatchPurseState({ + type: PurseActions.SET_CURRENCY, + payload: { + currency: { type: -1, amount: parseFloat(parser.credits) } + } + }); + }, [ dispatchPurseState ]); + + const onUserCurrencyEvent = useCallback((event: UserCurrencyEvent) => + { + const parser = event.getParser(); + + const currencies: Currency[] = []; + + for(const [ key, value ] of parser.currencies.entries()) currencies.push({ type: key, amount: value }); + + dispatchPurseState({ + type: PurseActions.SET_CURRENCIES, + payload: { currencies } + }); + }, [ dispatchPurseState ]); + + const onUserCurrencyUpdateEvent = useCallback((event: UserCurrencyUpdateEvent) => + { + const parser = event.getParser(); + + dispatchPurseState({ + type: PurseActions.SET_CURRENCY, + payload: { + currency: { type: parser.type, amount: parser.amount } + } + }); + }, [ dispatchPurseState ]); + + CreateMessageHook(UserCreditsEvent, onUserCreditsEvent); + CreateMessageHook(UserCurrencyEvent, onUserCurrencyEvent); + CreateMessageHook(UserCurrencyUpdateEvent, onUserCurrencyUpdateEvent); + + return null; +} diff --git a/src/views/purse/PurseMessageHandler.types.ts b/src/views/purse/PurseMessageHandler.types.ts new file mode 100644 index 00000000..f9787398 --- /dev/null +++ b/src/views/purse/PurseMessageHandler.types.ts @@ -0,0 +1,4 @@ +export interface PurseMessageHandlerProps +{ + +} diff --git a/src/views/purse/PurseView.tsx b/src/views/purse/PurseView.tsx index a75f8741..d9c6d1f4 100644 --- a/src/views/purse/PurseView.tsx +++ b/src/views/purse/PurseView.tsx @@ -1,90 +1,39 @@ -import { UserCreditsEvent, UserCurrencyComposer, UserCurrencyEvent, UserCurrencyUpdateEvent } from 'nitro-renderer'; -import { useCallback, useEffect, useState } from 'react'; -import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; -import { TransitionAnimation } from '../../transitions/TransitionAnimation'; -import { TransitionAnimationTypes } from '../../transitions/TransitionAnimation.types'; +import { UserCurrencyComposer } from 'nitro-renderer'; +import { FC, useEffect, useMemo, useReducer } from 'react'; +import { SendMessageHook } from '../../hooks/messages/message-event'; import { GetConfiguration } from '../../utils/GetConfiguration'; -import { CurrencySet } from './currency/CurrencySet'; +import { PurseContextProvider } from './context/PurseContext'; import { CurrencyView } from './currency/CurrencyView'; +import { PurseMessageHandler } from './PurseMessageHandler'; import { PurseViewProps } from './PurseView.types'; +import { initialPurse, PurseReducer } from './reducers/PurseReducer'; -export function PurseView(props: PurseViewProps): JSX.Element +export const PurseView: FC = props => { - const [ currencies, setCurrencies ] = useState([ new CurrencySet(-1, 0) ]); - const [ isReady, setIsReady ] = useState(false); - - const displayedCurrencies = GetConfiguration('system.currency.types', []); - - const onUserCreditsEvent = useCallback((event: UserCreditsEvent) => + const [ purseState, dispatchPurseState ] = useReducer(PurseReducer, initialPurse); + const { currencies = [] } = purseState; + + const displayedCurrencies = useMemo(() => { - const parser = event.getParser(); - - updateCurrency(-1, parseFloat(parser.credits)); + return GetConfiguration('system.currency.types', []); }, []); - const onUserCurrencyEvent = useCallback((event: UserCurrencyEvent) => - { - const parser = event.getParser(); - - for(const [ key, value ] of parser.currencies.entries()) updateCurrency(key, value); - - setIsReady(true); - }, []); - - const onUserCurrencyUpdateEvent = useCallback((event: UserCurrencyUpdateEvent) => - { - const parser = event.getParser(); - - updateCurrency(parser.type, parser.amount) - }, []); - - function updateCurrency(type: number, amount: number): void - { - setCurrencies(oldState => - { - const newState: CurrencySet[] = []; - - let found = false; - - for(const set of oldState) - { - if(set.type !== type) - { - newState.push(set); - - continue; - } - - newState.push(new CurrencySet(set.type, amount)); - - found = true; - } - - if(!found) newState.push(new CurrencySet(type, amount)); - - return newState; - }); - } - - CreateMessageHook(UserCreditsEvent, onUserCreditsEvent); - CreateMessageHook(UserCurrencyEvent, onUserCurrencyEvent); - CreateMessageHook(UserCurrencyUpdateEvent, onUserCurrencyUpdateEvent); - useEffect(() => { SendMessageHook(new UserCurrencyComposer()); }, []); return ( - + +
- { currencies && currencies.map((set, index) => + { currencies && currencies.map((currency, index) => { - if(displayedCurrencies.indexOf(set.type) === -1) return null; + if(displayedCurrencies.indexOf(currency.type) === -1) return null; - return + return }) }
-
+ ); } diff --git a/src/views/purse/context/PurseContext.tsx b/src/views/purse/context/PurseContext.tsx new file mode 100644 index 00000000..788d4d8d --- /dev/null +++ b/src/views/purse/context/PurseContext.tsx @@ -0,0 +1,14 @@ +import { createContext, FC, useContext } from 'react'; +import { IPurseContext, PurseContextProps } from './PurseContext.types'; + +const PurseContext = createContext({ + purseState: null, + dispatchPurseState: null +}); + +export const PurseContextProvider: FC = props => +{ + return { props.children } +} + +export const usePurseContext = () => useContext(PurseContext); diff --git a/src/views/purse/context/PurseContext.types.ts b/src/views/purse/context/PurseContext.types.ts new file mode 100644 index 00000000..4b18f160 --- /dev/null +++ b/src/views/purse/context/PurseContext.types.ts @@ -0,0 +1,13 @@ +import { Dispatch, ProviderProps } from 'react'; +import { IPurseAction, IPurseState } from '../reducers/PurseReducer'; + +export interface IPurseContext +{ + purseState: IPurseState; + dispatchPurseState: Dispatch; +} + +export interface PurseContextProps extends ProviderProps +{ + +} diff --git a/src/views/purse/currency/CurrencySet.ts b/src/views/purse/currency/CurrencySet.ts deleted file mode 100644 index 6c990975..00000000 --- a/src/views/purse/currency/CurrencySet.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class CurrencySet -{ - constructor( - public type: number, - public amount: number) - { - - } -} diff --git a/src/views/purse/currency/CurrencyView.tsx b/src/views/purse/currency/CurrencyView.tsx index 8564540a..9fdd6a06 100644 --- a/src/views/purse/currency/CurrencyView.tsx +++ b/src/views/purse/currency/CurrencyView.tsx @@ -6,7 +6,7 @@ import { CurrencyViewProps } from './CurrencyView.types'; export function CurrencyView(props: CurrencyViewProps): JSX.Element { - const { currencySet = null } = props; + const { currency = null } = props; const [ firstRender, setFirstRender ] = useState(true); const [ isAnimating, setIsAnimating ] = useState(false); @@ -22,22 +22,20 @@ export function CurrencyView(props: CurrencyViewProps): JSX.Element setIsAnimating(true); - let timeout = setTimeout(() => - { - setIsAnimating(false) - - timeout = null - }, 300); + const timeout = setTimeout(() => setIsAnimating(false), 305); - return () => clearTimeout(timeout); - }, [ firstRender, currencySet ]); + return () => + { + clearTimeout(timeout); + } + }, [ firstRender, currency ]); return ( - +
-
{ currencySet.amount }
-
+
{ !isAnimating && currency.amount }
+
diff --git a/src/views/purse/currency/CurrencyView.types.ts b/src/views/purse/currency/CurrencyView.types.ts index a43fa26f..6e276237 100644 --- a/src/views/purse/currency/CurrencyView.types.ts +++ b/src/views/purse/currency/CurrencyView.types.ts @@ -1,6 +1,6 @@ -import { CurrencySet } from './CurrencySet'; +import { Currency } from '../utils/Currency'; export interface CurrencyViewProps { - currencySet: CurrencySet; + currency: Currency; } diff --git a/src/views/purse/reducers/PurseReducer.tsx b/src/views/purse/reducers/PurseReducer.tsx new file mode 100644 index 00000000..e0243a13 --- /dev/null +++ b/src/views/purse/reducers/PurseReducer.tsx @@ -0,0 +1,67 @@ +import { Reducer } from 'react'; +import { Currency } from '../utils/Currency'; + +export interface IPurseState +{ + currencies: Currency[]; +} + +export interface IPurseAction +{ + type: string; + payload: { + currency?: Currency; + currencies?: Currency[]; + } +} + +export class PurseActions +{ + public static SET_CURRENCY: string = 'PA_SET_CURRENCY'; + public static SET_CURRENCIES: string = 'PA_SET_CURRENCIES'; +} + +export const initialPurse: IPurseState = { + currencies: [] +} + +export const PurseReducer: Reducer = (state, action) => +{ + switch(action.type) + { + case PurseActions.SET_CURRENCY: { + const updated = action.payload.currency; + + let didSet = false; + + const currencies = state.currencies.map((existing, index) => + { + if(existing.type !== updated.type) return existing; + + didSet = true; + + return { ...updated }; + }); + + if(!didSet) currencies.push({ ...updated }); + + return { ...state, currencies }; + } + case PurseActions.SET_CURRENCIES: { + const updated = action.payload.currencies; + + const currencies = state.currencies.filter((existing, index) => + { + if(existing.type !== -1) return null; + + return existing; + }); + + if(updated && updated.length) currencies.push(...updated); + + return { ...state, currencies }; + } + default: + return state; + } +} diff --git a/src/views/purse/utils/Currency.ts b/src/views/purse/utils/Currency.ts new file mode 100644 index 00000000..9a2e2dea --- /dev/null +++ b/src/views/purse/utils/Currency.ts @@ -0,0 +1,5 @@ +export interface Currency +{ + type: number; + amount: number; +}