1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- import type { PropsWithChildren } from 'react';
- import React from 'react';
- import { Router as OriginalRouter, useHistory } from 'react-router';
- import type {
- LocationDescriptor,
- LocationDescriptorObject,
- Path,
- } from 'history';
- import { createBrowserHistory } from 'history';
- import { layoutFromWindow } from 'mastodon/is_mobile';
- import { isDevelopment } from 'mastodon/utils/environment';
- interface MastodonLocationState {
- fromMastodon?: boolean;
- mastodonModalKey?: string;
- }
- type LocationState = MastodonLocationState | null | undefined;
- type HistoryPath = Path | LocationDescriptor<LocationState>;
- const browserHistory = createBrowserHistory<LocationState>();
- const originalPush = browserHistory.push.bind(browserHistory);
- const originalReplace = browserHistory.replace.bind(browserHistory);
- export function useAppHistory() {
- return useHistory<LocationState>();
- }
- function normalizePath(
- path: HistoryPath,
- state?: LocationState,
- ): LocationDescriptorObject<LocationState> {
- const location = typeof path === 'string' ? { pathname: path } : { ...path };
- if (location.state === undefined && state !== undefined) {
- location.state = state;
- } else if (
- location.state !== undefined &&
- state !== undefined &&
- isDevelopment()
- ) {
- // 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) => {
- const location = normalizePath(path, state);
- location.state = location.state ?? {};
- location.state.fromMastodon = true;
- originalPush(location);
- };
- browserHistory.replace = (path: HistoryPath, state?: MastodonLocationState) => {
- const location = normalizePath(path, state);
- if (!location.pathname) return;
- if (browserHistory.location.state?.fromMastodon) {
- location.state = location.state ?? {};
- location.state.fromMastodon = true;
- }
- originalReplace(location);
- };
- export const Router: React.FC<PropsWithChildren> = ({ children }) => {
- return <OriginalRouter history={browserHistory}>{children}</OriginalRouter>;
- };
|