[enhancement]: Support react-router links in Modal (#586)
This commit is contained in:
parent
04b4d92f69
commit
d03a3a11eb
3 changed files with 198 additions and 147 deletions
|
@ -3,10 +3,9 @@ import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-mod
|
||||||
import { ModuleRegistry } from '@ag-grid-community/core';
|
import { ModuleRegistry } from '@ag-grid-community/core';
|
||||||
import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model';
|
import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model';
|
||||||
import { MantineProvider } from '@mantine/core';
|
import { MantineProvider } from '@mantine/core';
|
||||||
import { ModalsProvider } from '@mantine/modals';
|
|
||||||
import isElectron from 'is-electron';
|
import isElectron from 'is-electron';
|
||||||
import { initSimpleImg } from 'react-simple-img';
|
import { initSimpleImg } from 'react-simple-img';
|
||||||
import { BaseContextModal, toast } from './components';
|
import { toast } from './components';
|
||||||
import { useTheme } from './hooks';
|
import { useTheme } from './hooks';
|
||||||
import { IsUpdatedDialog } from './is-updated-dialog';
|
import { IsUpdatedDialog } from './is-updated-dialog';
|
||||||
import { AppRouter } from './router/app-router';
|
import { AppRouter } from './router/app-router';
|
||||||
|
@ -20,7 +19,6 @@ import './styles/global.scss';
|
||||||
import { ContextMenuProvider } from '/@/renderer/features/context-menu';
|
import { ContextMenuProvider } from '/@/renderer/features/context-menu';
|
||||||
import { useHandlePlayQueueAdd } from '/@/renderer/features/player/hooks/use-handle-playqueue-add';
|
import { useHandlePlayQueueAdd } from '/@/renderer/features/player/hooks/use-handle-playqueue-add';
|
||||||
import { PlayQueueHandlerContext } from '/@/renderer/features/player';
|
import { PlayQueueHandlerContext } from '/@/renderer/features/player';
|
||||||
import { AddToPlaylistContextModal } from '/@/renderer/features/playlists';
|
|
||||||
import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings';
|
import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings';
|
||||||
import { PlayerState, usePlayerStore, useQueueControls } from '/@/renderer/store';
|
import { PlayerState, usePlayerStore, useQueueControls } from '/@/renderer/store';
|
||||||
import { FontType, PlaybackType, PlayerStatus } from '/@/renderer/types';
|
import { FontType, PlaybackType, PlayerStatus } from '/@/renderer/types';
|
||||||
|
@ -246,27 +244,11 @@ export const App = () => {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ModalsProvider
|
<PlayQueueHandlerContext.Provider value={providerValue}>
|
||||||
modalProps={{
|
<ContextMenuProvider>
|
||||||
centered: true,
|
<AppRouter />
|
||||||
styles: {
|
</ContextMenuProvider>
|
||||||
body: { position: 'relative' },
|
</PlayQueueHandlerContext.Provider>
|
||||||
content: { overflow: 'auto' },
|
|
||||||
},
|
|
||||||
transitionProps: {
|
|
||||||
duration: 300,
|
|
||||||
exitDuration: 300,
|
|
||||||
transition: 'fade',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
modals={{ addToPlaylist: AddToPlaylistContextModal, base: BaseContextModal }}
|
|
||||||
>
|
|
||||||
<PlayQueueHandlerContext.Provider value={providerValue}>
|
|
||||||
<ContextMenuProvider>
|
|
||||||
<AppRouter />
|
|
||||||
</ContextMenuProvider>
|
|
||||||
</PlayQueueHandlerContext.Provider>
|
|
||||||
</ModalsProvider>
|
|
||||||
<IsUpdatedDialog />
|
<IsUpdatedDialog />
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,10 +7,13 @@ import { Album, AlbumArtist, AnyLibraryItem, LibraryItem, Song } from '/@/render
|
||||||
import { formatDurationString } from '/@/renderer/utils';
|
import { formatDurationString } from '/@/renderer/utils';
|
||||||
import { formatSizeString } from '/@/renderer/utils/format-size-string';
|
import { formatSizeString } from '/@/renderer/utils/format-size-string';
|
||||||
import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify';
|
import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify';
|
||||||
import { Rating, Spoiler } from '/@/renderer/components';
|
import { Rating, Spoiler, Text } from '/@/renderer/components';
|
||||||
import { sanitize } from '/@/renderer/utils/sanitize';
|
import { sanitize } from '/@/renderer/utils/sanitize';
|
||||||
import { SongPath } from '/@/renderer/features/item-details/components/song-path';
|
import { SongPath } from '/@/renderer/features/item-details/components/song-path';
|
||||||
import { SEPARATOR_STRING } from '/@/renderer/api/utils';
|
import { generatePath } from 'react-router';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
|
import { Separator } from '/@/renderer/components/separator';
|
||||||
|
|
||||||
export type ItemDetailsModalProps = {
|
export type ItemDetailsModalProps = {
|
||||||
item: Album | AlbumArtist | Song;
|
item: Album | AlbumArtist | Song;
|
||||||
|
@ -43,8 +46,28 @@ const handleRow = <T extends AnyLibraryItem>(t: TFunction, item: T, rule: ItemDe
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatArtists = (item: Album | Song) =>
|
const formatArtists = (isAlbumArtist: boolean) => (item: Album | Song) =>
|
||||||
item.albumArtists?.map((artist) => artist.name).join(SEPARATOR_STRING);
|
(isAlbumArtist ? item.albumArtists : item.artists)?.map((artist, index) => (
|
||||||
|
<span key={artist.id}>
|
||||||
|
{index > 0 && <Separator />}
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
component={Link}
|
||||||
|
overflow="visible"
|
||||||
|
size="md"
|
||||||
|
to={
|
||||||
|
artist.id
|
||||||
|
? generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, {
|
||||||
|
albumArtistId: artist.id,
|
||||||
|
})
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
weight={500}
|
||||||
|
>
|
||||||
|
{artist.name || '—'}
|
||||||
|
</Text>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
|
||||||
const formatComment = (item: Album | Song) =>
|
const formatComment = (item: Album | Song) =>
|
||||||
item.comment ? <Spoiler maxHeight={50}>{replaceURLWithHTMLLinks(item.comment)}</Spoiler> : null;
|
item.comment ? <Spoiler maxHeight={50}>{replaceURLWithHTMLLinks(item.comment)}</Spoiler> : null;
|
||||||
|
@ -52,7 +75,27 @@ const formatComment = (item: Album | Song) =>
|
||||||
const formatDate = (key: string | null) => (key ? dayjs(key).fromNow() : '');
|
const formatDate = (key: string | null) => (key ? dayjs(key).fromNow() : '');
|
||||||
|
|
||||||
const formatGenre = (item: Album | AlbumArtist | Song) =>
|
const formatGenre = (item: Album | AlbumArtist | Song) =>
|
||||||
item.genres?.map((genre) => genre.name).join(SEPARATOR_STRING);
|
item.genres?.map((genre, index) => (
|
||||||
|
<span key={genre.id}>
|
||||||
|
{index > 0 && <Separator />}
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
component={Link}
|
||||||
|
overflow="visible"
|
||||||
|
size="md"
|
||||||
|
to={
|
||||||
|
genre.id
|
||||||
|
? generatePath(AppRoute.LIBRARY_GENRES_SONGS, {
|
||||||
|
genreId: genre.id,
|
||||||
|
})
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
weight={500}
|
||||||
|
>
|
||||||
|
{genre.name || '—'}
|
||||||
|
</Text>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
|
||||||
const formatRating = (item: Album | AlbumArtist | Song) =>
|
const formatRating = (item: Album | AlbumArtist | Song) =>
|
||||||
item.userRating !== null ? (
|
item.userRating !== null ? (
|
||||||
|
@ -67,7 +110,7 @@ const BoolField = (key: boolean) =>
|
||||||
|
|
||||||
const AlbumPropertyMapping: ItemDetailRow<Album>[] = [
|
const AlbumPropertyMapping: ItemDetailRow<Album>[] = [
|
||||||
{ key: 'name', label: 'common.title' },
|
{ key: 'name', label: 'common.title' },
|
||||||
{ label: 'entity.albumArtist_one', render: formatArtists },
|
{ label: 'entity.albumArtist_one', render: formatArtists(true) },
|
||||||
{ label: 'entity.genre_other', render: formatGenre },
|
{ label: 'entity.genre_other', render: formatGenre },
|
||||||
{
|
{
|
||||||
label: 'common.duration',
|
label: 'common.duration',
|
||||||
|
@ -159,13 +202,32 @@ const AlbumArtistPropertyMapping: ItemDetailRow<AlbumArtist>[] = [
|
||||||
const SongPropertyMapping: ItemDetailRow<Song>[] = [
|
const SongPropertyMapping: ItemDetailRow<Song>[] = [
|
||||||
{ key: 'name', label: 'common.title' },
|
{ key: 'name', label: 'common.title' },
|
||||||
{ key: 'path', label: 'common.path', render: SongPath },
|
{ key: 'path', label: 'common.path', render: SongPath },
|
||||||
{ label: 'entity.albumArtist_one', render: formatArtists },
|
{ label: 'entity.albumArtist_one', render: formatArtists(true) },
|
||||||
|
{ key: 'artists', label: 'entity.artist_other', render: formatArtists(false) },
|
||||||
{
|
{
|
||||||
key: 'artists',
|
key: 'album',
|
||||||
label: 'entity.artist_other',
|
label: 'entity.album_one',
|
||||||
render: (song) => song.artists.map((artist) => artist.name).join(SEPARATOR_STRING),
|
render: (song) =>
|
||||||
|
song.albumId &&
|
||||||
|
song.album && (
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
component={Link}
|
||||||
|
overflow="visible"
|
||||||
|
size="md"
|
||||||
|
to={
|
||||||
|
song.albumId
|
||||||
|
? generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
|
||||||
|
albumId: song.albumId,
|
||||||
|
})
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
weight={500}
|
||||||
|
>
|
||||||
|
{song.album}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{ key: 'album', label: 'entity.album_one' },
|
|
||||||
{ key: 'discNumber', label: 'common.disc' },
|
{ key: 'discNumber', label: 'common.disc' },
|
||||||
{ key: 'trackNumber', label: 'common.trackNumber' },
|
{ key: 'trackNumber', label: 'common.trackNumber' },
|
||||||
{ key: 'releaseYear', label: 'filter.releaseYear' },
|
{ key: 'releaseYear', label: 'filter.releaseYear' },
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import { lazy, Suspense } from 'react';
|
import { lazy, Suspense } from 'react';
|
||||||
import {
|
import { Route, HashRouter, Routes } from 'react-router-dom';
|
||||||
Route,
|
|
||||||
createRoutesFromElements,
|
|
||||||
RouterProvider,
|
|
||||||
createHashRouter,
|
|
||||||
} from 'react-router-dom';
|
|
||||||
import { AppRoute } from './routes';
|
import { AppRoute } from './routes';
|
||||||
import { DefaultLayout } from '/@/renderer/layouts';
|
import { DefaultLayout } from '/@/renderer/layouts';
|
||||||
import { AppOutlet } from '/@/renderer/router/app-outlet';
|
import { AppOutlet } from '/@/renderer/router/app-outlet';
|
||||||
import { TitlebarOutlet } from '/@/renderer/router/titlebar-outlet';
|
import { TitlebarOutlet } from '/@/renderer/router/titlebar-outlet';
|
||||||
|
import { ModalsProvider } from '@mantine/modals';
|
||||||
|
import { BaseContextModal } from '/@/renderer/components';
|
||||||
|
import { AddToPlaylistContextModal } from '/@/renderer/features/playlists';
|
||||||
|
|
||||||
const NowPlayingRoute = lazy(
|
const NowPlayingRoute = lazy(
|
||||||
() => import('/@/renderer/features/now-playing/routes/now-playing-route'),
|
() => import('/@/renderer/features/now-playing/routes/now-playing-route'),
|
||||||
|
@ -67,137 +65,146 @@ const RouteErrorBoundary = lazy(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AppRouter = () => {
|
export const AppRouter = () => {
|
||||||
const router = createHashRouter(
|
const router = (
|
||||||
createRoutesFromElements(
|
<HashRouter future={{ v7_startTransition: true }}>
|
||||||
<>
|
<ModalsProvider
|
||||||
<Route element={<TitlebarOutlet />}>
|
modalProps={{
|
||||||
<Route
|
centered: true,
|
||||||
element={<AppOutlet />}
|
styles: {
|
||||||
errorElement={<RouteErrorBoundary />}
|
body: { position: 'relative' },
|
||||||
>
|
content: { overflow: 'auto' },
|
||||||
<Route element={<DefaultLayout />}>
|
},
|
||||||
<Route
|
transitionProps: {
|
||||||
index
|
duration: 300,
|
||||||
element={<HomeRoute />}
|
exitDuration: 300,
|
||||||
errorElement={<RouteErrorBoundary />}
|
transition: 'fade',
|
||||||
/>
|
},
|
||||||
<Route
|
}}
|
||||||
element={<HomeRoute />}
|
modals={{ addToPlaylist: AddToPlaylistContextModal, base: BaseContextModal }}
|
||||||
errorElement={<RouteErrorBoundary />}
|
>
|
||||||
path={AppRoute.HOME}
|
<Routes>
|
||||||
/>
|
<Route element={<TitlebarOutlet />}>
|
||||||
<Route
|
<Route
|
||||||
element={<SearchRoute />}
|
element={<AppOutlet />}
|
||||||
errorElement={<RouteErrorBoundary />}
|
errorElement={<RouteErrorBoundary />}
|
||||||
path={AppRoute.SEARCH}
|
>
|
||||||
/>
|
<Route element={<DefaultLayout />}>
|
||||||
<Route
|
|
||||||
element={<SettingsRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.SETTINGS}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<NowPlayingRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.NOW_PLAYING}
|
|
||||||
/>
|
|
||||||
<Route path={AppRoute.LIBRARY_GENRES}>
|
|
||||||
<Route
|
<Route
|
||||||
index
|
index
|
||||||
element={<GenreListRoute />}
|
element={<HomeRoute />}
|
||||||
errorElement={<RouteErrorBoundary />}
|
errorElement={<RouteErrorBoundary />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
element={<AlbumListRoute />}
|
element={<HomeRoute />}
|
||||||
path={AppRoute.LIBRARY_GENRES_ALBUMS}
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.HOME}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
element={<SongListRoute />}
|
element={<SearchRoute />}
|
||||||
path={AppRoute.LIBRARY_GENRES_SONGS}
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.SEARCH}
|
||||||
/>
|
/>
|
||||||
</Route>
|
|
||||||
<Route
|
|
||||||
element={<AlbumListRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.LIBRARY_ALBUMS}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<AlbumDetailRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.LIBRARY_ALBUMS_DETAIL}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<SongListRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.LIBRARY_SONGS}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<PlaylistListRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.PLAYLISTS}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<PlaylistDetailRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.PLAYLISTS_DETAIL}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<PlaylistDetailSongListRoute />}
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.PLAYLISTS_DETAIL_SONGS}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
errorElement={<RouteErrorBoundary />}
|
|
||||||
path={AppRoute.LIBRARY_ALBUM_ARTISTS}
|
|
||||||
>
|
|
||||||
<Route
|
<Route
|
||||||
index
|
element={<SettingsRoute />}
|
||||||
element={<AlbumArtistListRoute />}
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.SETTINGS}
|
||||||
/>
|
/>
|
||||||
<Route path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL}>
|
<Route
|
||||||
|
element={<NowPlayingRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.NOW_PLAYING}
|
||||||
|
/>
|
||||||
|
<Route path={AppRoute.LIBRARY_GENRES}>
|
||||||
<Route
|
<Route
|
||||||
index
|
index
|
||||||
element={<AlbumArtistDetailRoute />}
|
element={<GenreListRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
element={<AlbumListRoute />}
|
element={<AlbumListRoute />}
|
||||||
path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY}
|
path={AppRoute.LIBRARY_GENRES_ALBUMS}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
element={<SongListRoute />}
|
element={<SongListRoute />}
|
||||||
path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS}
|
path={AppRoute.LIBRARY_GENRES_SONGS}
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
element={<AlbumArtistDetailTopSongsListRoute />}
|
|
||||||
path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_TOP_SONGS}
|
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route
|
||||||
|
element={<AlbumListRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.LIBRARY_ALBUMS}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<AlbumDetailRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.LIBRARY_ALBUMS_DETAIL}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<SongListRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.LIBRARY_SONGS}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<PlaylistListRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.PLAYLISTS}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<PlaylistDetailRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.PLAYLISTS_DETAIL}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<PlaylistDetailSongListRoute />}
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.PLAYLISTS_DETAIL_SONGS}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
errorElement={<RouteErrorBoundary />}
|
||||||
|
path={AppRoute.LIBRARY_ALBUM_ARTISTS}
|
||||||
|
>
|
||||||
|
<Route
|
||||||
|
index
|
||||||
|
element={<AlbumArtistListRoute />}
|
||||||
|
/>
|
||||||
|
<Route path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL}>
|
||||||
|
<Route
|
||||||
|
index
|
||||||
|
element={<AlbumArtistDetailRoute />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<AlbumListRoute />}
|
||||||
|
path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<SongListRoute />}
|
||||||
|
path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
element={<AlbumArtistDetailTopSongsListRoute />}
|
||||||
|
path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_TOP_SONGS}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
</Route>
|
||||||
|
<Route
|
||||||
|
element={<InvalidRoute />}
|
||||||
|
path="*"
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
|
</Route>
|
||||||
|
</Route>
|
||||||
|
<Route element={<TitlebarOutlet />}>
|
||||||
|
<Route element={<DefaultLayout shell />}>
|
||||||
<Route
|
<Route
|
||||||
element={<InvalidRoute />}
|
element={<ActionRequiredRoute />}
|
||||||
path="*"
|
path={AppRoute.ACTION_REQUIRED}
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Routes>
|
||||||
<Route element={<TitlebarOutlet />}>
|
</ModalsProvider>
|
||||||
<Route element={<DefaultLayout shell />}>
|
</HashRouter>
|
||||||
<Route
|
|
||||||
element={<ActionRequiredRoute />}
|
|
||||||
path={AppRoute.ACTION_REQUIRED}
|
|
||||||
/>
|
|
||||||
</Route>
|
|
||||||
</Route>
|
|
||||||
</>,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return <Suspense fallback={<></>}>{router}</Suspense>;
|
||||||
<Suspense fallback={<></>}>
|
|
||||||
<RouterProvider
|
|
||||||
future={{ v7_startTransition: true }}
|
|
||||||
router={router}
|
|
||||||
/>
|
|
||||||
</Suspense>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
Reference in a new issue