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