refactor playlist route component organization

This commit is contained in:
jeffvli
2025-11-29 20:05:08 -08:00
parent ad198ea047
commit 24846fbae4
5 changed files with 55 additions and 41 deletions
@@ -1,6 +1,9 @@
import { lazy, Suspense } from 'react';
import { useSuspenseQuery } from '@tanstack/react-query';
import { lazy, Suspense, useEffect } from 'react';
import { useParams } from 'react-router';
import { useListContext } from '/@/renderer/context/list-context';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import { ItemListSettings, useCurrentServer, useListSettings } from '/@/renderer/store';
import { Spinner } from '/@/shared/components/spinner/spinner';
import { PlaylistSongListQuery } from '/@/shared/types/domain-types';
@@ -19,10 +22,31 @@ export const PlaylistDetailSongListContent = () => {
ItemListKey.PLAYLIST_SONG,
);
const { playlistId } = useParams() as { playlistId: string };
const server = useCurrentServer();
const { setItemCount } = useListContext();
const playlistSongsQuery = useSuspenseQuery(
playlistsQueries.songList({
query: {
id: playlistId,
},
serverId: server?.id,
}),
);
useEffect(() => {
if (
playlistSongsQuery.data?.totalRecordCount !== undefined &&
playlistSongsQuery.data.totalRecordCount !== null
) {
setItemCount?.(playlistSongsQuery.data.totalRecordCount);
}
}, [playlistSongsQuery.data?.totalRecordCount, setItemCount]);
return (
<Suspense fallback={<Spinner container />}>
<PlaylistDetailSongListView
data={playlistSongsQuery.data}
display={display}
grid={grid}
itemsPerPage={itemsPerPage}
@@ -37,10 +61,12 @@ export const PlaylistDetailSongListContent = () => {
export type OverridePlaylistSongListQuery = Omit<Partial<PlaylistSongListQuery>, 'id'>;
export const PlaylistDetailSongListView = ({
data,
display,
playlistId,
table,
}: ItemListSettings & {
data: any;
playlistId: string;
}) => {
const server = useCurrentServer();
@@ -51,6 +77,7 @@ export const PlaylistDetailSongListView = ({
<PlaylistDetailSongListTable
autoFitColumns={table.autoFitColumns}
columns={table.columns}
data={data}
enableAlternateRowColors={table.enableAlternateRowColors}
enableHorizontalBorders={table.enableHorizontalBorders}
enableRowHoverHighlight={table.enableRowHoverHighlight}
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router';
import { useLocation, useParams } from 'react-router';
import { PageHeader } from '/@/renderer/components/page-header/page-header';
import { useListContext } from '/@/renderer/context/list-context';
@@ -28,11 +28,13 @@ export const PlaylistDetailSongListHeader = ({
const { playlistId } = useParams() as { playlistId: string };
const { itemCount } = useListContext();
const server = useCurrentServer();
const detailQuery = useQuery(
playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
);
const location = useLocation();
const detailQuery = useQuery({
...playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
initialData: location.state?.item,
});
if (detailQuery.isLoading) return null;
const isSmartPlaylist = isSmartPlaylistProp ?? detailQuery?.data?.rules;
const playlistDuration = detailQuery?.data?.duration;
@@ -1,4 +1,3 @@
import { useQuery } from '@tanstack/react-query';
import { forwardRef, useMemo } from 'react';
import { useItemListColumnReorder } from '/@/renderer/components/item-list/helpers/use-item-list-column-reorder';
@@ -8,7 +7,6 @@ import { ItemTableList } from '/@/renderer/components/item-list/item-table-list/
import { ItemTableListColumn } from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
import { ItemControls, ItemListTableComponentProps } from '/@/renderer/components/item-list/types';
import { usePlayer } from '/@/renderer/features/player/context/player-context';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
import { usePlaylistSongListFilters } from '/@/renderer/features/playlists/hooks/use-playlist-song-list-filters';
import { useSearchTermFilter } from '/@/renderer/features/shared/hooks/use-search-term-filter';
import { searchLibraryItems } from '/@/renderer/features/shared/utils';
@@ -19,6 +17,7 @@ import { ItemListKey, Play } from '/@/shared/types/types';
interface PlaylistDetailSongListTableProps
extends Omit<ItemListTableComponentProps<PlaylistSongListQuery>, 'query'> {
data: any;
playlistId: string;
}
@@ -27,6 +26,7 @@ export const PlaylistDetailSongListTable = forwardRef<any, PlaylistDetailSongLis
{
autoFitColumns = false,
columns,
data,
enableAlternateRowColors = false,
enableHorizontalBorders = false,
enableRowHoverHighlight = true,
@@ -39,12 +39,6 @@ export const PlaylistDetailSongListTable = forwardRef<any, PlaylistDetailSongLis
},
ref,
) => {
const playlistSongs = useQuery(
playlistsQueries.songList({
query: { id: playlistId },
serverId: serverId,
}),
);
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
enabled: saveScrollOffset,
@@ -62,7 +56,7 @@ export const PlaylistDetailSongListTable = forwardRef<any, PlaylistDetailSongLis
const { query } = usePlaylistSongListFilters();
const filterSortedSongs = useMemo(() => {
let items = playlistSongs.data?.items || [];
let items = data?.items || [];
if (searchTerm) {
if (searchTerm) {
@@ -73,7 +67,7 @@ export const PlaylistDetailSongListTable = forwardRef<any, PlaylistDetailSongLis
}
return sortSongList(items, query.sortBy, query.sortOrder);
}, [playlistSongs.data?.items, searchTerm, query.sortBy, query.sortOrder]);
}, [data?.items, searchTerm, query.sortBy, query.sortOrder]);
const player = usePlayer();
@@ -1,8 +1,8 @@
import { closeAllModals, openModal } from '@mantine/modals';
import { useQuery } from '@tanstack/react-query';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Suspense, useCallback, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { generatePath, useNavigate, useParams } from 'react-router';
import { generatePath, useLocation, useNavigate, useParams } from 'react-router';
import { ListContext } from '/@/renderer/context/list-context';
import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api';
@@ -26,6 +26,7 @@ import { Button } from '/@/shared/components/button/button';
import { Group } from '/@/shared/components/group/group';
import { Icon } from '/@/shared/components/icon/icon';
import { ConfirmModal } from '/@/shared/components/modal/modal';
import { Spinner } from '/@/shared/components/spinner/spinner';
import { Stack } from '/@/shared/components/stack/stack';
import { Text } from '/@/shared/components/text/text';
import { toast } from '/@/shared/components/toast/toast';
@@ -243,12 +244,15 @@ const PlaylistQueryEditor = ({
const PlaylistDetailSongListRoute = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const { playlistId } = useParams() as { playlistId: string };
const server = useCurrentServer();
const detailQuery = useQuery(
playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
);
const detailQuery = useQuery({
...playlistsQueries.detail({ query: { id: playlistId }, serverId: server?.id }),
initialData: location.state?.item,
staleTime: 0,
});
const createPlaylistMutation = useCreatePlaylist({});
const deletePlaylistMutation = useDeletePlaylist({});
@@ -410,15 +414,6 @@ const PlaylistDetailSongListRoute = () => {
setIsQueryBuilderExpanded(true);
};
const playlistSongs = useQuery(
playlistsQueries.songList({
query: {
id: playlistId,
},
serverId: server?.id,
}),
);
const [itemCount, setItemCount] = useState<number | undefined>(undefined);
const providerValue = useMemo(() => {
@@ -431,15 +426,6 @@ const PlaylistDetailSongListRoute = () => {
};
}, [playlistId, itemCount]);
useEffect(() => {
if (
playlistSongs.data?.totalRecordCount !== undefined &&
playlistSongs.data.totalRecordCount !== null
) {
setItemCount(playlistSongs.data.totalRecordCount);
}
}, [playlistSongs.data?.totalRecordCount]);
return (
<AnimatedPage key={`playlist-detail-songList-${playlistId}`}>
<ListContext.Provider value={providerValue}>
@@ -466,7 +452,9 @@ const PlaylistDetailSongListRoute = () => {
queryBuilderRef={queryBuilderRef}
/>
)}
<PlaylistDetailSongListContent />
<Suspense fallback={<Spinner container />}>
<PlaylistDetailSongListContent />
</Suspense>
</ListContext.Provider>
</AnimatedPage>
);
@@ -41,7 +41,10 @@ interface PlaylistRowButtonProps extends Omit<ButtonProps, 'onContextMenu' | 'on
}
const PlaylistRowButton = ({ item, name, onContextMenu, onPlay, to }: PlaylistRowButtonProps) => {
const url = generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: to });
const url = {
pathname: generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: to }),
state: { item },
};
const { t } = useTranslation();
const [isHovered, setIsHovered] = useState(false);