Update `react-router` (#397)

This commit is contained in:
Piotr Rogowski 2022-01-25 21:18:04 +01:00 committed by GitHub
parent 20299b9998
commit 0899383750
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 132 additions and 243 deletions

165
package-lock.json generated
View File

@ -26,7 +26,7 @@
"react-markdown": "^8.0.0",
"react-perfect-scrollbar": "^1.5.8",
"react-redux": "^7.2.6",
"react-router-dom": "^5.3.0",
"react-router-dom": "^6.2.1",
"react-scripts": "^5.0.0",
"uplot": "^1.6.18",
"uplot-react": "^1.1.1"
@ -10012,16 +10012,11 @@
}
},
"node_modules/history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz",
"integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==",
"dependencies": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
"@babel/runtime": "^7.7.6"
}
},
"node_modules/hoist-non-react-statics": {
@ -10755,11 +10750,6 @@
"node": ">=8"
}
},
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -13758,19 +13748,6 @@
"node": ">=6"
}
},
"node_modules/mini-create-react-context": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
"integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"tiny-warning": "^1.0.3"
},
"peerDependencies": {
"prop-types": "^15.0.0",
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/mini-css-extract-plugin": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz",
@ -14459,14 +14436,6 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"dependencies": {
"isarray": "0.0.1"
}
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@ -16868,40 +16837,27 @@
}
},
"node_modules/react-router": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz",
"integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
"integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==",
"dependencies": {
"@babel/runtime": "^7.12.13",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
"mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
"history": "^5.2.0"
},
"peerDependencies": {
"react": ">=15"
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz",
"integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
"integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==",
"dependencies": {
"@babel/runtime": "^7.12.13",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
"react-router": "5.2.1",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
"history": "^5.2.0",
"react-router": "6.2.1"
},
"peerDependencies": {
"react": ">=15"
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/react-scripts": {
@ -17284,11 +17240,6 @@
"node": ">=4"
}
},
"node_modules/resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
"node_modules/resolve-url-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz",
@ -19299,11 +19250,6 @@
"node": ">= 8"
}
},
"node_modules/value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@ -27657,16 +27603,11 @@
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz",
"integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==",
"requires": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
"@babel/runtime": "^7.7.6"
}
},
"hoist-non-react-statics": {
@ -28155,11 +28096,6 @@
"is-docker": "^2.0.0"
}
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -30289,15 +30225,6 @@
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"mini-create-react-context": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
"integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
"requires": {
"@babel/runtime": "^7.12.1",
"tiny-warning": "^1.0.3"
}
},
"mini-css-extract-plugin": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz",
@ -30807,14 +30734,6 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
}
},
"path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@ -32415,34 +32334,20 @@
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
},
"react-router": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz",
"integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
"integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==",
"requires": {
"@babel/runtime": "^7.12.13",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
"mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
"history": "^5.2.0"
}
},
"react-router-dom": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz",
"integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
"integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==",
"requires": {
"@babel/runtime": "^7.12.13",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
"react-router": "5.2.1",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
"history": "^5.2.0",
"react-router": "6.2.1"
}
},
"react-scripts": {
@ -32741,11 +32646,6 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
},
"resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
"resolve-url-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz",
@ -34226,11 +34126,6 @@
}
}
},
"value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

View File

@ -48,7 +48,7 @@
"react-markdown": "^8.0.0",
"react-perfect-scrollbar": "^1.5.8",
"react-redux": "^7.2.6",
"react-router-dom": "^5.3.0",
"react-router-dom": "^6.2.1",
"react-scripts": "^5.0.0",
"uplot": "^1.6.18",
"uplot-react": "^1.1.1"

View File

