Fix history handling not properly handling states after update to react-router v5 (#27526)
This commit is contained in:
parent
6cf9f1211b
commit
15182d1e5e
1 changed files with 43 additions and 23 deletions
|
@ -3,7 +3,11 @@ import React from 'react';
|
|||
|
||||
import { Router as OriginalRouter } from 'react-router';
|
||||
|
||||
import type { LocationDescriptor, Path } from 'history';
|
||||
import type {
|
||||
LocationDescriptor,
|
||||
LocationDescriptorObject,
|
||||
Path,
|
||||
} from 'history';
|
||||
import { createBrowserHistory } from 'history';
|
||||
|
||||
import { layoutFromWindow } from 'mastodon/is_mobile';
|
||||
|
@ -20,39 +24,55 @@ const browserHistory = createBrowserHistory<
|
|||
const originalPush = browserHistory.push.bind(browserHistory);
|
||||
const originalReplace = browserHistory.replace.bind(browserHistory);
|
||||
|
||||
function extractRealPath(path: HistoryPath) {
|
||||
if (typeof path === 'string') return path;
|
||||
else return path.pathname;
|
||||
function normalizePath(
|
||||
path: HistoryPath,
|
||||
state?: MastodonLocationState,
|
||||
): LocationDescriptorObject<MastodonLocationState> {
|
||||
const location = typeof path === 'string' ? { pathname: path } : { ...path };
|
||||
|
||||
if (location.state === undefined && state !== undefined) {
|
||||
location.state = state;
|
||||
} else if (
|
||||
location.state !== undefined &&
|
||||
state !== undefined &&
|
||||
process.env.NODE_ENV === 'development'
|
||||
) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
'You should avoid providing a 2nd state argument to push when the 1st argument is a location-like object that already has state; it is ignored',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
layoutFromWindow() === 'multi-column' &&
|
||||
!location.pathname?.startsWith('/deck')
|
||||
) {
|
||||
location.pathname = `/deck${location.pathname}`;
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
browserHistory.push = (path: HistoryPath, state?: MastodonLocationState) => {
|
||||
state = state ?? {};
|
||||
state.fromMastodon = true;
|
||||
const location = normalizePath(path, state);
|
||||
|
||||
const realPath = extractRealPath(path);
|
||||
if (!realPath) return;
|
||||
location.state = location.state ?? {};
|
||||
location.state.fromMastodon = true;
|
||||
|
||||
if (layoutFromWindow() === 'multi-column' && !realPath.startsWith('/deck')) {
|
||||
originalPush(`/deck${realPath}`, state);
|
||||
} else {
|
||||
originalPush(path, state);
|
||||
}
|
||||
originalPush(location);
|
||||
};
|
||||
|
||||
browserHistory.replace = (path: HistoryPath, state?: MastodonLocationState) => {
|
||||
const location = normalizePath(path, state);
|
||||
|
||||
if (!location.pathname) return;
|
||||
|
||||
if (browserHistory.location.state?.fromMastodon) {
|
||||
state = state ?? {};
|
||||
state.fromMastodon = true;
|
||||
location.state = location.state ?? {};
|
||||
location.state.fromMastodon = true;
|
||||
}
|
||||
|
||||
const realPath = extractRealPath(path);
|
||||
if (!realPath) return;
|
||||
|
||||
if (layoutFromWindow() === 'multi-column' && !realPath.startsWith('/deck')) {
|
||||
originalReplace(`/deck${realPath}`, state);
|
||||
} else {
|
||||
originalReplace(path, state);
|
||||
}
|
||||
originalReplace(location);
|
||||
};
|
||||
|
||||
export const Router: React.FC<PropsWithChildren> = ({ children }) => {
|
||||
|
|
Loading…
Reference in a new issue