diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx
index abdbd790..b0b71eb5 100644
--- a/src/renderer/app.tsx
+++ b/src/renderer/app.tsx
@@ -3,10 +3,9 @@ import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-mod
import { ModuleRegistry } from '@ag-grid-community/core';
import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model';
import { MantineProvider } from '@mantine/core';
-import { ModalsProvider } from '@mantine/modals';
import isElectron from 'is-electron';
import { initSimpleImg } from 'react-simple-img';
-import { BaseContextModal, toast } from './components';
+import { toast } from './components';
import { useTheme } from './hooks';
import { IsUpdatedDialog } from './is-updated-dialog';
import { AppRouter } from './router/app-router';
@@ -20,7 +19,6 @@ import './styles/global.scss';
import { ContextMenuProvider } from '/@/renderer/features/context-menu';
import { useHandlePlayQueueAdd } from '/@/renderer/features/player/hooks/use-handle-playqueue-add';
import { PlayQueueHandlerContext } from '/@/renderer/features/player';
-import { AddToPlaylistContextModal } from '/@/renderer/features/playlists';
import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings';
import { PlayerState, usePlayerStore, useQueueControls } from '/@/renderer/store';
import { FontType, PlaybackType, PlayerStatus } from '/@/renderer/types';
@@ -246,27 +244,11 @@ export const App = () => {
},
}}
>
-
-
-
-
-
-
-
+
+
+
+
+
);
diff --git a/src/renderer/features/item-details/components/item-details-modal.tsx b/src/renderer/features/item-details/components/item-details-modal.tsx
index 9d2cdcd3..7c0b1bde 100644
--- a/src/renderer/features/item-details/components/item-details-modal.tsx
+++ b/src/renderer/features/item-details/components/item-details-modal.tsx
@@ -7,10 +7,13 @@ import { Album, AlbumArtist, AnyLibraryItem, LibraryItem, Song } from '/@/render
import { formatDurationString } from '/@/renderer/utils';
import { formatSizeString } from '/@/renderer/utils/format-size-string';
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 { 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 = {
item: Album | AlbumArtist | Song;
@@ -43,8 +46,28 @@ const handleRow = (t: TFunction, item: T, rule: ItemDe
);
};
-const formatArtists = (item: Album | Song) =>
- item.albumArtists?.map((artist) => artist.name).join(SEPARATOR_STRING);
+const formatArtists = (isAlbumArtist: boolean) => (item: Album | Song) =>
+ (isAlbumArtist ? item.albumArtists : item.artists)?.map((artist, index) => (
+
+ {index > 0 && }
+
+ {artist.name || '—'}
+
+
+ ));
const formatComment = (item: Album | Song) =>
item.comment ? {replaceURLWithHTMLLinks(item.comment)} : null;
@@ -52,7 +75,27 @@ const formatComment = (item: Album | Song) =>
const formatDate = (key: string | null) => (key ? dayjs(key).fromNow() : '');
const formatGenre = (item: Album | AlbumArtist | Song) =>
- item.genres?.map((genre) => genre.name).join(SEPARATOR_STRING);
+ item.genres?.map((genre, index) => (
+
+ {index > 0 && }
+
+ {genre.name || '—'}
+
+
+ ));
const formatRating = (item: Album | AlbumArtist | Song) =>
item.userRating !== null ? (
@@ -67,7 +110,7 @@ const BoolField = (key: boolean) =>
const AlbumPropertyMapping: ItemDetailRow[] = [
{ 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: 'common.duration',
@@ -159,13 +202,32 @@ const AlbumArtistPropertyMapping: ItemDetailRow[] = [
const SongPropertyMapping: ItemDetailRow[] = [
{ key: 'name', label: 'common.title' },
{ 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',
- label: 'entity.artist_other',
- render: (song) => song.artists.map((artist) => artist.name).join(SEPARATOR_STRING),
+ key: 'album',
+ label: 'entity.album_one',
+ render: (song) =>
+ song.albumId &&
+ song.album && (
+
+ {song.album}
+
+ ),
},
- { key: 'album', label: 'entity.album_one' },
{ key: 'discNumber', label: 'common.disc' },
{ key: 'trackNumber', label: 'common.trackNumber' },
{ key: 'releaseYear', label: 'filter.releaseYear' },
diff --git a/src/renderer/router/app-router.tsx b/src/renderer/router/app-router.tsx
index 41cbc628..5749c138 100644
--- a/src/renderer/router/app-router.tsx
+++ b/src/renderer/router/app-router.tsx
@@ -1,14 +1,12 @@
import { lazy, Suspense } from 'react';
-import {
- Route,
- createRoutesFromElements,
- RouterProvider,
- createHashRouter,
-} from 'react-router-dom';
+import { Route, HashRouter, Routes } from 'react-router-dom';
import { AppRoute } from './routes';
import { DefaultLayout } from '/@/renderer/layouts';
import { AppOutlet } from '/@/renderer/router/app-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(
() => import('/@/renderer/features/now-playing/routes/now-playing-route'),
@@ -67,137 +65,146 @@ const RouteErrorBoundary = lazy(
);
export const AppRouter = () => {
- const router = createHashRouter(
- createRoutesFromElements(
- <>
- }>
- }
- errorElement={}
- >
- }>
- }
- errorElement={}
- />
- }
- errorElement={}
- path={AppRoute.HOME}
- />
- }
- errorElement={}
- path={AppRoute.SEARCH}
- />
- }
- errorElement={}
- path={AppRoute.SETTINGS}
- />
- }
- errorElement={}
- path={AppRoute.NOW_PLAYING}
- />
-
+ const router = (
+
+
+
+ }>
+ }
+ errorElement={}
+ >
+ }>
}
+ element={}
errorElement={}
/>
}
- path={AppRoute.LIBRARY_GENRES_ALBUMS}
+ element={}
+ errorElement={}
+ path={AppRoute.HOME}
/>
}
- path={AppRoute.LIBRARY_GENRES_SONGS}
+ element={}
+ errorElement={}
+ path={AppRoute.SEARCH}
/>
-
- }
- errorElement={}
- path={AppRoute.LIBRARY_ALBUMS}
- />
- }
- errorElement={}
- path={AppRoute.LIBRARY_ALBUMS_DETAIL}
- />
- }
- errorElement={}
- path={AppRoute.LIBRARY_SONGS}
- />
- }
- errorElement={}
- path={AppRoute.PLAYLISTS}
- />
- }
- errorElement={}
- path={AppRoute.PLAYLISTS_DETAIL}
- />
- }
- errorElement={}
- path={AppRoute.PLAYLISTS_DETAIL_SONGS}
- />
- }
- path={AppRoute.LIBRARY_ALBUM_ARTISTS}
- >
}
+ element={}
+ errorElement={}
+ path={AppRoute.SETTINGS}
/>
-
+ }
+ errorElement={}
+ path={AppRoute.NOW_PLAYING}
+ />
+
}
+ element={}
+ errorElement={}
/>
}
- path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY}
+ path={AppRoute.LIBRARY_GENRES_ALBUMS}
/>
}
- path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS}
- />
- }
- path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_TOP_SONGS}
+ path={AppRoute.LIBRARY_GENRES_SONGS}
/>
+ }
+ errorElement={}
+ path={AppRoute.LIBRARY_ALBUMS}
+ />
+ }
+ errorElement={}
+ path={AppRoute.LIBRARY_ALBUMS_DETAIL}
+ />
+ }
+ errorElement={}
+ path={AppRoute.LIBRARY_SONGS}
+ />
+ }
+ errorElement={}
+ path={AppRoute.PLAYLISTS}
+ />
+ }
+ errorElement={}
+ path={AppRoute.PLAYLISTS_DETAIL}
+ />
+ }
+ errorElement={}
+ path={AppRoute.PLAYLISTS_DETAIL_SONGS}
+ />
+ }
+ path={AppRoute.LIBRARY_ALBUM_ARTISTS}
+ >
+ }
+ />
+
+ }
+ />
+ }
+ path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY}
+ />
+ }
+ path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS}
+ />
+ }
+ path={AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_TOP_SONGS}
+ />
+
+
+ }
+ path="*"
+ />
+
+
+ }>
+ }>
}
- path="*"
+ element={}
+ path={AppRoute.ACTION_REQUIRED}
/>
-
- }>
- }>
- }
- path={AppRoute.ACTION_REQUIRED}
- />
-
-
- >,
- ),
+
+
+
);
- return (
- >}>
-
-
- );
+ return >}>{router};
};