import { FC, memo, ReactNode } from 'react'; import { findClassModule } from '../class-mapper'; import Logger from '../logger'; import { Navigation } from '../modules/Router'; import { joinClassNames } from '../utils'; import { Focusable } from './Focusable'; const logger = new Logger('ToastRenderer'); // TODO there are more of these export enum ToastLocation { /** Big Picture popup toasts */ GAMEPADUI_POPUP = 1, /** QAM Notifications tab */ GAMEPADUI_QAM = 3, } export interface ToastData { title: ReactNode; body: ReactNode; subtext?: ReactNode; logo?: ReactNode; icon?: ReactNode; timestamp?: Date; onClick?: () => void; className?: string; contentClassName?: string; /** ms before toast popup is hidden. defaults to 5 seconds */ duration?: number; /** ms before toast is removed from the tray. Valve's logic will always remove all toasts 48h after they are first viewed regardless of this value */ expiration?: number; critical?: boolean; eType?: number; sound?: number; /** Hidden 10min after first viewed */ showNewIndicator?: boolean; playSound?: boolean; showToast?: boolean; } interface ToastProps { toast: ToastData; newIndicator?: boolean; } interface ToastRendererProps extends ToastProps { location: ToastLocation; } const templateClasses = findClassModule((m) => m.ShortTemplate) || {}; // These are memoized as they like to randomly rerender const GamepadUIPopupToast: FC> = memo(({ toast }) => { return (
{toast.logo &&
{toast.logo}
}
{toast.icon &&
{toast.icon}
}
{toast.title}
{toast.body}
); }); const GamepadUIQAMToast: FC = memo(({ toast, newIndicator }) => { // The fields aren't mismatched, the logic for these is just a bit weird. return ( { toast.onClick?.(); Navigation.CloseSideMenus(); }} className={joinClassNames(templateClasses.StandardTemplateContainer, toast.className || '', 'MillenniumGamepadUIQAMToast')} >
{toast.logo &&
{toast.logo}
}
{toast.icon &&
{toast.icon}
} {toast.title &&
{toast.title}
} {/* timestamp should always be defined by toaster */} {/* TODO check how valve does this */} {toast.timestamp &&
{toast.timestamp.toLocaleTimeString(undefined, { timeStyle: 'short' })}
}
{toast.body &&
{toast.body}
} {toast.subtext &&
{toast.subtext}
}
{newIndicator && (
)}
); }); /** @hide @internal This is not meant for external use */ export const ToastRenderer: FC = memo(({ toast, location, newIndicator }) => { switch (location) { default: logger.warn(`Toast UI not implemented for location ${location}! Falling back to GamepadUIQAMToast.`); return ; case ToastLocation.GAMEPADUI_POPUP: return ; case ToastLocation.GAMEPADUI_QAM: return ; } }); export default ToastRenderer;