Skip to content

Commit

Permalink
[enhancement/localization]: sort navidrome albums by year, add more l…
Browse files Browse the repository at this point in the history
…anguage keys
  • Loading branch information
kgarner7 committed Feb 3, 2024
1 parent 86a9386 commit 24bf7ae
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ First thing to do is check that your MPV binary path is correct. Navigate to the

Feishin supports any music server that implements a [Navidrome](https://www.navidrome.org/) or [Jellyfin](https://jellyfin.org/) API. **Subsonic API is not currently supported**. This will likely be added in [later when the new Subsonic API is decided on](https://support.symfonium.app/t/subsonic-servers-participation/1233).

- [Navidrome](https://github.com/navidrome/navidrome)
- [Navidrome](https://github.com/navidrome/navidrome) version 0.48.0 and newer
- [Jellyfin](https://github.com/jellyfin/jellyfin)
- [Funkwhale](https://funkwhale.audio/) - TBD
- Subsonic-compatible servers - TBD
Expand Down
13 changes: 13 additions & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,17 @@
}
},
"page": {
"albumArtistDetail": {
"about": "About {{artist}}",
"appearsOn": "appears on",
"recentReleases": "recent releases",
"viewDiscography": "view discography",
"relatedArtists": "related $t(entity.artist_other)",
"topSongs": "top songs",
"topSongsFrom": "Top songs from {{title}}",
"viewAll": "view all",
"viewAllTracks": "view all $t(entity.track_other)"
},
"albumArtistList": {
"title": "$t(entity.albumArtist_other)"
},
Expand Down Expand Up @@ -353,6 +364,8 @@
"tracks": "$t(entity.track_other)"
},
"trackList": {
"artistTracks": "Tracks by {{artist}}",
"genreTracks": "\"{{genre}}\" $t(entity.track_other)",
"title": "$t(entity.track_other)"
}
},
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ export const albumListSortMap: AlbumListSortMap = {
rating: NDAlbumListSort.RATING,
recentlyAdded: NDAlbumListSort.RECENTLY_ADDED,
recentlyPlayed: NDAlbumListSort.PLAY_DATE,
releaseDate: undefined,
// Recent versions of Navidrome support release date, but fallback to year for now
releaseDate: NDAlbumListSort.YEAR,
songCount: NDAlbumListSort.SONG_COUNT,
year: NDAlbumListSort.YEAR,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
order={2}
weight={700}
>
Recent releases
{t('page.albumArtistDetail.recentReleases', {
postProcess: 'sentenceCase',
})}
</TextTitle>
<Button
compact
Expand All @@ -222,7 +224,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
to={artistDiscographyLink}
variant="subtle"
>
View discography
{t('page.albumArtistDetail.viewDiscography')}
</Button>
</Group>
),
Expand All @@ -238,7 +240,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
order={2}
weight={700}
>
Appears on
{t('page.albumArtistDetail.appearsOn', { postProcess: 'sentenceCase' })}
</TextTitle>
),
uniqueId: 'compilationAlbums',
Expand All @@ -252,7 +254,9 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
order={2}
weight={700}
>
Related artists
{t('page.albumArtistDetail.relatedArtists', {
postProcess: 'sentenceCase',
})}
</TextTitle>
),
uniqueId: 'similarArtists',
Expand All @@ -267,6 +271,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
recentAlbumsQuery?.data?.items,
recentAlbumsQuery.isFetching,
recentAlbumsQuery?.isLoading,
t,
]);

