import { Action } from 'history'; import { FunctionComponent, useEffect } from 'react'; import { useLocation, useNavigationType } from 'react-router-dom'; import globalize from 'lib/globalize'; import type { RestoreViewFailResponse } from 'types/viewManager'; import viewManager from './viewManager'; export interface ViewManagerPageProps { controller: string view: string type?: string isFullscreen?: boolean isNowPlayingBarEnabled?: boolean isThemeMediaSupported?: boolean transition?: string } interface ViewOptions { url: string type?: string // eslint-disable-next-line @typescript-eslint/no-explicit-any state: any autoFocus: boolean fullscreen?: boolean transition?: string options: { supportsThemeMedia?: boolean enableMediaControl?: boolean } } const loadView = async (controller: string, view: string, viewOptions: ViewOptions) => { const [ controllerFactory, viewHtml ] = await Promise.all([ import(/* webpackChunkName: "[request]" */ `../../controllers/${controller}`), import(/* webpackChunkName: "[request]" */ `../../controllers/${view}`) .then(html => globalize.translateHtml(html)) ]); viewManager.loadView({ ...viewOptions, controllerFactory, view: viewHtml }); }; /** * Page component that renders legacy views via the ViewManager. * NOTE: Any new pages should use the generic Page component instead. */ const ViewManagerPage: FunctionComponent = ({ controller, view, type, isFullscreen = false, isNowPlayingBarEnabled = true, isThemeMediaSupported = false, transition }) => { const location = useLocation(); const navigationType = useNavigationType(); useEffect(() => { const loadPage = () => { const viewOptions = { url: location.pathname + location.search, type, state: location.state, autoFocus: false, fullscreen: isFullscreen, transition, options: { supportsThemeMedia: isThemeMediaSupported, enableMediaControl: isNowPlayingBarEnabled } }; if (navigationType !== Action.Pop) { console.debug('[ViewManagerPage] loading view [%s]', view); return loadView(controller, view, viewOptions); } console.debug('[ViewManagerPage] restoring view [%s]', view); return viewManager.tryRestoreView(viewOptions) .catch(async (result?: RestoreViewFailResponse) => { if (!result?.cancelled) { console.debug('[ViewManagerPage] restore failed; loading view [%s]', view); return loadView(controller, view, viewOptions); } }); }; loadPage(); }, // location.state and navigationType are NOT included as dependencies here since dialogs will update state while the current view stays the same // eslint-disable-next-line react-hooks/exhaustive-deps [ controller, view, type, isFullscreen, isNowPlayingBarEnabled, isThemeMediaSupported, transition, location.pathname, location.search ]); return null; }; export default ViewManagerPage;