@ -1,8 +1,7 @@
import {
Switch,
Routes as ReactRoutes,
Route,
useLocation,
matchPath,
useMatch,
} from 'react-router-dom';
import {
Layout,
@ -16,7 +15,6 @@ import {
Suspense,
useCallback,
useEffect,
useMemo,
} from 'react';
import TopBar from './components/TopBar';
import StatusBar from './components/StatusBar';
@ -64,12 +62,8 @@ const App = ({ ui, navigation }: { ui: UIState, navigation: NavigationState }) =
// const [lastDialogPath, setLastDialogPath] = useState<string|null>();
// const lastDialogPath = storageGetSync('lastDialog');
const { pathname } = useLocation();
const matchedTunePath = useMemo(() => matchPath(pathname, {
path: Routes.TUNE_ROOT,
}), [pathname]);
const tuneId = (matchedTunePath?.params as any)?.tuneId;
const tunePathMatch = useMatch(`${Routes.TUNE_ROOT}/*`);
const tuneId = tunePathMatch?.params.tuneId;
useEffect(() => {
if (tuneId) {
@ -125,53 +119,53 @@ const App = ({ ui, navigation }: { ui: UIState, navigation: NavigationState }) =
<>
<Layout>
<TopBar tuneId={navigation.tuneId} />
<Switch>
<Route path={Routes.ROOT} exact>
<ReactRoutes>
<Route path={Routes.ROOT} element={
<ContentFor>
<Hub />
</ContentFor>
</Route>
<Route path={Routes.TUNE_ROOT} exact>
} />
<Route path={Routes.TUNE_ROOT} element={
<ContentFor>
<Info />
</ContentFor>
</Route>
<Route path={Routes.TUNE_TUNE}>
} />
<Route path={`${Routes.TUNE_TUNE}/*`} element={
<ContentFor marginLeft={margin}>
<Tune />
</ContentFor>
</Route>
<Route path={Routes.TUNE_LOGS} exact>
} />
<Route path={Routes.TUNE_LOGS} element={
<ContentFor marginLeft={margin}>
<Logs />
</ContentFor>
</Route>
<Route path={Routes.TUNE_DIAGNOSE} exact>
} />
<Route path={Routes.TUNE_DIAGNOSE} element={
<ContentFor marginLeft={margin}>
<Diagnose />
</ContentFor>
</Route>
<Route path={Routes.LOGIN} exact>
} />
<Route path={Routes.LOGIN} element={
<ContentFor>
<Login />
</ContentFor>
</Route>
<Route path={Routes.SIGN_UP} exact>
} />
<Route path={Routes.SIGN_UP} element={
<ContentFor>
<SignUp />
</ContentFor>
</Route>
<Route path={Routes.RESET_PASSWORD} exact>
} />
<Route path={Routes.RESET_PASSWORD} element={
<ContentFor>
<ResetPassword />
</ContentFor>
</Route>
<Route path={Routes.UPLOAD} exact>
} />
<Route path={Routes.UPLOAD} element={
<ContentFor>
<Upload />
</ContentFor>
</Route>
</Switch>
} />
</ReactRoutes>
<Result
status="warning"
title="Page not found"

View File

@ -33,7 +33,7 @@ import {
CarOutlined,
} from '@ant-design/icons';
import {
useHistory,
useNavigate,
generatePath,
} from 'react-router';
import {
@ -231,7 +231,7 @@ const buildTuneUrl = (tuneId: string, route: string) => generatePath(route, { tu
const ActionsProvider = (props: CommandPaletteProps) => {
const { config, tune, navigation } = props;
const { query } = useKBar();
const history = useHistory();
const navigate = useNavigate();
const generateActions = useCallback((types: MenusType) => {
const newActions: Action[] = [
@ -241,7 +241,7 @@ const ActionsProvider = (props: CommandPaletteProps) => {
name: 'Info',
subtitle: 'Basic information about this tune.',
icon: <InfoCircleOutlined />,
perform: () => history.push(buildTuneUrl(navigation.tuneId!, Routes.TUNE_ROOT)),
perform: () => navigate(buildTuneUrl(navigation.tuneId!, Routes.TUNE_ROOT)),
},
{
id: 'LogsAction',
@ -249,7 +249,7 @@ const ActionsProvider = (props: CommandPaletteProps) => {
name: 'Logs',
subtitle: 'Log viewer.',
icon: <FundOutlined />,
perform: () => history.push(buildTuneUrl(navigation.tuneId!, Routes.TUNE_LOGS)),
perform: () => navigate(buildTuneUrl(navigation.tuneId!, Routes.TUNE_LOGS)),
},
{
id: 'DiagnoseAction',
@ -257,7 +257,7 @@ const ActionsProvider = (props: CommandPaletteProps) => {
name: 'Diagnose',
subtitle: 'Tooth and composite logs viewer.',
icon: <SettingOutlined />,
perform: () => history.push(buildTuneUrl(navigation.tuneId!, Routes.TUNE_DIAGNOSE)),
perform: () => navigate(buildTuneUrl(navigation.tuneId!, Routes.TUNE_DIAGNOSE)),
},
];
@ -281,16 +281,17 @@ const ActionsProvider = (props: CommandPaletteProps) => {
section: types[menuName].title,
name: subMenu.title,
icon: <Icon name={subMenuName} />,
perform: () => history.push(buildUrl(navigation.tuneId!, menuName, subMenuName)),
perform: () => navigate(buildUrl(navigation.tuneId!, menuName, subMenuName)),
});
});
});
return newActions;
}, [history, navigation.tuneId]);
}, [navigate, navigation.tuneId]);
useEffect(() => {
if (Object.keys(tune.constants).length) {
// TODO: unregister old actions
query.registerActions(generateActions(config.menus));
}
}, [config.menus, generateActions, query, tune.constants]);
@ -301,7 +302,7 @@ const ActionsProvider = (props: CommandPaletteProps) => {
const CommandPalette = (props: CommandPaletteProps) => {
const { children, config, tune, navigation } = props;
const { logout } = useAuth();
const history = useHistory();
const navigate = useNavigate();
const logoutAction = useCallback(async () => {
try {
@ -320,7 +321,7 @@ const CommandPalette = (props: CommandPaletteProps) => {
name: 'Hub',
subtitle: 'Public tunes and logs.',
icon: <CarOutlined />,
perform: () => history.push(Routes.ROOT),
perform: () => navigate(Routes.ROOT),
},
{
id: 'ToggleSidebar',
@ -334,7 +335,7 @@ const CommandPalette = (props: CommandPaletteProps) => {
name: 'Upload',
subtitle: 'Upload tune and logs.',
icon: <CloudUploadOutlined />,
perform: () => history.push(Routes.UPLOAD),
perform: () => navigate(Routes.UPLOAD),
},
{
id: 'LoginAction',
@ -342,7 +343,7 @@ const CommandPalette = (props: CommandPaletteProps) => {
name: 'Login',
subtitle: 'Login using email, Google or GitHub account.',
icon: <LoginOutlined />,
perform: () => history.push(Routes.LOGIN),
perform: () => navigate(Routes.LOGIN),
},
{
id: 'SignUpAction',
@ -350,7 +351,7 @@ const CommandPalette = (props: CommandPaletteProps) => {
name: 'Sign-up',
subtitle: 'Create new account.',
icon: <UserAddOutlined />,
perform: () => history.push(Routes.SIGN_UP),
perform: () => navigate(Routes.SIGN_UP),
},
{
id: 'LogoutAction',

View File

@ -1,16 +1,13 @@
import {
useCallback,
useEffect,
useMemo,
} from 'react';
import {
matchPath,
useLocation,
useHistory,
} from 'react-router';
import {
useNavigate,
Link,
generatePath,
useMatch,
} from 'react-router-dom';
import {
Layout,
@ -72,18 +69,14 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
const { sm, lg } = useBreakpoint();
const { pathname } = useLocation();
const { currentUser, logout } = useAuth();
const history = useHistory();
const navigate = useNavigate();
const { query } = useKBar();
const buildTuneUrl = (route: string) => tuneId ? generatePath(route, { tuneId }) : null;
const matchedRootPath = useMemo(() => matchPath(pathname, {
path: Routes.ROOT,
}), [pathname]);
const matchedTuneRootPath = useMemo(() => matchPath(pathname, {
path: Routes.TUNE_ROOT,
}), [pathname]);
const matchedTabPath = useMemo(() => matchPath(pathname, {
path: Routes.TUNE_TAB,
}), [pathname]);
const rootPathMatch = useMatch(Routes.ROOT);
const tuneRootMatch = useMatch(`${Routes.TUNE_ROOT}/*`);
const tuneTuneMatch = useMatch(`${Routes.TUNE_TUNE}/*`);
const tabMatch = useMatch(`${Routes.TUNE_TAB}/*`);
const uploadMatch = useMatch(Routes.UPLOAD);
const logoutClick = useCallback(async () => {
try {
await logout();
@ -118,10 +111,10 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
<Col span={14} md={12} sm={16} style={{ textAlign: 'center' }}>
<Radio.Group
key={pathname}
defaultValue={matchedTabPath?.url || matchedTuneRootPath?.url || matchedRootPath?.url || ''}
defaultValue={tuneTuneMatch?.pathnameBase || tabMatch?.pathname || tuneRootMatch?.pathname || rootPathMatch?.pathname}
optionType="button"
buttonStyle="solid"
onChange={(e) => history.push(e.target.value)}
onChange={(e) => navigate(e.target.value)}
>
<Radio.Button value={buildTuneUrl(Routes.ROOT)}>
<Space>
@ -190,7 +183,7 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
<Button icon={<SearchOutlined />} onClick={toggleCommandPalette} />
</Tooltip>}
<Link to={Routes.UPLOAD}>
<Button icon={<CloudUploadOutlined />} type={matchedTabPath?.url === Routes.UPLOAD ? 'primary' : 'default'}>
<Button icon={<CloudUploadOutlined />} type={uploadMatch ? 'primary' : 'default'}>
{lg && 'Upload'}
</Button>
</Link>

View File

@ -7,6 +7,7 @@ import { connect } from 'react-redux';
import {
generatePath,
Link,
PathMatch,
} from 'react-router-dom';
import PerfectScrollbar from 'react-perfect-scrollbar';
import {
@ -52,14 +53,6 @@ export const buildUrl = (tuneId: string, main: string, sub: string) => generateP
dialog: sub,
});
export interface DialogMatchedPathType {
url: string;
params: {
category: string;
dialog: string;
};
}
const mapStateToProps = (state: AppState) => ({
config: state.config,
tune: state.tune,
@ -72,7 +65,7 @@ interface SideBarProps {
tune: TuneType;
ui: UIState;
navigation: NavigationState;
matchedPath: DialogMatchedPathType;
matchedPath: PathMatch<'dialog' | 'tuneId' | 'category'>;
};
const SideBar = ({ config, tune, ui, navigation, matchedPath }: SideBarProps) => {
@ -148,11 +141,11 @@ const SideBar = ({ config, tune, ui, navigation, matchedPath }: SideBarProps) =>
<Sider {...siderProps} className="app-sidebar">
<PerfectScrollbar options={{ suppressScrollX: true }}>
<Menu
defaultSelectedKeys={[matchedPath.url]}
defaultSelectedKeys={[matchedPath.pathname]}
defaultOpenKeys={ui.sidebarCollapsed ? [] : [`/${matchedPath.params.category}`]}
mode="inline"
style={{ height: '100%' }}
key={matchedPath.url}
key={matchedPath.pathname}
>
{menus}
</Menu>

View File

@ -18,7 +18,7 @@ import {
} from 'react';
import {
generatePath,
useHistory,
useNavigate,
} from 'react-router';
import useDb from '../hooks/useDb';
import { TuneDbData } from '../types/dbData';
@ -48,10 +48,10 @@ const loadingCards = (
const Hub = () => {
const [tunes, setTunes] = useState<TuneDbData[]>([]);
const { listTunes } = useDb();
const history = useHistory();
const navigate = useNavigate();
const [copied, setCopied] = useState(false);
const goToTune = (tuneId: string) => history.push(generatePath(Routes.TUNE_ROOT, { tuneId }));
const goToTune = (tuneId: string) => navigate(generatePath(Routes.TUNE_ROOT, { tuneId }));
const copyToClipboard = async (shareUrl: string) => {
if (navigator.clipboard) {

View File

@ -1,15 +1,17 @@
import { Skeleton } from 'antd';
import {
useLocation,
Route,
matchPath,
Redirect,
generatePath,
useMatch,
useNavigate,
} from 'react-router-dom';
import { connect } from 'react-redux';
import { useMemo } from 'react';
import {
useEffect,
useMemo,
} from 'react';
import { Config as ConfigType } from '@speedy-tuner/types';
import Dialog from '../components/Tune/Dialog';
import SideBar, { DialogMatchedPathType } from '../components/Tune/SideBar';
import SideBar from '../components/Tune/SideBar';
import { Routes } from '../routes';
import useConfig from '../hooks/useConfig';
import {
@ -24,14 +26,12 @@ const mapStateToProps = (state: AppState) => ({
});
const Tune = ({ navigation, config }: { navigation: NavigationState, config: ConfigType }) => {
const { pathname } = useLocation();
const dialogMatch = useMatch(Routes.TUNE_DIALOG);
const tuneRootMatch = useMatch(Routes.TUNE_TUNE);
// const { storageGetSync } = useBrowserStorage();
// const lastDialogPath = storageGetSync('lastDialog');
const { isConfigReady } = useConfig(config);
const dialogMatchedPath: DialogMatchedPathType = useMemo(() => matchPath(pathname, {
path: Routes.TUNE_DIALOG,
exact: true,
}) || { url: '', params: { category: '', dialog: '' } }, [pathname]);
const navigate = useNavigate();
const firstDialogPath = useMemo(() => {
if (!isConfigReady) {
@ -40,6 +40,7 @@ const Tune = ({ navigation, config }: { navigation: NavigationState, config: Con
const firstCategory = Object.keys(config.menus)[0];
const firstDialog = Object.keys(config.menus[firstCategory].subMenus)[0];
return generatePath(Routes.TUNE_DIALOG, {
tuneId: navigation.tuneId!,
category: firstCategory,
@ -47,15 +48,27 @@ const Tune = ({ navigation, config }: { navigation: NavigationState, config: Con
});
}, [config.menus, isConfigReady, navigation.tuneId]);
useEffect(() => {
if (tuneRootMatch && firstDialogPath) {
navigate(firstDialogPath, { replace: true });
}
}, [firstDialogPath, navigate, tuneRootMatch, isConfigReady]);
// TODO: unify loading indicators across the app
if (!isConfigReady || !dialogMatch) {
return (
<div>
<Skeleton active />
</div>
);
}
return (
<>
<Route path={Routes.TUNE_TUNE} exact>
{firstDialogPath && <Redirect to={firstDialogPath} />}
</Route>
<SideBar matchedPath={dialogMatchedPath} />
<SideBar matchedPath={dialogMatch!} />
<Dialog
name={dialogMatchedPath.params.dialog}
url={dialogMatchedPath.url}
name={dialogMatch?.params.dialog!}
url={dialogMatch?.pathname || ''}
/>
</>
);

View File

@ -36,7 +36,7 @@ import { UploadRequestOption } from 'rc-upload/lib/interface';
import { UploadFile } from 'antd/lib/upload/interface';
import {
generatePath,
useHistory,
useNavigate,
} from 'react-router-dom';
import ReactMarkdown from 'react-markdown';
import pako from 'pako';
@ -114,7 +114,7 @@ const UploadPage = () => {
const [customIniFile, setCustomIniFile] = useState<UploadedFile | null>(null);
const hasNavigatorShare = navigator.share !== undefined;
const { currentUser, refreshToken } = useAuth();
const history = useHistory();
const navigate = useNavigate();
const { removeFile, uploadFile, basePathForFile } = useServerStorage();
const { updateData } = useDb();
const requiredRules = [{ required: true, message: 'This field is required!' }];
@ -122,7 +122,7 @@ const UploadPage = () => {
const noop = () => { };
const goToNewTune = () => history.push(generatePath(Routes.TUNE_ROOT, {
const goToNewTune = () => navigate(generatePath(Routes.TUNE_ROOT, {
tuneId: newTuneId!,
}));
@ -409,7 +409,7 @@ const UploadPage = () => {
const prepareData = useCallback(async () => {
if (!currentUser) {
restrictedPage();
history.push(Routes.LOGIN);
navigate(Routes.LOGIN);
return;
}
@ -418,7 +418,7 @@ const UploadPage = () => {
await refreshToken();
if (!currentUser.emailVerified) {
emailNotVerified();
history.push(Routes.LOGIN);
navigate(Routes.LOGIN);
return;
}
@ -432,11 +432,11 @@ const UploadPage = () => {
const tuneId = nanoidCustom();
setNewTuneId(tuneId);
console.log('New tuneId:', tuneId);
}, [currentUser, history, refreshToken]);
}, [currentUser, navigate, refreshToken]);
useEffect(() => {
prepareData();
}, [currentUser, history, prepareData, refreshToken]);
}, [currentUser, prepareData, refreshToken]);
const uploadButton = (
<Space direction="vertical">

View File

@ -17,7 +17,7 @@ import {
} from '@ant-design/icons';
import {
Link,
useHistory,
useNavigate,
} from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { Routes } from '../../routes';
@ -37,9 +37,9 @@ const Login = () => {
const [isGoogleLoading, setIsGoogleLoading] = useState(false);
const [isGithubLoading, setIsGithubLoading] = useState(false);
const { login, googleAuth, githubAuth } = useAuth();
const history = useHistory();
const navigate = useNavigate();
const isAnythingLoading = isEmailLoading || isGoogleLoading || isGithubLoading;
const redirectAfterLogin = useCallback(() => history.push(Routes.UPLOAD), [history]);
const redirectAfterLogin = useCallback(() => navigate(Routes.UPLOAD), [navigate]);
const googleLogin = useCallback(async () => {
setIsGoogleLoading(true);

View File

@ -8,7 +8,7 @@ import {
import { MailOutlined } from '@ant-design/icons';
import {
Link,
useHistory,
useNavigate,
} from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { Routes } from '../../routes';
@ -25,14 +25,14 @@ const ResetPassword = () => {
const [form] = Form.useForm();
const [isLoading, setIsLoading] = useState(false);
const { resetPassword } = useAuth();
const history = useHistory();
const navigate = useNavigate();
const onFinish = async ({ email }: { form: any, email: string }) => {
setIsLoading(true);
try {
await resetPassword(email);
resetSuccessful();
history.push(Routes.LOGIN);
navigate(Routes.LOGIN);
} catch (error) {
form.resetFields();
console.warn(error);

View File

@ -11,7 +11,7 @@ import {
} from '@ant-design/icons';
import {
Link,
useHistory,
useNavigate,
} from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { Routes } from '../../routes';
@ -31,7 +31,7 @@ const SignUp = () => {
const [form] = Form.useForm();
const [isLoading, setIsLoading] = useState(false);
const { signUp } = useAuth();
const history = useHistory();
const navigate = useNavigate();
const onFinish = async ({ email, password }: { email: string, password: string }) => {
setIsLoading(true);
@ -39,7 +39,7 @@ const SignUp = () => {
await signUp(email, password);
signUpSuccessful();
emailNotVerified();
history.push(Routes.ROOT);
navigate(Routes.ROOT);
} catch (error) {
form.resetFields();
console.warn(error);