diff --git a/src/components/viewManager/ViewManagerPage.tsx b/src/components/viewManager/ViewManagerPage.tsx new file mode 100644 index 0000000000..aba382dacc --- /dev/null +++ b/src/components/viewManager/ViewManagerPage.tsx @@ -0,0 +1,80 @@ +import React, { FunctionComponent, useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; + +import globalize from '../../scripts/globalize'; +import viewManager from './viewManager'; + +export interface ViewManagerPageProps { + controller: string + view: string + type?: string + isFullscreen?: boolean + isNowPlayingBarEnabled?: boolean + isThemeMediaSupported?: boolean + transition?: string +} + +/** + * 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(); + + useEffect(() => { + const loadPage = async () => { + const [ controllerFactory, viewHtml ] = await Promise.all([ + import(/* webpackChunkName: "[request]" */ `../../controllers/${controller}`), + import(/* webpackChunkName: "[request]" */ `../../controllers/${view}`) + .then(html => globalize.translateHtml(html)) + ]); + + const viewOptions = { + url: location.pathname + location.search, + controllerFactory, + view: viewHtml, + type, + state: location.state, + autoFocus: false, + fullscreen: isFullscreen, + transition, + options: { + supportsThemeMedia: isThemeMediaSupported, + enableMediaControl: isNowPlayingBarEnabled + } + }; + + viewManager.tryRestoreView(viewOptions) + .catch((result?: any) => { + if (!result || !result.cancelled) { + viewManager.loadView(viewOptions); + } + }); + }; + + loadPage(); + }, [ + controller, + view, + type, + isFullscreen, + isNowPlayingBarEnabled, + isThemeMediaSupported, + transition, + location.pathname, + location.search, + location.state + ]); + + return <>; +}; + +export default ViewManagerPage; diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index 03138797c9..c9a64b658a 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -167,7 +167,7 @@ class ViewManager { } return viewContainer.tryRestoreView(options).then(function (view) { - onViewChanging(); + if (onViewChanging) onViewChanging(); onViewChange(view, options, true); }); } diff --git a/src/routes/index.tsx b/src/routes/index.tsx index d18ce561e1..086caca909 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Navigate, Route, Routes } from 'react-router-dom'; import ConnectionRequired from '../components/ConnectionRequired'; +import { LEGACY_USER_ROUTES, toViewManagerPageRoute } from './legacyRoutes'; import UserNew from './user/usernew'; import Search from './search'; import UserEdit from './user/useredit'; @@ -22,6 +23,8 @@ const AppRoutes = () => ( } /> } /> } /> + + {LEGACY_USER_ROUTES.map(toViewManagerPageRoute)} {/* Admin routes */} diff --git a/src/routes/legacyRoutes/index.tsx b/src/routes/legacyRoutes/index.tsx new file mode 100644 index 0000000000..2bcced2666 --- /dev/null +++ b/src/routes/legacyRoutes/index.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Route } from 'react-router-dom'; + +import ViewManagerPage, { ViewManagerPageProps } from '../../components/viewManager/ViewManagerPage'; + +export interface LegacyRoute { + path: string, + pageProps: ViewManagerPageProps +} + +export function toViewManagerPageRoute(route: LegacyRoute) { + return ( + + } + /> + ); +} + +export * from './user'; diff --git a/src/routes/legacyRoutes/user.ts b/src/routes/legacyRoutes/user.ts new file mode 100644 index 0000000000..8f48a0ee22 --- /dev/null +++ b/src/routes/legacyRoutes/user.ts @@ -0,0 +1,96 @@ +import { LegacyRoute } from '.'; + +export const LEGACY_USER_ROUTES: LegacyRoute[] = [ + { + path: 'details', + pageProps: { + controller: 'itemDetails/index', + view: 'itemDetails/index.html' + } + }, { + path: 'list.html', + pageProps: { + controller: 'list', + view: 'list.html' + } + }, { + path: 'livetv.html', + pageProps: { + controller: 'livetv/livetvsuggested', + view: 'livetv.html' + } + }, { + path: 'music.html', + pageProps: { + controller: 'music/musicrecommended', + view: 'music/music.html' + } + }, { + path: 'mypreferencesmenu.html', + pageProps: { + controller: 'user/menu/index', + view: 'user/menu/index.html' + } + }, { + path: 'mypreferencescontrols.html', + pageProps: { + controller: 'user/controls/index', + view: 'user/controls/index.html' + } + }, { + path: 'mypreferencesdisplay.html', + pageProps: { + controller: 'user/display/index', + view: 'user/display/index.html' + } + }, { + path: 'mypreferenceshome.html', + pageProps: { + controller: 'user/home/index', + view: 'user/home/index.html' + } + }, { + path: 'mypreferencesquickconnect.html', + pageProps: { + controller: 'user/quickConnect/index', + view: 'user/quickConnect/index.html' + } + }, { + path: 'mypreferencesplayback.html', + pageProps: { + controller: 'user/playback/index', + view: 'user/playback/index.html' + } + }, { + path: 'mypreferencessubtitles.html', + pageProps: { + controller: 'user/subtitles/index', + view: 'user/subtitles/index.html' + } + }, { + path: 'tv.html', + pageProps: { + controller: 'shows/tvrecommended', + view: 'shows/tvrecommended.html' + } + }, { + path: 'video', + pageProps: { + controller: 'playback/video/index', + view: 'playback/video/index.html', + type: 'video-osd', + isFullscreen: true, + isNowPlayingBarEnabled: false, + isThemeMediaSupported: true + } + }, { + path: 'queue', + pageProps: { + controller: 'playback/queue/index', + view: 'playback/queue/index.html', + isFullscreen: true, + isNowPlayingBarEnabled: false, + isThemeMediaSupported: true + } + } +]; diff --git a/src/scripts/routes.js b/src/scripts/routes.js index a92ef28e1a..f8f68a5322 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -70,55 +70,6 @@ import { appRouter } from '../components/appRouter'; controller: 'session/resetPassword/index' }); - defineRoute({ - alias: '/mypreferencesmenu.html', - path: 'user/menu/index.html', - autoFocus: false, - controller: 'user/menu/index' - }); - - defineRoute({ - alias: '/mypreferencescontrols.html', - path: 'user/controls/index.html', - autoFocus: false, - controller: 'user/controls/index' - }); - - defineRoute({ - alias: '/mypreferencesdisplay.html', - path: 'user/display/index.html', - autoFocus: false, - controller: 'user/display/index' - }); - - defineRoute({ - alias: '/mypreferenceshome.html', - path: 'user/home/index.html', - autoFocus: false, - controller: 'user/home/index' - }); - - defineRoute({ - alias: '/mypreferencesquickconnect.html', - path: 'user/quickConnect/index.html', - autoFocus: false, - transition: 'fade', - controller: 'user/quickConnect/index' - }); - defineRoute({ - alias: '/mypreferencesplayback.html', - path: 'user/playback/index.html', - autoFocus: false, - controller: 'user/playback/index' - }); - - defineRoute({ - alias: '/mypreferencessubtitles.html', - path: 'user/subtitles/index.html', - autoFocus: false, - controller: 'user/subtitles/index' - }); - defineRoute({ alias: '/dashboard.html', path: 'dashboard/dashboard.html', @@ -293,27 +244,6 @@ import { appRouter } from '../components/appRouter'; controller: 'dashboard/plugins/repositories/index' }); - defineRoute({ - alias: '/list.html', - path: 'list.html', - autoFocus: false, - controller: 'list' - }); - - defineRoute({ - alias: '/details', - path: 'itemDetails/index.html', - controller: 'itemDetails/index', - autoFocus: false - }); - - defineRoute({ - alias: '/livetv.html', - path: 'livetv.html', - controller: 'livetv/livetvsuggested', - autoFocus: false - }); - defineRoute({ alias: '/livetvguideprovider.html', path: 'livetvguideprovider.html', @@ -345,13 +275,6 @@ import { appRouter } from '../components/appRouter'; controller: 'livetvtuner' }); - defineRoute({ - alias: '/music.html', - path: 'music/music.html', - controller: 'music/musicrecommended', - autoFocus: false - }); - defineRoute({ alias: '/installedplugins.html', path: 'dashboard/plugins/installed/index.html', @@ -400,13 +323,6 @@ import { appRouter } from '../components/appRouter'; controller: 'dashboard/streaming' }); - defineRoute({ - alias: '/tv.html', - path: 'shows/tvrecommended.html', - autoFocus: false, - controller: 'shows/tvrecommended' - }); - defineRoute({ alias: '/wizardremoteaccess.html', path: 'wizard/remote/index.html', @@ -455,27 +371,6 @@ import { appRouter } from '../components/appRouter'; anonymous: true }); - defineRoute({ - alias: '/video', - path: 'playback/video/index.html', - controller: 'playback/video/index', - autoFocus: false, - type: 'video-osd', - supportsThemeMedia: true, - fullscreen: true, - enableMediaControl: false - }); - - defineRoute({ - alias: '/queue', - path: 'playback/queue/index.html', - controller: 'playback/queue/index', - autoFocus: false, - fullscreen: true, - supportsThemeMedia: true, - enableMediaControl: false - }); - defineRoute({ path: '/configurationpage', autoFocus: false,