const playButtonBehavior = usePlayButtonBehavior();
Expand Down Expand Up @@ -381,7 +386,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
to={artistDiscographyLink}
variant="subtle"
>
View discography
{t('page.albumArtistDetail.viewDiscography')}
</Button>
<Button
compact
Expand All @@ -390,7 +395,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
to={artistSongsLink}
variant="subtle"
>
View all songs
{t('page.albumArtistDetail.viewAllTracks')}
</Button>
</Group>
{showGenres ? (
Expand Down Expand Up @@ -463,7 +468,9 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
order={2}
weight={700}
>
About {detailQuery?.data?.name}
{t('page.albumArtistDetail.about', {
artist: detailQuery?.data?.name,
})}
</TextTitle>
<Spoiler
dangerouslySetInnerHTML={{ __html: detailQuery?.data?.biography || '' }}
Expand All @@ -484,7 +491,9 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
order={2}
weight={700}
>
Top Songs
{t('page.albumArtistDetail.topSongs', {
postProcess: 'sentenceCase',
})}
</TextTitle>
<Button
compact
Expand All @@ -498,7 +507,9 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
)}
variant="subtle"
>
View all
{t('page.albumArtistDetail.viewAll', {
postProcess: 'sentenceCase',
})}
</Button>
</Group>
</Group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export const AlbumArtistDetailTopSongsListHeader = ({
<PageHeader p="1rem">
<LibraryHeaderBar>
<LibraryHeaderBar.PlayButton onClick={() => handlePlay(playButtonBehavior)} />
<LibraryHeaderBar.Title>Top songs from {title}</LibraryHeaderBar.Title>
<LibraryHeaderBar.Title>
{t('page.albumArtistDetail.topSongsFrom', { title })}
</LibraryHeaderBar.Title>
<Paper
fw="600"
px="1rem"
Expand All @@ -57,7 +59,7 @@ export const AlbumArtistDetailTopSongsListHeader = ({
icon={<RiPlayFill />}
onClick={() => handlePlay(Play.NOW)}
>
{t('player.add', { postProcess: 'sentenceCase' })}
{t('player.play', { postProcess: 'sentenceCase' })}
</DropdownMenu.Item>
<DropdownMenu.Item
icon={<RiAddBoxFill />}
Expand Down
10 changes: 6 additions & 4 deletions src/renderer/features/search/components/search-header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ChangeEvent, MutableRefObject } from 'react';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { Flex, Group, Stack } from '@mantine/core';
import debounce from 'lodash/debounce';
import { ChangeEvent, MutableRefObject } from 'react';
import { useTranslation } from 'react-i18next';
import { generatePath, Link, useParams, useSearchParams } from 'react-router-dom';
import { useCurrentServer } from '../../../store/auth.store';
import { LibraryItem } from '/@/renderer/api/types';
Expand All @@ -17,6 +18,7 @@ interface SearchHeaderProps {
}

export const SearchHeader = ({ tableRef, navigationId }: SearchHeaderProps) => {
const { t } = useTranslation();
const { itemType } = useParams() as { itemType: LibraryItem };
const [searchParams, setSearchParams] = useSearchParams();
const cq = useContainerQuery();
Expand Down Expand Up @@ -70,7 +72,7 @@ export const SearchHeader = ({ tableRef, navigationId }: SearchHeaderProps) => {
}}
variant={itemType === LibraryItem.SONG ? 'filled' : 'subtle'}
>
Tracks
{t('entity.track_other', { postProcess: 'sentenceCase' })}
</Button>
<Button
compact
Expand All @@ -87,7 +89,7 @@ export const SearchHeader = ({ tableRef, navigationId }: SearchHeaderProps) => {
}}
variant={itemType === LibraryItem.ALBUM ? 'filled' : 'subtle'}
>
Albums
{t('entity.album_other', { postProcess: 'sentenceCase' })}
</Button>
<Button
compact
Expand All @@ -104,7 +106,7 @@ export const SearchHeader = ({ tableRef, navigationId }: SearchHeaderProps) => {
}}
variant={itemType === LibraryItem.ALBUM_ARTIST ? 'filled' : 'subtle'}
>
Artists
{t('entity.artist_other', { postProcess: 'sentenceCase' })}
</Button>
</Group>
</FilterBar>
Expand Down
15 changes: 10 additions & 5 deletions src/renderer/features/songs/routes/song-list-route.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback, useMemo, useRef } from 'react';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import isEmpty from 'lodash/isEmpty';
import { useTranslation } from 'react-i18next';
import { useParams, useSearchParams } from 'react-router-dom';
import { GenreListSort, LibraryItem, SongListQuery, SortOrder } from '/@/renderer/api/types';
import { ListContext } from '/@/renderer/context/list-context';
Expand All @@ -16,6 +17,7 @@ import { titleCase } from '/@/renderer/utils';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';

const TrackListRoute = () => {
const { t } = useTranslation();
const gridRef = useRef<VirtualInfiniteGridRef | null>(null);
const tableRef = useRef<AgGridReactType | null>(null);
const server = useCurrentServer();
Expand Down Expand Up @@ -132,18 +134,21 @@ const TrackListRoute = () => {
};
}, [albumArtistId, customFilters, genreId, handlePlay, pageKey]);

const artist = searchParams.get('artistName');
const title = artist
? t('page.trackList.artistTracks', { artist })
: genreId
? t('page.trackList.genreTracks', { genre: titleCase(genreTitle) })
: undefined;

return (
<AnimatedPage>
<ListContext.Provider value={providerValue}>
<SongListHeader
gridRef={gridRef}
itemCount={itemCount}
tableRef={tableRef}
title={
searchParams.get('artistName') || genreId
? `"${titleCase(genreTitle)}" Tracks`
: undefined
}
title={title}
/>
<SongListContent
gridRef={gridRef}
Expand Down

0 comments on commit 24bf7ae

Please sign in to comment.