add table row playback controls

- supports song, album, artist, and album artist tables
- hovering over the first row index or track number column will display a hovercard for the playback controls
This commit is contained in:
jeffvli
2026-05-19 20:58:34 -07:00
parent 42e9394246
commit 64efbc5210
16 changed files with 656 additions and 180 deletions
@@ -14,6 +14,7 @@ import styles from './album-artist-detail-content.module.css';
import { queryKeys } from '/@/renderer/api/query-keys';
import { DataRow, MemoizedItemCard } from '/@/renderer/components/item-card/item-card';
import { useDefaultItemListControls } from '/@/renderer/components/item-list/helpers/item-list-controls';
import { playSongFromItemListControl } from '/@/renderer/components/item-list/helpers/play-row-from-list';
import { useGridRows } from '/@/renderer/components/item-list/helpers/use-grid-rows';
import { useItemListColumnReorder } from '/@/renderer/components/item-list/helpers/use-item-list-column-reorder';
import { useItemListColumnResize } from '/@/renderer/components/item-list/helpers/use-item-list-column-resize';
@@ -365,12 +366,13 @@ const AlbumArtistMetadataTopSongsContent = ({
return;
}
const playType = (meta?.playType as Play) || Play.NOW;
const items = internalState?.getData() as Song[];
if (index !== undefined) {
player.addToQueueByData(items, playType, item.id);
}
playSongFromItemListControl({
index,
internalState,
item: item as Song,
meta,
player,
});
},
};
}, [player]);
@@ -657,12 +659,13 @@ const AlbumArtistMetadataFavoriteSongs = ({
return;
}
const playType = (meta?.playType as Play) || Play.NOW;
const items = internalState?.getData() as Song[];
if (index !== undefined) {
player.addToQueueByData(items, playType, item.id);
}
playSongFromItemListControl({
index,
internalState,
item: item as Song,
meta,
player,
});
},
};
}, [player]);
@@ -2,6 +2,7 @@ import { useSuspenseQueries } from '@tanstack/react-query';
import { useMemo } from 'react';
import { useParams } from 'react-router';
import { playSongFromItemListControl } from '/@/renderer/components/item-list/helpers/play-row-from-list';
import { useItemListColumnReorder } from '/@/renderer/components/item-list/helpers/use-item-list-column-reorder';
import { useItemListColumnResize } from '/@/renderer/components/item-list/helpers/use-item-list-column-resize';
import { ItemTableList } from '/@/renderer/components/item-list/item-table-list/item-table-list';
@@ -24,7 +25,7 @@ import { useCurrentServer } from '/@/renderer/store/auth.store';
import { useSettingsStore } from '/@/renderer/store/settings.store';
import { sortSongList } from '/@/shared/api/utils';
import { LibraryItem, Song } from '/@/shared/types/domain-types';
import { ItemListKey, Play } from '/@/shared/types/types';
import { ItemListKey } from '/@/shared/types/types';
const AlbumArtistDetailFavoriteSongsListRoute = () => {
const { albumArtistId, artistId } = useParams() as {
@@ -96,12 +97,13 @@ const AlbumArtistDetailFavoriteSongsListRoute = () => {
return;
}
const playType = (meta?.playType as Play) || Play.NOW;
const items = internalState?.getData() as Song[];
if (index !== undefined) {
player.addToQueueByData(items, playType, item.id);
}
playSongFromItemListControl({
index,
internalState,
item: item as Song,
meta,
player,
});
},
};
}, [player]);
@@ -2,6 +2,7 @@ import { useSuspenseQuery } from '@tanstack/react-query';
import { useMemo } from 'react';
import { useParams } from 'react-router';
import { playSongFromItemListControl } from '/@/renderer/components/item-list/helpers/play-row-from-list';
import { useItemListColumnReorder } from '/@/renderer/components/item-list/helpers/use-item-list-column-reorder';
import { useItemListColumnResize } from '/@/renderer/components/item-list/helpers/use-item-list-column-resize';
import { ItemTableList } from '/@/renderer/components/item-list/item-table-list/item-table-list';
@@ -18,7 +19,7 @@ import { useCurrentServer } from '/@/renderer/store/auth.store';
import { useSettingsStore } from '/@/renderer/store/settings.store';
import { useLocalStorage } from '/@/shared/hooks/use-local-storage';
import { LibraryItem, Song } from '/@/shared/types/domain-types';
import { ItemListKey, Play } from '/@/shared/types/types';
import { ItemListKey } from '/@/shared/types/types';
const AlbumArtistDetailTopSongsListRoute = () => {
const { albumArtistId, artistId } = useParams() as {
@@ -78,12 +79,13 @@ const AlbumArtistDetailTopSongsListRoute = () => {
return;
}
const playType = (meta?.playType as Play) || Play.NOW;
const items = internalState?.getData() as Song[];
if (index !== undefined) {
player.addToQueueByData(items, playType, item.id);
}
playSongFromItemListControl({
index,
internalState,
item: item as Song,
meta,
player,
});
},
};
}, [player]);