Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace history syncing with RouterHistory #5825

Merged
merged 3 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions src/RootApp.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import loadable from '@loadable/component';
import { History } from '@remix-run/router';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import React from 'react';
Expand All @@ -8,21 +6,14 @@ import { ApiProvider } from 'hooks/useApi';
import { WebConfigProvider } from 'hooks/useWebConfig';
import { queryClient } from 'utils/query/queryClient';

const StableAppRouter = loadable(() => import('./apps/stable/AppRouter'));
const RootAppRouter = loadable(() => import('./RootAppRouter'));

const RootApp = ({ history }: Readonly<{ history: History }>) => {
const layoutMode = localStorage.getItem('layout');
const isExperimentalLayout = layoutMode === 'experimental';
import RootAppRouter from './RootAppRouter';

const RootApp = () => {
return (
<QueryClientProvider client={queryClient}>
<ApiProvider>
<WebConfigProvider>
{isExperimentalLayout ?
<RootAppRouter history={history} /> :
<StableAppRouter history={history} />
}
<RootAppRouter />
</WebConfigProvider>
</ApiProvider>
<ReactQueryDevtools initialIsOpen={false} />
Expand Down
24 changes: 16 additions & 8 deletions src/RootAppRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@

import { History } from '@remix-run/router';
import React from 'react';
import {
RouterProvider,
createHashRouter,
Outlet
Outlet,
useLocation
} from 'react-router-dom';

import { DASHBOARD_APP_PATHS, DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';
import { EXPERIMENTAL_APP_ROUTES } from 'apps/experimental/routes/routes';
import { STABLE_APP_ROUTES } from 'apps/stable/routes/routes';
import AppHeader from 'components/AppHeader';
import Backdrop from 'components/Backdrop';
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
import { DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';
import { createRouterHistory } from 'components/router/routerHistory';
import UserThemeProvider from 'themes/UserThemeProvider';

const layoutMode = localStorage.getItem('layout');
const isExperimentalLayout = layoutMode === 'experimental';

const router = createHashRouter([
{
element: <RootAppLayout />,
children: [
...EXPERIMENTAL_APP_ROUTES,
...(isExperimentalLayout ? EXPERIMENTAL_APP_ROUTES : STABLE_APP_ROUTES),
...DASHBOARD_APP_ROUTES
]
}
]);

export default function RootAppRouter({ history }: Readonly<{ history: History}>) {
useLegacyRouterSync({ router, history });
export const history = createRouterHistory(router);

export default function RootAppRouter() {
return <RouterProvider router={router} />;
}

Expand All @@ -35,10 +39,14 @@ export default function RootAppRouter({ history }: Readonly<{ history: History}>
* NOTE: The app will crash if these get removed from the DOM.
*/
function RootAppLayout() {
const location = useLocation();
const isNewLayoutPath = Object.values(DASHBOARD_APP_PATHS)
.some(path => location.pathname.startsWith(`/${path}`));

return (
<UserThemeProvider>
<Backdrop />
<AppHeader isHidden />
<AppHeader isHidden={isExperimentalLayout || isNewLayoutPath} />

<Outlet />
</UserThemeProvider>
Expand Down
10 changes: 9 additions & 1 deletion src/apps/experimental/routes/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import ConnectionRequired from 'components/ConnectionRequired';
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import { toRedirectRoute } from 'components/router/Redirect';
import AppLayout from '../AppLayout';

import { ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
import VideoPage from './video';
import loadable from '@loadable/component';
import BangRedirect from 'components/router/BangRedirect';

const AppLayout = loadable(() => import('../AppLayout'));

export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
{
Expand Down Expand Up @@ -38,6 +41,11 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
]
},

{
path: '!/*',
Component: BangRedirect
},

/* Redirects for old paths */
...REDIRECTS.map(toRedirectRoute)
];
43 changes: 0 additions & 43 deletions src/apps/stable/AppRouter.tsx

This file was deleted.

6 changes: 6 additions & 0 deletions src/apps/stable/routes/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import AppLayout from '../AppLayout';
import { REDIRECTS } from './_redirects';
import { ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
import BangRedirect from 'components/router/BangRedirect';

export const STABLE_APP_ROUTES: RouteObject[] = [
{
Expand All @@ -32,6 +33,11 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
]
},

{
path: '!/*',
Component: BangRedirect
},

/* Redirects for old paths */
...REDIRECTS.map(toRedirectRoute)
];
3 changes: 2 additions & 1 deletion src/components/dialogHelper/dialogHelper.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { history } from '../router/appRouter';
import focusManager from '../focusManager';
import browser from '../../scripts/browser';
import layoutManager from '../layoutManager';
import inputManager from '../../scripts/inputManager';
import { toBoolean } from '../../utils/string.ts';
import dom from '../../scripts/dom';

import { history } from 'RootAppRouter';

import './dialoghelper.scss';
import '../../styles/scrollstyles.scss';

Expand Down
34 changes: 34 additions & 0 deletions src/components/router/BangRedirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useMemo } from 'react';
import { Navigate, useLocation } from 'react-router-dom';

const BangRedirect = () => {
const location = useLocation();

const to = useMemo(() => {
const _to = {
search: location.search,
hash: location.hash
};

if (location.pathname.startsWith('/!/')) {
return { ..._to, pathname: location.pathname.substring(2) };
} else if (location.pathname.startsWith('/!')) {
return { ..._to, pathname: location.pathname.replace(/^\/!/, '/') };
} else if (location.pathname.startsWith('!')) {
return { ..._to, pathname: location.pathname.substring(1) };
}
}, [ location ]);

if (!to) return null;

console.warn('[BangRedirect] You are using a deprecated URL format. This will stop working in a future Jellyfin update.');

return (
<Navigate
replace
to={to}
/>
);
};

export default BangRedirect;
5 changes: 2 additions & 3 deletions src/components/router/appRouter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
import { Action, createHashHistory } from 'history';
import { Action } from 'history';

import { appHost } from '../apphost';
import { clearBackdrop, setBackdropTransparency } from '../backdrop/backdrop';
Expand All @@ -15,8 +15,7 @@ import { queryClient } from 'utils/query/queryClient';
import { getItemQuery } from 'hooks/useItem';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import { ConnectionState } from 'utils/jellyfin-apiclient/ConnectionState.ts';

export const history = createHashHistory();
import { history } from 'RootAppRouter';

/**
* Page types of "no return" (when "Go back" should behave differently, probably quitting the application).
Expand Down
73 changes: 73 additions & 0 deletions src/components/router/routerHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { Router, RouterState } from '@remix-run/router';
import type { History, Listener, To } from 'history';

import Events, { type Event } from 'utils/events';

const HISTORY_UPDATE_EVENT = 'HISTORY_UPDATE';

export class RouterHistory implements History {
_router: Router;
createHref: (arg: any) => string;

constructor(router: Router) {
this._router = router;

this._router.subscribe(state => {
console.debug('[RouterHistory] history update', state);
Events.trigger(document, HISTORY_UPDATE_EVENT, [ state ]);
});

this.createHref = router.createHref;
}

get action() {
return this._router.state.historyAction;
}

get location() {
return this._router.state.location;
}

back() {
void this._router.navigate(-1);
}

forward() {
void this._router.navigate(1);
}

go(delta: number) {
void this._router.navigate(delta);
}

push(to: To, state?: any) {
void this._router.navigate(to, { state });
}

replace(to: To, state?: any): void {
void this._router.navigate(to, { state, replace: true });
}

block() {
// NOTE: We don't seem to use this functionality, so leaving it unimplemented.
throw new Error('`history.block()` is not implemented');
return () => undefined;
}

listen(listener: Listener) {
const compatListener = (_e: Event, state: RouterState) => {
return listener({ action: state.historyAction, location: state.location });
};

Events.on(document, HISTORY_UPDATE_EVENT, compatListener);

return () => Events.off(document, HISTORY_UPDATE_EVENT, compatListener);
}
}

export const createRouterHistory = (router: Router): History => {
return new RouterHistory(router);
};

/* eslint-enable @typescript-eslint/no-explicit-any */
71 changes: 0 additions & 71 deletions src/hooks/useLegacyRouterSync.ts

This file was deleted.

Loading
Loading