1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge pull request #6601 from thornbill/catch-all-route

This commit is contained in:
Bill Thornton 2025-03-13 12:58:02 -04:00 committed by GitHub
commit 411601ff68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 98 additions and 10 deletions

View file

@ -17,6 +17,10 @@ $drawer-width: 240px;
left: $drawer-width;
}
}
// The fallback page has no drawer
#fallbackPage {
left: 0;
}
// Hide some items from the user "settings" page that are in the drawer
#myPreferencesMenuPage {

View file

@ -5,6 +5,7 @@ import ConnectionRequired from 'components/ConnectionRequired';
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import ErrorBoundary from 'components/router/ErrorBoundary';
import FallbackRoute from 'components/router/FallbackRoute';
import { ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
@ -15,9 +16,11 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
path: '/*',
lazy: () => import('../AppLayout'),
children: [
{ index: true, element: <Navigate replace to='/home.html' /> },
{
/* User routes: Any child route of this layout is authenticated */
element: <ConnectionRequired isUserRequired />,
/* User routes */
Component: ConnectionRequired,
children: [
...ASYNC_USER_ROUTES.map(toAsyncPageRoute),
...LEGACY_USER_ROUTES.map(toViewManagerPageRoute),
@ -25,15 +28,26 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
// The video page is special since it combines new controls with the legacy view
{
path: 'video',
element: <VideoPage />
Component: VideoPage
}
],
ErrorBoundary
},
/* Public routes */
{ index: true, element: <Navigate replace to='/home.html' /> },
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
{
/* Public routes */
element: <ConnectionRequired isUserRequired={false} />,
children: [
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute),
/* Fallback route for invalid paths */
{
path: '*',
Component: FallbackRoute
}
]
}
]
}
];

View file

@ -5,6 +5,7 @@ import ConnectionRequired from 'components/ConnectionRequired';
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import ErrorBoundary from 'components/router/ErrorBoundary';
import FallbackRoute from 'components/router/FallbackRoute';
import AppLayout from '../AppLayout';
@ -16,9 +17,11 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
path: '/*',
Component: AppLayout,
children: [
{ index: true, element: <Navigate replace to='/home.html' /> },
{
/* User routes */
element: <ConnectionRequired isUserRequired />,
Component: ConnectionRequired,
children: [
...ASYNC_USER_ROUTES.map(toAsyncPageRoute),
...LEGACY_USER_ROUTES.map(toViewManagerPageRoute)
@ -26,9 +29,19 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
ErrorBoundary
},
/* Public routes */
{ index: true, element: <Navigate replace to='/home.html' /> },
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
{
/* Public routes */
element: <ConnectionRequired isUserRequired={false} />,
children: [
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute),
/* Fallback route for invalid paths */
{
path: '*',
Component: FallbackRoute
}
]
}
]
}
];

View file

@ -0,0 +1,55 @@
import React, { useMemo } from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import Page from 'components/Page';
import globalize from 'lib/globalize';
import LinkButton from 'elements/emby-button/LinkButton';
const FallbackRoute = () => {
const location = useLocation();
// Check if the requested path should be redirected
const to = useMemo(() => {
const _to = {
search: location.search,
hash: location.hash
};
// If a path ends in ".html", redirect to the path with it removed
if (location.pathname.endsWith('.html')) {
return { ..._to, pathname: location.pathname.slice(0, -5) };
}
}, [ location ]);
if (to) {
console.warn('[FallbackRoute] You are using a deprecated URL format. This will stop working in a future Jellyfin update.');
return (
<Navigate
replace
to={to}
/>
);
}
return (
<Page
id='fallbackPage'
title={globalize.translate('HeaderPageNotFound')}
className='mainAnimatedPage libraryPage'
>
<div className='padded-left padded-right'>
<h1>{globalize.translate('HeaderPageNotFound')}</h1>
<p>{globalize.translate('PageNotFound')}</p>
<LinkButton
className='button-link'
href='#/home.html'
>
{globalize.translate('GoHome')}
</LinkButton>
</div>
</Page>
);
};
export default FallbackRoute;

View file

@ -473,6 +473,7 @@
"HeaderNoLyrics": "No lyrics found",
"HeaderOnNow": "On Now",
"HeaderOtherItems": "Other Items",
"HeaderPageNotFound": "Page not found",
"HeaderParentalRatings": "Parental Ratings",
"HeaderPassword": "Password",
"HeaderPasswordReset": "Password Reset",
@ -1315,6 +1316,7 @@
"PackageInstallCancelled": "{0} (version {1}) installation cancelled.",
"PackageInstallCompleted": "{0} (version {1}) installation completed.",
"PackageInstallFailed": "{0} (version {1}) installation failed.",
"PageNotFound": "This is not the page you are looking for.",
"ParentalRating": "Parental rating",
"PasswordMatchError": "Password and password confirmation must match.",
"PasswordRequiredForAdmin": "A password is required for admin accounts.",