diff --git a/src/renderer/components/card/card-rows.tsx b/src/renderer/components/card/card-rows.tsx index 40b1fa993..21dc29ffd 100644 --- a/src/renderer/components/card/card-rows.tsx +++ b/src/renderer/components/card/card-rows.tsx @@ -275,7 +275,7 @@ export const PLAYLIST_CARD_ROWS: { [key: string]: CardRow } = { name: { property: 'name', route: { - route: AppRoute.PLAYLISTS_DETAIL, + route: AppRoute.PLAYLISTS_DETAIL_SONGS, slugs: [{ idProperty: 'id', slugProperty: 'playlistId' }], }, }, diff --git a/src/renderer/components/virtual-table/hooks/use-virtual-table.ts b/src/renderer/components/virtual-table/hooks/use-virtual-table.ts index a99cdb295..776a6d8c6 100644 --- a/src/renderer/components/virtual-table/hooks/use-virtual-table.ts +++ b/src/renderer/components/virtual-table/hooks/use-virtual-table.ts @@ -385,7 +385,9 @@ export const useVirtualTable = ({ ); break; case LibraryItem.PLAYLIST: - navigate(generatePath(AppRoute.PLAYLISTS_DETAIL, { playlistId: e.data.id })); + navigate( + generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: e.data.id }), + ); break; default: break; diff --git a/src/renderer/features/playlists/components/playlist-detail-content.tsx b/src/renderer/features/playlists/components/playlist-detail-content.tsx deleted file mode 100644 index 12dc2192e..000000000 --- a/src/renderer/features/playlists/components/playlist-detail-content.tsx +++ /dev/null @@ -1,254 +0,0 @@ -import { MutableRefObject, useMemo, useRef } from 'react'; -import { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core'; -import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; -import { Box, Group } from '@mantine/core'; -import { closeAllModals, openModal } from '@mantine/modals'; -import { useTranslation } from 'react-i18next'; -import { RiMoreFill } from 'react-icons/ri'; -import { generatePath, useNavigate, useParams } from 'react-router'; -import { Link } from 'react-router-dom'; -import styled from 'styled-components'; -import { useListStoreByKey } from '../../../store/list.store'; -import { LibraryItem, QueueSong } from '/@/renderer/api/types'; -import { Button, ConfirmModal, DropdownMenu, MotionGroup, toast } from '/@/renderer/components'; -import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table'; -import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; -import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; -import { - PLAYLIST_SONG_CONTEXT_MENU_ITEMS, - SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS, -} from '/@/renderer/features/context-menu/context-menu-items'; -import { usePlayQueueAdd } from '/@/renderer/features/player'; -import { openUpdatePlaylistModal } from '/@/renderer/features/playlists/components/update-playlist-form'; -import { useDeletePlaylist } from '/@/renderer/features/playlists/mutations/delete-playlist-mutation'; -import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query'; -import { usePlaylistSongListInfinite } from '/@/renderer/features/playlists/queries/playlist-song-list-query'; -import { PlayButton, PLAY_TYPES } from '/@/renderer/features/shared'; -import { AppRoute } from '/@/renderer/router/routes'; -import { useCurrentServer } from '/@/renderer/store'; -import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; -import { Play } from '/@/renderer/types'; - -const ContentContainer = styled.div` - position: relative; - display: flex; - flex-direction: column; - padding: 1rem 2rem 5rem; - overflow: hidden; - - .ag-theme-alpine-dark { - --ag-header-background-color: rgb(0 0 0 / 0%) !important; - } -`; - -interface PlaylistDetailContentProps { - tableRef: MutableRefObject; -} - -export const PlaylistDetailContent = ({ tableRef }: PlaylistDetailContentProps) => { - const { t } = useTranslation(); - const navigate = useNavigate(); - const { playlistId } = useParams() as { playlistId: string }; - const { table } = useListStoreByKey({ key: LibraryItem.SONG }); - const handlePlayQueueAdd = usePlayQueueAdd(); - const server = useCurrentServer(); - const detailQuery = usePlaylistDetail({ query: { id: playlistId }, serverId: server?.id }); - const playButtonBehavior = usePlayButtonBehavior(); - - const playlistSongsQueryInfinite = usePlaylistSongListInfinite({ - options: { - cacheTime: 0, - keepPreviousData: false, - }, - query: { - id: playlistId, - limit: 50, - startIndex: 0, - }, - serverId: server?.id, - }); - - const handleLoadMore = () => { - playlistSongsQueryInfinite.fetchNextPage(); - }; - - const columnDefs: ColDef[] = useMemo( - () => - getColumnDefs(table.columns).filter((c) => c.colId !== 'album' && c.colId !== 'artist'), - [table.columns], - ); - - const contextMenuItems = useMemo(() => { - if (detailQuery?.data?.rules) { - return SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS; - } - - return PLAYLIST_SONG_CONTEXT_MENU_ITEMS; - }, [detailQuery?.data?.rules]); - - const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, contextMenuItems, { - playlistId, - }); - - const playlistSongData = useMemo( - () => playlistSongsQueryInfinite.data?.pages.flatMap((p) => p?.items), - [playlistSongsQueryInfinite.data?.pages], - ); - - const deletePlaylistMutation = useDeletePlaylist({}); - - const handleDeletePlaylist = () => { - deletePlaylistMutation.mutate( - { query: { id: playlistId }, serverId: server?.id }, - { - onError: (err) => { - toast.error({ - message: err.message, - title: t('error.genericError', { postProcess: 'sentenceCase' }), - }); - }, - onSuccess: () => { - closeAllModals(); - navigate(AppRoute.PLAYLISTS); - }, - }, - ); - }; - - const openDeletePlaylist = () => { - openModal({ - children: ( - - Are you sure you want to delete this playlist? - - ), - title: t('form.deletePlaylist.title', { postProcess: 'sentenceCase' }), - }); - }; - - const handlePlay = (playType?: Play) => { - handlePlayQueueAdd?.({ - byItemType: { - id: [playlistId], - type: LibraryItem.PLAYLIST, - }, - playType: playType || playButtonBehavior, - }); - }; - - const handleRowDoubleClick = (e: RowDoubleClickedEvent) => { - if (!e.data) return; - - handlePlayQueueAdd?.({ - byItemType: { - id: [playlistId], - type: LibraryItem.PLAYLIST, - }, - initialSongId: e.data.id, - playType: playButtonBehavior, - }); - }; - - const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); - - const loadMoreRef = useRef(null); - - return ( - - - - handlePlay()} /> - - - - - - {PLAY_TYPES.filter((type) => type.play !== playButtonBehavior).map( - (type) => ( - handlePlay(type.play)} - > - {type.label} - - ), - )} - - { - if (!detailQuery.data || !server) return; - openUpdatePlaylistModal({ playlist: detailQuery.data, server }); - }} - > - Edit playlist - - - Delete playlist - - - - - - - - { - // It's possible that there are duplicate song ids in a playlist - return `${data.data.id}-${data.data.pageIndex}`; - }} - rowClassRules={rowClassRules} - rowData={playlistSongData} - rowHeight={60} - rowSelection="multiple" - onCellContextMenu={handleContextMenu} - onRowDoubleClicked={handleRowDoubleClick} - /> - - - - - - ); -}; diff --git a/src/renderer/features/playlists/components/playlist-detail-header.tsx b/src/renderer/features/playlists/components/playlist-detail-header.tsx deleted file mode 100644 index 1235681cd..000000000 --- a/src/renderer/features/playlists/components/playlist-detail-header.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { forwardRef, Fragment, Ref } from 'react'; -import { Group, Stack } from '@mantine/core'; -import { useParams } from 'react-router'; -import { Badge, Text } from '/@/renderer/components'; -import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query'; -import { LibraryHeader } from '/@/renderer/features/shared'; -import { AppRoute } from '/@/renderer/router/routes'; -import { formatDurationString } from '/@/renderer/utils'; -import { LibraryItem } from '/@/renderer/api/types'; -import { useCurrentServer } from '../../../store/auth.store'; - -interface PlaylistDetailHeaderProps { - background: string; - imagePlaceholderUrl?: string | null; - imageUrl?: string | null; -} - -export const PlaylistDetailHeader = forwardRef( - ( - { background, imageUrl, imagePlaceholderUrl }: PlaylistDetailHeaderProps, - ref: Ref, - ) => { - const { playlistId } = useParams() as { playlistId: string }; - const server = useCurrentServer(); - const detailQuery = usePlaylistDetail({ query: { id: playlistId }, serverId: server?.id }); - - const metadataItems = [ - { - id: 'songCount', - secondary: false, - value: `${detailQuery?.data?.songCount || 0} songs`, - }, - { - id: 'duration', - secondary: true, - value: - detailQuery?.data?.duration && formatDurationString(detailQuery.data.duration), - }, - ]; - - const isSmartPlaylist = detailQuery?.data?.rules; - - return ( - - - - - {metadataItems.map((item, index) => ( - - {index > 0 && } - {item.value} - - ))} - {isSmartPlaylist && ( - <> - - - Smart Playlist - - - )} - - {detailQuery?.data?.description} - - - - ); - }, -); diff --git a/src/renderer/features/playlists/components/playlist-list-grid-view.tsx b/src/renderer/features/playlists/components/playlist-list-grid-view.tsx index 14abc68e8..3d51e7caa 100644 --- a/src/renderer/features/playlists/components/playlist-list-grid-view.tsx +++ b/src/renderer/features/playlists/components/playlist-list-grid-view.tsx @@ -1,5 +1,5 @@ -import { QueryKey, useQueryClient } from '@tanstack/react-query'; import { MutableRefObject, useCallback, useMemo } from 'react'; +import { QueryKey, useQueryClient } from '@tanstack/react-query'; import AutoSizer, { Size } from 'react-virtualized-auto-sizer'; import { ListOnScrollProps } from 'react-window'; import { useListContext } from '../../../context/list-context'; @@ -22,7 +22,7 @@ import { import { usePlayQueueAdd } from '/@/renderer/features/player'; import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared'; import { AppRoute } from '/@/renderer/router/routes'; -import { useCurrentServer, useGeneralSettings, useListStoreByKey } from '/@/renderer/store'; +import { useCurrentServer, useListStoreByKey } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; interface PlaylistListGridViewProps { @@ -37,7 +37,6 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie const handlePlayQueueAdd = usePlayQueueAdd(); const { display, grid, filter } = useListStoreByKey({ key: pageKey }); const { setGrid } = useListStoreActions(); - const { defaultFullPlaylist } = useGeneralSettings(); const createFavoriteMutation = useCreateFavorite({}); const deleteFavoriteMutation = useDeleteFavorite({}); @@ -68,9 +67,7 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie }; const cardRows = useMemo(() => { - const rows: CardRow[] = defaultFullPlaylist - ? [PLAYLIST_CARD_ROWS.nameFull] - : [PLAYLIST_CARD_ROWS.name]; + const rows: CardRow[] = [PLAYLIST_CARD_ROWS.name]; switch (filter.sortBy) { case PlaylistListSort.DURATION: @@ -93,7 +90,7 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie } return rows; - }, [defaultFullPlaylist, filter.sortBy]); + }, [filter.sortBy]); const handleGridScroll = useCallback( (e: ListOnScrollProps) => { @@ -187,9 +184,7 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie loading={itemCount === undefined || itemCount === null} minimumBatchSize={40} route={{ - route: defaultFullPlaylist - ? AppRoute.PLAYLISTS_DETAIL_SONGS - : AppRoute.PLAYLISTS_DETAIL, + route: AppRoute.PLAYLISTS_DETAIL_SONGS, slugs: [{ idProperty: 'id', slugProperty: 'playlistId' }], }} width={width} diff --git a/src/renderer/features/playlists/components/playlist-list-table-view.tsx b/src/renderer/features/playlists/components/playlist-list-table-view.tsx index 6decfea2b..af5fe0e3c 100644 --- a/src/renderer/features/playlists/components/playlist-list-table-view.tsx +++ b/src/renderer/features/playlists/components/playlist-list-table-view.tsx @@ -8,7 +8,7 @@ import { VirtualTable } from '/@/renderer/components/virtual-table'; import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table'; import { PLAYLIST_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items'; import { AppRoute } from '/@/renderer/router/routes'; -import { useCurrentServer, useGeneralSettings } from '/@/renderer/store'; +import { useCurrentServer } from '/@/renderer/store'; interface PlaylistListTableViewProps { itemCount?: number; @@ -18,16 +18,11 @@ interface PlaylistListTableViewProps { export const PlaylistListTableView = ({ tableRef, itemCount }: PlaylistListTableViewProps) => { const navigate = useNavigate(); const server = useCurrentServer(); - const { defaultFullPlaylist } = useGeneralSettings(); const pageKey = 'playlist'; const handleRowDoubleClick = (e: RowDoubleClickedEvent) => { if (!e.data) return; - if (defaultFullPlaylist) { - navigate(generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: e.data.id })); - } else { - navigate(generatePath(AppRoute.PLAYLISTS_DETAIL, { playlistId: e.data.id })); - } + navigate(generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: e.data.id })); }; const tableProps = useVirtualTable({ diff --git a/src/renderer/features/playlists/queries/playlist-song-list-query.ts b/src/renderer/features/playlists/queries/playlist-song-list-query.ts index 8d2699d72..8754fa295 100644 --- a/src/renderer/features/playlists/queries/playlist-song-list-query.ts +++ b/src/renderer/features/playlists/queries/playlist-song-list-query.ts @@ -1,9 +1,9 @@ -import { useQuery, useInfiniteQuery } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; +import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; -import type { PlaylistSongListQuery, PlaylistSongListResponse } from '/@/renderer/api/types'; +import type { PlaylistSongListQuery } from '/@/renderer/api/types'; import type { QueryHookArgs } from '/@/renderer/lib/react-query'; import { getServerById } from '/@/renderer/store'; -import { api } from '/@/renderer/api'; export const usePlaylistSongList = (args: QueryHookArgs) => { const { options, query, serverId } = args || {}; @@ -23,31 +23,31 @@ export const usePlaylistSongList = (args: QueryHookArgs) }); }; -export const usePlaylistSongListInfinite = (args: QueryHookArgs) => { - const { options, query, serverId } = args || {}; - const server = getServerById(serverId); +// export const usePlaylistSongListInfinite = (args: QueryHookArgs) => { +// const { options, query, serverId } = args || {}; +// const server = getServerById(serverId); - return useInfiniteQuery({ - enabled: !!server, - getNextPageParam: (lastPage: PlaylistSongListResponse | undefined, pages) => { - if (!lastPage?.items) return undefined; - if (lastPage?.items?.length >= (query?.limit || 50)) { - return pages?.length; - } +// return useInfiniteQuery({ +// enabled: !!server, +// getNextPageParam: (lastPage: PlaylistSongListResponse | undefined, pages) => { +// if (!lastPage?.items) return undefined; +// if (lastPage?.items?.length >= (query?.limit || 50)) { +// return pages?.length; +// } - return undefined; - }, - queryFn: ({ pageParam = 0, signal }) => { - return api.controller.getPlaylistSongList({ - apiClientProps: { server, signal }, - query: { - ...query, - limit: query.limit || 50, - startIndex: pageParam * (query.limit || 50), - }, - }); - }, - queryKey: queryKeys.playlists.detailSongList(server?.id || '', query.id, query), - ...options, - }); -}; +// return undefined; +// }, +// queryFn: ({ pageParam = 0, signal }) => { +// return api.controller.getPlaylistSongList({ +// apiClientProps: { server, signal }, +// query: { +// ...query, +// limit: query.limit || 50, +// startIndex: pageParam * (query.limit || 50), +// }, +// }); +// }, +// queryKey: queryKeys.playlists.detailSongList(server?.id || '', query.id, query), +// ...options, +// }); +// }; diff --git a/src/renderer/features/settings/components/general/control-settings.tsx b/src/renderer/features/settings/components/general/control-settings.tsx index 8e9407d05..d04d979c0 100644 --- a/src/renderer/features/settings/components/general/control-settings.tsx +++ b/src/renderer/features/settings/components/general/control-settings.tsx @@ -246,28 +246,6 @@ export const ControlSettings = () => { isHidden: !isElectron(), title: t('setting.savePlayQueue', { postProcess: 'sentenceCase' }), }, - { - control: ( - - setSettings({ - general: { - ...settings, - defaultFullPlaylist: e.currentTarget.checked, - }, - }) - } - /> - ), - description: t('setting.skipPlaylistPage', { - context: 'description', - postProcess: 'sentenceCase', - }), - isHidden: false, - title: t('setting.skipPlaylistPage', { postProcess: 'sentenceCase' }), - }, ]; return ; diff --git a/src/renderer/features/sidebar/components/sidebar-playlist-list.tsx b/src/renderer/features/sidebar/components/sidebar-playlist-list.tsx index 934679860..ecd636f48 100644 --- a/src/renderer/features/sidebar/components/sidebar-playlist-list.tsx +++ b/src/renderer/features/sidebar/components/sidebar-playlist-list.tsx @@ -14,16 +14,12 @@ import { Play } from '/@/renderer/types'; import AutoSizer from 'react-virtualized-auto-sizer'; import { FixedSizeList, ListChildComponentProps } from 'react-window'; import { useHideScrollbar } from '/@/renderer/hooks'; -import { useCurrentServer, useGeneralSettings } from '/@/renderer/store'; +import { useCurrentServer } from '/@/renderer/store'; const PlaylistRow = ({ index, data, style }: ListChildComponentProps) => { const { t } = useTranslation(); const path = data?.items[index].id - ? data.defaultFullPlaylist - ? generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: data.items[index].id }) - : generatePath(AppRoute.PLAYLISTS_DETAIL, { - playlistId: data?.items[index].id, - }) + ? generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, { playlistId: data.items[index].id }) : undefined; return ( @@ -120,7 +116,6 @@ const PlaylistRow = ({ index, data, style }: ListChildComponentProps) => { export const SidebarPlaylistList = () => { const { isScrollbarHidden, hideScrollbarElementProps } = useHideScrollbar(0); const handlePlayQueueAdd = usePlayQueueAdd(); - const { defaultFullPlaylist } = useGeneralSettings(); const server = useCurrentServer(); const playlistsQuery = usePlaylistList({ @@ -154,11 +149,10 @@ export const SidebarPlaylistList = () => { const memoizedItemData = useMemo(() => { return { - defaultFullPlaylist, handlePlay: handlePlayPlaylist, items: playlistsQuery?.data?.items, }; - }, [playlistsQuery?.data?.items, defaultFullPlaylist, handlePlayPlaylist]); + }, [playlistsQuery?.data?.items, handlePlayPlaylist]); return ( import('/@/renderer/features/albums/routes/alb const SongListRoute = lazy(() => import('/@/renderer/features/songs/routes/song-list-route')); -const PlaylistDetailRoute = lazy( - () => import('/@/renderer/features/playlists/routes/playlist-detail-route'), -); - const PlaylistDetailSongListRoute = lazy( () => import('/@/renderer/features/playlists/routes/playlist-detail-song-list-route'), ); @@ -136,11 +132,6 @@ export const AppRouter = () => { errorElement={} path={AppRoute.PLAYLISTS} /> - } - errorElement={} - path={AppRoute.PLAYLISTS_DETAIL} - /> } errorElement={}