diff --git a/src/renderer/components/item-list/item-table-list/item-table-list.tsx b/src/renderer/components/item-list/item-table-list/item-table-list.tsx
index 727884395..aa8dc4a28 100644
--- a/src/renderer/components/item-list/item-table-list/item-table-list.tsx
+++ b/src/renderer/components/item-list/item-table-list/item-table-list.tsx
@@ -103,6 +103,7 @@ interface VirtualizedTableGridProps {
enableHeader: boolean;
enableHorizontalBorders: boolean;
enableRowHoverHighlight: boolean;
+ enableScrollShadow: boolean;
enableSelection: boolean;
enableVerticalBorders: boolean;
getRowHeight: (index: number, cellProps: TableItemProps) => number;
@@ -146,6 +147,7 @@ const VirtualizedTableGrid = ({
enableHeader,
enableHorizontalBorders,
enableRowHoverHighlight,
+ enableScrollShadow,
enableSelection,
enableVerticalBorders,
getRowHeight,
@@ -429,7 +431,7 @@ const VirtualizedTableGrid = ({
/>
)}
- {enableHeader && showTopShadow && (
+ {enableHeader && enableScrollShadow && showTopShadow && (
)}
{!!pinnedLeftColumnCount && (
@@ -489,7 +491,7 @@ const VirtualizedTableGrid = ({
/>
)}
- {enableHeader && showTopShadow && (
+ {enableHeader && enableScrollShadow && showTopShadow && (
)}
@@ -507,10 +509,10 @@ const VirtualizedTableGrid = ({
return getRowHeight(index + pinnedRowCount, cellProps);
}}
/>
- {pinnedLeftColumnCount > 0 && showLeftShadow && (
+ {pinnedLeftColumnCount > 0 && enableScrollShadow && showLeftShadow && (
)}
- {pinnedRightColumnCount > 0 && showRightShadow && (
+ {pinnedRightColumnCount > 0 && enableScrollShadow && showRightShadow && (
)}
@@ -560,7 +562,7 @@ const VirtualizedTableGrid = ({
/>
)}
- {enableHeader && showTopShadow && (
+ {enableHeader && enableScrollShadow && showTopShadow && (
)}
(({ listKey, searchTerm }, ref) => {
- const { table } = useListSettings(listKey) || {};
+export const PlayQueue = forwardRef
(
+ ({ enableScrollShadow = true, listKey, searchTerm }, ref) => {
+ const { table } = useListSettings(listKey) || {};
- const isFetching = useIsPlayerFetching();
- const tableRef = useRef(null);
- const mergedRef = useMergedRef(ref, tableRef);
- const { getQueue } = usePlayerActions();
- const queueType = usePlayerQueueType();
- const followCurrentSong = useFollowCurrentSong();
+ const isFetching = useIsPlayerFetching();
+ const tableRef = useRef(null);
+ const mergedRef = useMergedRef(ref, tableRef);
+ const { getQueue } = usePlayerActions();
+ const queueType = usePlayerQueueType();
+ const followCurrentSong = useFollowCurrentSong();
- const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 200);
+ const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 200);
- const [data, setData] = useState([]);
- const [groups, setGroups] = useState([]);
+ const [data, setData] = useState([]);
+ const [groups, setGroups] = useState([]);
- useEffect(() => {
- const setQueue = () => {
- const queue = getQueue() || { groups: [], items: [] };
+ useEffect(() => {
+ const setQueue = () => {
+ const queue = getQueue() || { groups: [], items: [] };
- setData(queue.items);
+ setData(queue.items);
- if (queueType === PlayerQueueType.PRIORITY && queue.groups && queue.groups.length > 0) {
- const transformedGroups: TableGroupHeader[] = queue.groups.map((group) => ({
- itemCount: group.count,
- render: (): ReactElement => {
- return (
-
-
- {group.name}
-
-
- );
- },
- rowHeight: 40,
- }));
- setGroups(transformedGroups);
- } else {
- setGroups([]);
- }
- };
-
- const unsub = subscribePlayerQueue(() => {
- setQueue();
- });
-
- const unsubCurrentTrack = subscribeCurrentTrack((e) => {
- if (followCurrentSong && e.index !== -1) {
- tableRef.current?.scrollToIndex(e.index, {
- align: 'center',
- behavior: 'auto',
- });
- }
- });
-
- const handleAutoDJQueueAdded = () => {
- if (followCurrentSong) {
- const state = usePlayerStore.getState();
- let index = state.player.index;
-
- if (isShuffleEnabled(state)) {
- index = mapShuffledToQueueIndex(index, state.queue.shuffled);
+ if (
+ queueType === PlayerQueueType.PRIORITY &&
+ queue.groups &&
+ queue.groups.length > 0
+ ) {
+ const transformedGroups: TableGroupHeader[] = queue.groups.map((group) => ({
+ itemCount: group.count,
+ render: (): ReactElement => {
+ return (
+
+
+ {group.name}
+
+
+ );
+ },
+ rowHeight: 40,
+ }));
+ setGroups(transformedGroups);
+ } else {
+ setGroups([]);
}
+ };
- if (index !== -1) {
- // Use setTimeout to ensure the DOM has updated with the new queue items
- setTimeout(() => {
- tableRef.current?.scrollToIndex(index, {
- align: 'center',
- behavior: 'auto',
- });
- }, 0);
+ const unsub = subscribePlayerQueue(() => {
+ setQueue();
+ });
+
+ const unsubCurrentTrack = subscribeCurrentTrack((e) => {
+ if (followCurrentSong && e.index !== -1) {
+ tableRef.current?.scrollToIndex(e.index, {
+ align: 'center',
+ behavior: 'auto',
+ });
}
- }
- };
+ });
- eventEmitter.on('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
+ const handleAutoDJQueueAdded = () => {
+ if (followCurrentSong) {
+ const state = usePlayerStore.getState();
+ let index = state.player.index;
- setQueue();
-
- return () => {
- unsub();
- unsubCurrentTrack();
- eventEmitter.off('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
- };
- }, [getQueue, queueType, tableRef, followCurrentSong]);
-
- const filteredData: QueueSong[] = useMemo(() => {
- if (debouncedSearchTerm) {
- const searched = searchLibraryItems(data, debouncedSearchTerm, LibraryItem.SONG);
- return searched;
- }
-
- return data;
- }, [data, debouncedSearchTerm]);
-
- const isEmpty = filteredData.length === 0;
-
- const { handleColumnReordered } = useItemListColumnReorder({
- itemListKey: listKey,
- });
-
- const { handleColumnResized } = useItemListColumnResize({
- itemListKey: listKey,
- });
-
- const currentSong = usePlayerSong();
-
- const currentSongUniqueId = currentSong?._uniqueId;
-
- const { focused, ref: containerFocusRef } = useFocusWithin();
- const player = usePlayer();
-
- useHotkeys([
- [
- 'delete',
- () => {
- if (focused) {
- const selectedItems =
- tableRef.current?.internalState.getSelected() as QueueSong[];
-
- if (!selectedItems || selectedItems.length === 0) {
- return;
+ if (isShuffleEnabled(state)) {
+ index = mapShuffledToQueueIndex(index, state.queue.shuffled);
}
- player.clearSelected(selectedItems);
+ if (index !== -1) {
+ // Use setTimeout to ensure the DOM has updated with the new queue items
+ setTimeout(() => {
+ tableRef.current?.scrollToIndex(index, {
+ align: 'center',
+ behavior: 'auto',
+ });
+ }, 0);
+ }
}
- },
- ],
- ]);
+ };
- return (
-
-
- 0 ? groups : undefined}
- initialTop={{
- to: 0,
- type: 'offset',
- }}
- itemType={LibraryItem.QUEUE_SONG}
- onColumnReordered={handleColumnReordered}
- onColumnResized={handleColumnResized}
- ref={mergedRef}
- size={table.size}
- />
- {isEmpty && }
-
- );
-});
+ eventEmitter.on('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
+
+ setQueue();
+
+ return () => {
+ unsub();
+ unsubCurrentTrack();
+ eventEmitter.off('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
+ };
+ }, [getQueue, queueType, tableRef, followCurrentSong]);
+
+ const filteredData: QueueSong[] = useMemo(() => {
+ if (debouncedSearchTerm) {
+ const searched = searchLibraryItems(data, debouncedSearchTerm, LibraryItem.SONG);
+ return searched;
+ }
+
+ return data;
+ }, [data, debouncedSearchTerm]);
+
+ const isEmpty = filteredData.length === 0;
+
+ const { handleColumnReordered } = useItemListColumnReorder({
+ itemListKey: listKey,
+ });
+
+ const { handleColumnResized } = useItemListColumnResize({
+ itemListKey: listKey,
+ });
+
+ const currentSong = usePlayerSong();
+
+ const currentSongUniqueId = currentSong?._uniqueId;
+
+ const { focused, ref: containerFocusRef } = useFocusWithin();
+ const player = usePlayer();
+
+ useHotkeys([
+ [
+ 'delete',
+ () => {
+ if (focused) {
+ const selectedItems =
+ tableRef.current?.internalState.getSelected() as QueueSong[];
+
+ if (!selectedItems || selectedItems.length === 0) {
+ return;
+ }
+
+ player.clearSelected(selectedItems);
+ }
+ },
+ ],
+ ]);
+
+ return (
+
+
+ 0 ? groups : undefined}
+ initialTop={{
+ to: 0,
+ type: 'offset',
+ }}
+ itemType={LibraryItem.QUEUE_SONG}
+ onColumnReordered={handleColumnReordered}
+ onColumnResized={handleColumnResized}
+ ref={mergedRef}
+ size={table.size}
+ />
+ {isEmpty && }
+
+ );
+ },
+);
const EmptyQueueDropZone = () => {
const playerContext = usePlayer();
diff --git a/src/renderer/features/player/components/full-screen-player-queue.tsx b/src/renderer/features/player/components/full-screen-player-queue.tsx
index e65e26b33..2f46fed68 100644
--- a/src/renderer/features/player/components/full-screen-player-queue.tsx
+++ b/src/renderer/features/player/components/full-screen-player-queue.tsx
@@ -106,7 +106,11 @@ export const FullScreenPlayerQueue = () => {
{activeTab === 'queue' ? (
) : activeTab === 'related' ? (
diff --git a/src/renderer/features/similar-songs/components/similar-songs-list.tsx b/src/renderer/features/similar-songs/components/similar-songs-list.tsx
index 048351988..41350e9ae 100644
--- a/src/renderer/features/similar-songs/components/similar-songs-list.tsx
+++ b/src/renderer/features/similar-songs/components/similar-songs-list.tsx
@@ -64,6 +64,7 @@ export const SimilarSongsList = ({ count, song }: SimilarSongsListProps) => {
enableHeader
enableHorizontalBorders={fullScreenTable?.enableHorizontalBorders}
enableRowHoverHighlight={fullScreenTable?.enableRowHoverHighlight}
+ enableScrollShadow={false}
enableSelection
enableSelectionDialog={false}
enableVerticalBorders={fullScreenTable?.enableVerticalBorders}