diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx index d250494b3..a8c81da23 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx @@ -2,11 +2,12 @@ import { useQueryClient, useSuspenseQuery } from '@tanstack/react-query'; import { lazy, Suspense, useEffect, useMemo, useRef, useState } from 'react'; import { useParams } from 'react-router'; +import { PlaylistDetailSongListEditTable } from './playlist-detail-song-list-table'; + import { ItemListHandle } from '/@/renderer/components/item-list/types'; import { useListContext } from '/@/renderer/context/list-context'; import { eventEmitter } from '/@/renderer/events/event-emitter'; import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api'; -import { PlaylistDetailSongListEditTable } from '/@/renderer/features/playlists/components/playlist-detail-song-list-table'; import { useCurrentServer, useListSettings } from '/@/renderer/store'; import { Spinner } from '/@/shared/components/spinner/spinner'; import { PlaylistSongListQuery, PlaylistSongListResponse } from '/@/shared/types/domain-types'; @@ -20,6 +21,14 @@ const PlaylistDetailSongListTable = lazy(() => ), ); +const PlaylistDetailSongListGrid = lazy(() => + import('/@/renderer/features/playlists/components/playlist-detail-song-list-grid').then( + (module) => ({ + default: module.PlaylistDetailSongListGrid, + }), + ), +); + export const PlaylistDetailSongListContent = () => { const { playlistId } = useParams() as { playlistId: string }; const server = useCurrentServer(); @@ -82,6 +91,9 @@ export const PlaylistDetailSongListView = ({ data }: { data: PlaylistSongListRes const { display, table } = useListSettings(ItemListKey.PLAYLIST_SONG); switch (display) { + case ListDisplayType.GRID: { + return ; + } case ListDisplayType.TABLE: { return ( , 'query'> { + data: PlaylistSongListResponse; +} + +export const PlaylistDetailSongListGrid = forwardRef( + ({ data, saveScrollOffset = true }) => { + const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({ + enabled: saveScrollOffset, + }); + + const { searchTerm } = useSearchTermFilter(); + const { query } = usePlaylistSongListFilters(); + const { setListData } = useListContext(); + + const songData = useMemo(() => { + let items = data?.items || []; + + if (searchTerm) { + items = searchLibraryItems(items, searchTerm, LibraryItem.SONG); + } + + return sortSongList(items, query.sortBy, query.sortOrder); + }, [data?.items, searchTerm, query.sortBy, query.sortOrder]); + + useEffect(() => { + if (setListData) { + setListData(songData); + } + }, [songData, setListData]); + + const gridProps = useListSettings(ItemListKey.PLAYLIST_SONG).grid; + + const rows = useGridRows( + LibraryItem.PLAYLIST_SONG, + ItemListKey.PLAYLIST_SONG, + gridProps.size, + ); + + return ( + + ); + }, +); diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx index 99a7241e7..23303aa02 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-header-filters.tsx @@ -10,6 +10,7 @@ import { useListContext } from '/@/renderer/context/list-context'; import { ContextMenuController } from '/@/renderer/features/context-menu/context-menu-controller'; import { playlistsQueries } from '/@/renderer/features/playlists/api/playlists-api'; import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu'; +import { ListDisplayTypeToggleButton } from '/@/renderer/features/shared/components/list-display-type-toggle-button'; import { ListRefreshButton } from '/@/renderer/features/shared/components/list-refresh-button'; import { ListSearchInput } from '/@/renderer/features/shared/components/list-search-input'; import { ListSortByDropdown } from '/@/renderer/features/shared/components/list-sort-by-dropdown'; @@ -26,7 +27,7 @@ import { Icon } from '/@/shared/components/icon/icon'; import { Tooltip } from '/@/shared/components/tooltip/tooltip'; import { useLocalStorage } from '/@/shared/hooks/use-local-storage'; import { LibraryItem, SongListSort, SortOrder } from '/@/shared/types/domain-types'; -import { ItemListKey, ListDisplayType } from '/@/shared/types/types'; +import { ItemListKey } from '/@/shared/types/types'; interface PlaylistDetailSongListHeaderFiltersProps { isSmartPlaylist?: boolean; @@ -108,13 +109,8 @@ export const PlaylistDetailSongListHeaderFilters = ({ variant="subtle" /> + diff --git a/src/renderer/store/settings.store.ts b/src/renderer/store/settings.store.ts index e30c9f76b..df26563e2 100644 --- a/src/renderer/store/settings.store.ts +++ b/src/renderer/store/settings.store.ts @@ -1300,7 +1300,25 @@ const initialState: SettingsState = { itemGap: 'sm', itemsPerRow: 6, itemsPerRowEnabled: false, - rows: [], + rows: pickGridRows({ + alignLeftColumns: [TableColumn.TITLE, TableColumn.ARTIST], + columns: PLAYLIST_SONG_TABLE_COLUMNS, + enabledColumns: [TableColumn.TITLE, TableColumn.ARTIST], + pickColumns: [ + TableColumn.TITLE, + TableColumn.ARTIST, + TableColumn.DURATION, + TableColumn.YEAR, + TableColumn.BIT_RATE, + TableColumn.BPM, + TableColumn.CODEC, + TableColumn.DATE_ADDED, + TableColumn.GENRE, + TableColumn.LAST_PLAYED, + TableColumn.RELEASE_DATE, + TableColumn.TRACK_NUMBER, + ], + }), size: 'default', }, itemsPerPage: 100,