diff options
Diffstat (limited to 'frontend/src/components/DeckyToasterState.tsx')
| -rw-r--r-- | frontend/src/components/DeckyToasterState.tsx | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/frontend/src/components/DeckyToasterState.tsx b/frontend/src/components/DeckyToasterState.tsx new file mode 100644 index 00000000..8732d7f8 --- /dev/null +++ b/frontend/src/components/DeckyToasterState.tsx @@ -0,0 +1,69 @@ +import { ToastData } from 'decky-frontend-lib'; +import { FC, createContext, useContext, useEffect, useState } from 'react'; + +interface PublicDeckyToasterState { + toasts: Set<ToastData>; +} + +export class DeckyToasterState { + // TODO a set would be better + private _toasts: Set<ToastData> = new Set(); + + public eventBus = new EventTarget(); + + publicState(): PublicDeckyToasterState { + return { toasts: this._toasts }; + } + + addToast(toast: ToastData) { + this._toasts.add(toast); + this.notifyUpdate(); + } + + removeToast(toast: ToastData) { + this._toasts.delete(toast); + this.notifyUpdate(); + } + + private notifyUpdate() { + this.eventBus.dispatchEvent(new Event('update')); + } +} + +interface DeckyToasterContext extends PublicDeckyToasterState { + addToast(toast: ToastData): void; + removeToast(toast: ToastData): void; +} + +const DeckyToasterContext = createContext<DeckyToasterContext>(null as any); + +export const useDeckyToasterState = () => useContext(DeckyToasterContext); + +interface Props { + deckyToasterState: DeckyToasterState; +} + +export const DeckyToasterStateContextProvider: FC<Props> = ({ children, deckyToasterState }) => { + const [publicDeckyToasterState, setPublicDeckyToasterState] = useState<PublicDeckyToasterState>({ + ...deckyToasterState.publicState(), + }); + + useEffect(() => { + function onUpdate() { + setPublicDeckyToasterState({ ...deckyToasterState.publicState() }); + } + + deckyToasterState.eventBus.addEventListener('update', onUpdate); + + return () => deckyToasterState.eventBus.removeEventListener('update', onUpdate); + }, []); + + const addToast = deckyToasterState.addToast.bind(deckyToasterState); + const removeToast = deckyToasterState.removeToast.bind(deckyToasterState); + + return ( + <DeckyToasterContext.Provider value={{ ...publicDeckyToasterState, addToast, removeToast }}> + {children} + </DeckyToasterContext.Provider> + ); +}; |
