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,