From 42c0516a44e82e67f9a085d5c97e45ab970a24e8 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Sat, 22 Oct 2022 03:28:15 -0400 Subject: [PATCH 1/5] Add ViewManager React wrapper component --- .../viewManager/ViewManagerPage.tsx | 71 +++++++++++++++++++ src/routes/index.tsx | 4 ++ src/scripts/routes.js | 7 -- 3 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/components/viewManager/ViewManagerPage.tsx diff --git a/src/components/viewManager/ViewManagerPage.tsx b/src/components/viewManager/ViewManagerPage.tsx new file mode 100644 index 0000000000..30ab177306 --- /dev/null +++ b/src/components/viewManager/ViewManagerPage.tsx @@ -0,0 +1,71 @@ +import React, { FunctionComponent, useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; + +import globalize from '../../scripts/globalize'; +import viewManager from './viewManager'; + +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. + */ +const ViewManagerPage: FunctionComponent = ({ + controller, + view, + type, + isFullscreen = false, + isNowPlayingBarEnabled = true, + isThemeMediaSupported = false, + transition +}) => { + const location = useLocation(); + + useEffect(() => { + const loadPage = async () => { + const controllerFactory = await import(/* webpackChunkName: "[request]" */ `../../controllers/${controller}`); + + let viewHtml = await import(/* webpackChunkName: "[request]" */ `../../controllers/${view}`); + viewHtml = globalize.translateHtml(viewHtml); + + viewManager.loadView({ + url: location.pathname + location.search, + controllerFactory, + view: viewHtml, + type, + state: location.state, + autoFocus: false, + fullscreen: isFullscreen, + transition, + options: { + supportsThemeMedia: isThemeMediaSupported, + enableMediaControl: isNowPlayingBarEnabled + } + }); + }; + + loadPage(); + }, [ + controller, + view, + type, + isFullscreen, + isNowPlayingBarEnabled, + isThemeMediaSupported, + transition, + location.pathname, + location.search, + location.state + ]); + + return <>; +}; + +export default ViewManagerPage; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index d18ce561e1..97dcdc679e 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 ViewManagerPage from '../components/viewManager/ViewManagerPage'; import UserNew from './user/usernew'; import Search from './search'; import UserEdit from './user/useredit'; @@ -22,6 +23,9 @@ const AppRoutes = () => ( } /> } /> } /> + + } /> {/* Admin routes */} diff --git a/src/scripts/routes.js b/src/scripts/routes.js index a92ef28e1a..db43d45926 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -345,13 +345,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', From c5072f77f5b446ec1235e353a732a6b1a285fe50 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Mon, 24 Oct 2022 02:17:35 -0400 Subject: [PATCH 2/5] Fix restoring views --- src/components/viewManager/ViewManagerPage.tsx | 13 ++++++++++--- src/components/viewManager/viewManager.js | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/viewManager/ViewManagerPage.tsx b/src/components/viewManager/ViewManagerPage.tsx index 30ab177306..843f2fe533 100644 --- a/src/components/viewManager/ViewManagerPage.tsx +++ b/src/components/viewManager/ViewManagerPage.tsx @@ -4,7 +4,7 @@ import { useLocation } from 'react-router-dom'; import globalize from '../../scripts/globalize'; import viewManager from './viewManager'; -interface ViewManagerPageProps { +export interface ViewManagerPageProps { controller: string view: string type?: string @@ -35,7 +35,7 @@ const ViewManagerPage: FunctionComponent = ({ let viewHtml = await import(/* webpackChunkName: "[request]" */ `../../controllers/${view}`); viewHtml = globalize.translateHtml(viewHtml); - viewManager.loadView({ + const viewOptions = { url: location.pathname + location.search, controllerFactory, view: viewHtml, @@ -48,7 +48,14 @@ const ViewManagerPage: FunctionComponent = ({ supportsThemeMedia: isThemeMediaSupported, enableMediaControl: isNowPlayingBarEnabled } - }); + }; + + viewManager.tryRestoreView(viewOptions) + .catch((result?: any) => { + if (!result || !result.cancelled) { + viewManager.loadView(viewOptions); + } + }); }; loadPage(); 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); }); } From 7c96c386c2178cb1908fbaaed0d536154745a6e3 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Mon, 24 Oct 2022 10:57:25 -0400 Subject: [PATCH 3/5] Migrate all user routes to react router --- src/routes/index.tsx | 7 +-- src/routes/legacy/index.tsx | 23 ++++++++ src/routes/legacy/userRoutes.ts | 96 ++++++++++++++++++++++++++++++++ src/scripts/routes.js | 98 --------------------------------- 4 files changed, 122 insertions(+), 102 deletions(-) create mode 100644 src/routes/legacy/index.tsx create mode 100644 src/routes/legacy/userRoutes.ts diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 97dcdc679e..5b81cb8ae0 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Navigate, Route, Routes } from 'react-router-dom'; import ConnectionRequired from '../components/ConnectionRequired'; -import ViewManagerPage from '../components/viewManager/ViewManagerPage'; +import { LEGACY_USER_ROUTES, toViewManagerPageRoute } from './legacy'; import UserNew from './user/usernew'; import Search from './search'; import UserEdit from './user/useredit'; @@ -23,9 +23,8 @@ const AppRoutes = () => ( } /> } /> } /> - - } /> + + {LEGACY_USER_ROUTES.map(toViewManagerPageRoute)} {/* Admin routes */} diff --git a/src/routes/legacy/index.tsx b/src/routes/legacy/index.tsx new file mode 100644 index 0000000000..a3b732f969 --- /dev/null +++ b/src/routes/legacy/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 './userRoutes'; diff --git a/src/routes/legacy/userRoutes.ts b/src/routes/legacy/userRoutes.ts new file mode 100644 index 0000000000..8f48a0ee22 --- /dev/null +++ b/src/routes/legacy/userRoutes.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 db43d45926..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', @@ -393,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', @@ -448,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, From 2094a7a8c2beb23d552dbbe0792a029050237601 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 25 Oct 2022 12:39:12 -0400 Subject: [PATCH 4/5] Optimize loading controller and view --- src/components/viewManager/ViewManagerPage.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/viewManager/ViewManagerPage.tsx b/src/components/viewManager/ViewManagerPage.tsx index 843f2fe533..aba382dacc 100644 --- a/src/components/viewManager/ViewManagerPage.tsx +++ b/src/components/viewManager/ViewManagerPage.tsx @@ -16,6 +16,7 @@ export interface ViewManagerPageProps { /** * Page component that renders legacy views via the ViewManager. + * NOTE: Any new pages should use the generic Page component instead. */ const ViewManagerPage: FunctionComponent = ({ controller, @@ -30,10 +31,11 @@ const ViewManagerPage: FunctionComponent = ({ useEffect(() => { const loadPage = async () => { - const controllerFactory = await import(/* webpackChunkName: "[request]" */ `../../controllers/${controller}`); - - let viewHtml = await import(/* webpackChunkName: "[request]" */ `../../controllers/${view}`); - viewHtml = globalize.translateHtml(viewHtml); + 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, From c4a58c713354b1817b56e55467af854051784c0a Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 1 Nov 2022 16:44:51 -0400 Subject: [PATCH 5/5] Restructure legacy route code --- src/routes/index.tsx | 2 +- src/routes/{legacy => legacyRoutes}/index.tsx | 2 +- src/routes/{legacy/userRoutes.ts => legacyRoutes/user.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/routes/{legacy => legacyRoutes}/index.tsx (94%) rename src/routes/{legacy/userRoutes.ts => legacyRoutes/user.ts} (100%) diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 5b81cb8ae0..086caca909 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -2,7 +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 './legacy'; +import { LEGACY_USER_ROUTES, toViewManagerPageRoute } from './legacyRoutes'; import UserNew from './user/usernew'; import Search from './search'; import UserEdit from './user/useredit'; diff --git a/src/routes/legacy/index.tsx b/src/routes/legacyRoutes/index.tsx similarity index 94% rename from src/routes/legacy/index.tsx rename to src/routes/legacyRoutes/index.tsx index a3b732f969..2bcced2666 100644 --- a/src/routes/legacy/index.tsx +++ b/src/routes/legacyRoutes/index.tsx @@ -20,4 +20,4 @@ export function toViewManagerPageRoute(route: LegacyRoute) { ); } -export * from './userRoutes'; +export * from './user'; diff --git a/src/routes/legacy/userRoutes.ts b/src/routes/legacyRoutes/user.ts similarity index 100% rename from src/routes/legacy/userRoutes.ts rename to src/routes/legacyRoutes/user.ts