Subsonic 2, general rework (#758)

This commit is contained in:
Kendall Garner 2024-09-26 04:23:08 +00:00 committed by GitHub
parent 31492fa9ef
commit 8cddbef701
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
69 changed files with 4625 additions and 3566 deletions

View file

@ -111,18 +111,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
enabled: enabledItem.recentAlbums,
},
query: {
_custom: {
jellyfin: {
...(server?.type === ServerType.JELLYFIN
? { AlbumArtistIds: albumArtistId }
: undefined),
},
navidrome: {
...(server?.type === ServerType.NAVIDROME
? { artist_id: albumArtistId, compilation: false }
: undefined),
},
},
artistIds: [albumArtistId],
limit: 15,
sortBy: AlbumListSort.RELEASE_DATE,
sortOrder: SortOrder.DESC,
@ -133,21 +122,11 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
const compilationAlbumsQuery = useAlbumList({
options: {
enabled: enabledItem.compilations,
enabled: enabledItem.compilations && server?.type !== ServerType.SUBSONIC,
},
query: {
_custom: {
jellyfin: {
...(server?.type === ServerType.JELLYFIN
? { ContributingArtistIds: albumArtistId }
: undefined),
},
navidrome: {
...(server?.type === ServerType.NAVIDROME
? { artist_id: albumArtistId, compilation: true }
: undefined),
},
},
artistIds: [albumArtistId],
compilation: true,
limit: 15,
sortBy: AlbumListSort.RELEASE_DATE,
sortOrder: SortOrder.DESC,
@ -254,7 +233,10 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
},
{
data: compilationAlbumsQuery?.data?.items,
isHidden: !compilationAlbumsQuery?.data?.items?.length || !enabledItem.compilations,
isHidden:
!compilationAlbumsQuery?.data?.items?.length ||
!enabledItem.compilations ||
server?.type === ServerType.SUBSONIC,
itemType: LibraryItem.ALBUM,
loading: compilationAlbumsQuery?.isLoading || compilationAlbumsQuery.isFetching,
order: itemOrder.compilations,
@ -301,6 +283,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
recentAlbumsQuery?.data?.items,
recentAlbumsQuery.isFetching,
recentAlbumsQuery?.isLoading,
server?.type,
t,
]);

View file

@ -26,16 +26,19 @@ export const AlbumArtistDetailHeader = forwardRef(
const metadataItems = [
{
enabled: detailQuery?.data?.albumCount,
id: 'albumCount',
secondary: false,
value: t('entity.albumWithCount', { count: detailQuery?.data?.albumCount || 0 }),
},
{
enabled: detailQuery?.data?.songCount,
id: 'songCount',
secondary: false,
value: t('entity.trackWithCount', { count: detailQuery?.data?.songCount || 0 }),
},
{
enabled: detailQuery.data?.duration,
id: 'duration',
secondary: true,
value:
@ -70,7 +73,7 @@ export const AlbumArtistDetailHeader = forwardRef(
<Stack>
<Group>
{metadataItems
.filter((i) => i.value)
.filter((i) => i.enabled)
.map((item, index) => (
<Fragment key={`item-${item.id}-${index}`}>
{index > 0 && <Text $noSelect></Text>}

View file

@ -11,7 +11,6 @@ import {
AlbumArtistListQuery,
AlbumArtistListResponse,
AlbumArtistListSort,
ArtistListQuery,
LibraryItem,
} from '/@/renderer/api/types';
import { ALBUMARTIST_CARD_ROWS } from '/@/renderer/components';
@ -34,7 +33,7 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG
const handlePlayQueueAdd = usePlayQueueAdd();
const { pageKey } = useListContext();
const { grid, display, filter } = useListStoreByKey({ key: pageKey });
const { grid, display, filter } = useListStoreByKey<AlbumArtistListQuery>({ key: pageKey });
const { setGrid } = useListStoreActions();
const handleFavorite = useHandleFavorite({ gridRef, server });
@ -73,7 +72,7 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG
const fetch = useCallback(
async ({ skip: startIndex, take: limit }: { skip: number; take: number }) => {
const query: ArtistListQuery = {
const query: AlbumArtistListQuery = {
...filter,
limit,
startIndex,
@ -91,7 +90,6 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG
},
query: {
limit,
startIndex,
...filter,
},
}),

View file

@ -9,7 +9,13 @@ import { RiFolder2Line, RiMoreFill, RiRefreshLine, RiSettings3Fill } from 'react
import { useListContext } from '../../../context/list-context';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { AlbumArtistListSort, LibraryItem, ServerType, SortOrder } from '/@/renderer/api/types';
import {
AlbumArtistListQuery,
AlbumArtistListSort,
LibraryItem,
ServerType,
SortOrder,
} from '/@/renderer/api/types';
import { Button, DropdownMenu, MultiSelect, Slider, Switch, Text } from '/@/renderer/components';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { ALBUMARTIST_TABLE_COLUMNS } from '/@/renderer/components/virtual-table';
@ -85,6 +91,28 @@ const FILTERS = {
value: AlbumArtistListSort.SONG_COUNT,
},
],
subsonic: [
{
defaultOrder: SortOrder.DESC,
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
value: AlbumArtistListSort.ALBUM_COUNT,
},
{
defaultOrder: SortOrder.DESC,
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
value: AlbumArtistListSort.FAVORITED,
},
{
defaultOrder: SortOrder.ASC,
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
value: AlbumArtistListSort.NAME,
},
{
defaultOrder: SortOrder.DESC,
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
value: AlbumArtistListSort.RATING,
},
],
};
interface AlbumArtistListHeaderFiltersProps {
@ -100,7 +128,9 @@ export const AlbumArtistListHeaderFilters = ({
const queryClient = useQueryClient();
const server = useCurrentServer();
const { pageKey } = useListContext();
const { display, table, grid, filter } = useListStoreByKey({ key: pageKey });
const { display, table, grid, filter } = useListStoreByKey<AlbumArtistListQuery>({
key: pageKey,
});
const { setFilter, setTable, setTablePagination, setDisplayType, setGrid } =
useListStoreActions();
const cq = useContainerQuery();

View file

@ -4,7 +4,7 @@ import { Flex, Group, Stack } from '@mantine/core';
import debounce from 'lodash/debounce';
import { useTranslation } from 'react-i18next';
import { FilterBar } from '../../shared/components/filter-bar';
import { LibraryItem } from '/@/renderer/api/types';
import { AlbumArtistListQuery, LibraryItem } from '/@/renderer/api/types';
import { PageHeader, SearchInput } from '/@/renderer/components';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { AlbumArtistListHeaderFilters } from '/@/renderer/features/artists/components/album-artist-list-header-filters';
@ -28,8 +28,9 @@ export const AlbumArtistListHeader = ({
const server = useCurrentServer();
const cq = useContainerQuery();
const { filter, refresh, search } = useDisplayRefresh({
const { filter, refresh, search } = useDisplayRefresh<AlbumArtistListQuery>({
gridRef,
itemCount,
itemType: LibraryItem.ALBUM_ARTIST,
server,
tableRef,

View file

@ -0,0 +1,30 @@
import { useQuery } from '@tanstack/react-query';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { AlbumArtistListQuery } from '/@/renderer/api/types';
import { QueryHookArgs } from '/@/renderer/lib/react-query';
import { getServerById } from '/@/renderer/store';
export const useAlbumArtistListCount = (args: QueryHookArgs<AlbumArtistListQuery>) => {
const { options, query, serverId } = args;
const server = getServerById(serverId);
return useQuery({
enabled: !!serverId,
queryFn: ({ signal }) => {
if (!server) throw new Error('Server not found');
return api.controller.getAlbumArtistListCount({
apiClientProps: {
server,
signal,
},
query,
});
},
queryKey: queryKeys.albumArtists.count(
serverId || '',
Object.keys(query).length === 0 ? undefined : query,
),
...options,
});
};

View file

@ -13,7 +13,7 @@ export const useTopSongsList = (args: QueryHookArgs<TopSongListQuery>) => {
enabled: !!server?.id,
queryFn: ({ signal }) => {
if (!server) throw new Error('Server not found');
return api.controller.getTopSongList({ apiClientProps: { server, signal }, query });
return api.controller.getTopSongs({ apiClientProps: { server, signal }, query });
},
queryKey: queryKeys.albumArtists.topSongs(server?.id || '', query),
...options,

View file

@ -2,13 +2,13 @@ import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/li
import { useMemo, useRef } from 'react';
import { useCurrentServer } from '../../../store/auth.store';
import { useListFilterByKey } from '../../../store/list.store';
import { LibraryItem } from '/@/renderer/api/types';
import { AlbumArtistListQuery, LibraryItem } from '/@/renderer/api/types';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { ListContext } from '/@/renderer/context/list-context';
import { AlbumArtistListContent } from '/@/renderer/features/artists/components/album-artist-list-content';
import { AlbumArtistListHeader } from '/@/renderer/features/artists/components/album-artist-list-header';
import { useAlbumArtistList } from '/@/renderer/features/artists/queries/album-artist-list-query';
import { AnimatedPage } from '/@/renderer/features/shared';
import { useAlbumArtistListCount } from '/@/renderer/features/artists/queries/album-artist-list-count-query';
const AlbumArtistListRoute = () => {
const gridRef = useRef<VirtualInfiniteGridRef | null>(null);
@ -16,25 +16,18 @@ const AlbumArtistListRoute = () => {
const pageKey = LibraryItem.ALBUM_ARTIST;
const server = useCurrentServer();
const albumArtistListFilter = useListFilterByKey({ key: pageKey });
const albumArtistListFilter = useListFilterByKey<AlbumArtistListQuery>({ key: pageKey });
const itemCountCheck = useAlbumArtistList({
const itemCountCheck = useAlbumArtistListCount({
options: {
cacheTime: 1000 * 60,
staleTime: 1000 * 60,
},
query: {
limit: 1,
startIndex: 0,
...albumArtistListFilter,
},
query: albumArtistListFilter,
serverId: server?.id,
});
const itemCount =
itemCountCheck.data?.totalRecordCount === null
? undefined
: itemCountCheck.data?.totalRecordCount;
const itemCount = itemCountCheck.data === null ? undefined : itemCountCheck.data;
const providerValue = useMemo(() => {
return {