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

Add RouterHistory to replace syncing for compatibility

This commit is contained in:
Bill Thornton 2024-07-24 15:12:10 -04:00
parent 3315ce1e89
commit dce7a36fcf
7 changed files with 86 additions and 85 deletions

View file

@ -1,71 +0,0 @@
import { Update } from 'history';
import { useLayoutEffect, useState } from 'react';
import type { History, Router } from '@remix-run/router';
interface UseLegacyRouterSyncProps {
router: Router;
history: History;
}
export function useLegacyRouterSync({ router, history }: UseLegacyRouterSyncProps) {
const [routerLocation, setRouterLocation] = useState(router.state.location);
useLayoutEffect(() => {
const onHistoryChange = async (update: Update) => {
const isSynced = router.createHref(router.state.location) === router.createHref(update.location);
/**
* Some legacy codepaths may still use the `#!` routing scheme which is unsupported with the React routing
* implementation, so we need to remove the leading `!` from the pathname. React Router already removes the
* hash for us.
*/
if (update.location.pathname.startsWith('/!/')) {
history.replace(
{ ...update.location, pathname: update.location.pathname.replace(/^\/!/, '') },
update.location.state);
} else if (update.location.pathname.startsWith('/!')) {
history.replace(
{ ...update.location, pathname: update.location.pathname.replace(/^\/!/, '/') },
update.location.state);
} else if (update.location.pathname.startsWith('!')) {
history.replace(
{ ...update.location, pathname: update.location.pathname.replace(/^!/, '') },
update.location.state);
} else if (!isSynced) {
await router.navigate(update.location, { replace: true });
}
};
const unlisten = history.listen(onHistoryChange);
return () => {
unlisten();
};
}, [history, router]);
/**
* Because the router subscription needs to be in a zero-dependencies effect, syncing changes to the router back to
* the legacy history API needs to be in a separate effect. This should run any time the router location changes.
*/
useLayoutEffect(() => {
const isSynced = router.createHref(routerLocation) === router.createHref(history.location);
if (!isSynced) {
history.replace(routerLocation);
}
}, [history, router, routerLocation]);
/**
* We want to use an effect with no dependencies here when we set up the router subscription to ensure that we only
* subscribe to the router state once. The router doesn't provide a way to remove subscribers, so we need to be
* careful to not create multiple subscribers.
*/
useLayoutEffect(() => {
router.subscribe((newState) => {
setRouterLocation((prevLocation) => {
if (newState.location !== prevLocation) {
return newState.location;
}
return prevLocation;
});
});
});
}