optimize playqueue performance for active song styles

This commit is contained in:
jeffvli
2025-11-18 20:39:44 -08:00
parent 3d7533d3d3
commit 4a68fd5914
5 changed files with 21 additions and 8 deletions
@@ -8,7 +8,6 @@ import {
TableColumnTextContainer, TableColumnTextContainer,
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column'; } from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
import { ItemListItem } from '/@/renderer/components/item-list/types'; import { ItemListItem } from '/@/renderer/components/item-list/types';
import { useIsCurrentSong } from '/@/renderer/features/player/hooks/use-is-current-song';
import { usePlayerStatus } from '/@/renderer/store'; import { usePlayerStatus } from '/@/renderer/store';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { Flex } from '/@/shared/components/flex/flex'; import { Flex } from '/@/shared/components/flex/flex';
@@ -73,7 +72,8 @@ const DefaultRowIndexColumn = (props: ItemTableListInnerColumn) => {
const QueueSongRowIndexColumn = (props: ItemTableListInnerColumn) => { const QueueSongRowIndexColumn = (props: ItemTableListInnerColumn) => {
const status = usePlayerStatus(); const status = usePlayerStatus();
const { isActive } = useIsCurrentSong(props.data[props.rowIndex] as QueueSong); const song = props.data[props.rowIndex] as QueueSong;
const isActive = props.activeRowId === song?._uniqueId;
const adjustedRowIndex = const adjustedRowIndex =
props.adjustedRowIndexMap?.get(props.rowIndex) ?? props.adjustedRowIndexMap?.get(props.rowIndex) ??
@@ -10,7 +10,6 @@ import {
ItemTableListInnerColumn, ItemTableListInnerColumn,
TableColumnContainer, TableColumnContainer,
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column'; } from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
import { useIsCurrentSong } from '/@/renderer/features/player/hooks/use-is-current-song';
import { Text } from '/@/shared/components/text/text'; import { Text } from '/@/shared/components/text/text';
import { LibraryItem, QueueSong } from '/@/shared/types/domain-types'; import { LibraryItem, QueueSong } from '/@/shared/types/domain-types';
@@ -70,7 +69,8 @@ function QueueSongTitleColumn(props: ItemTableListInnerColumn) {
props.columns[props.columnIndex].id props.columns[props.columnIndex].id
]; ];
const { isActive } = useIsCurrentSong(props.data[props.rowIndex] as QueueSong); const song = props.data[props.rowIndex] as QueueSong;
const isActive = props.activeRowId === song?._uniqueId;
if (typeof row === 'string') { if (typeof row === 'string') {
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string); const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
@@ -10,7 +10,6 @@ import {
ItemTableListInnerColumn, ItemTableListInnerColumn,
TableColumnContainer, TableColumnContainer,
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column'; } from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
import { useIsCurrentSong } from '/@/renderer/features/player/hooks/use-is-current-song';
import { AppRoute } from '/@/renderer/router/routes'; import { AppRoute } from '/@/renderer/router/routes';
import { Image } from '/@/shared/components/image/image'; import { Image } from '/@/shared/components/image/image';
import { Text } from '/@/shared/components/text/text'; import { Text } from '/@/shared/components/text/text';
@@ -79,7 +78,8 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) => { export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
const row: object | undefined = (props.data as (any | undefined)[])[props.rowIndex]; const row: object | undefined = (props.data as (any | undefined)[])[props.rowIndex];
const { isActive } = useIsCurrentSong(props.data[props.rowIndex] as QueueSong); const song = props.data[props.rowIndex] as QueueSong;
const isActive = props.activeRowId === song?._uniqueId;
const artists = useMemo(() => { const artists = useMemo(() => {
if (row && 'artists' in row && Array.isArray(row.artists)) { if (row && 'artists' in row && Array.isArray(row.artists)) {
@@ -84,6 +84,7 @@ enum TableItemSize {
} }
interface VirtualizedTableGridProps { interface VirtualizedTableGridProps {
activeRowId?: string;
calculatedColumnWidths: number[]; calculatedColumnWidths: number[];
CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>; CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>;
cellPadding: 'lg' | 'md' | 'sm' | 'xl' | 'xs'; cellPadding: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
@@ -125,6 +126,7 @@ interface VirtualizedTableGridProps {
const VirtualizedTableGrid = React.memo( const VirtualizedTableGrid = React.memo(
({ ({
activeRowId,
calculatedColumnWidths, calculatedColumnWidths,
CellComponent, CellComponent,
cellPadding, cellPadding,
@@ -271,6 +273,7 @@ const VirtualizedTableGrid = React.memo(
const itemProps: TableItemProps = useMemo( const itemProps: TableItemProps = useMemo(
() => ({ () => ({
activeRowId,
adjustedRowIndexMap, adjustedRowIndexMap,
calculatedColumnWidths, calculatedColumnWidths,
cellPadding, cellPadding,
@@ -300,11 +303,12 @@ const VirtualizedTableGrid = React.memo(
tableId, tableId,
}), }),
[ [
activeRowId,
adjustedRowIndexMap, adjustedRowIndexMap,
calculatedColumnWidths, calculatedColumnWidths,
cellPadding, cellPadding,
controls,
parsedColumns, parsedColumns,
controls,
dataWithGroups, dataWithGroups,
enableAlternateRowColors, enableAlternateRowColors,
enableColumnReorder, enableColumnReorder,
@@ -622,7 +626,8 @@ export interface TableGroupHeader {
} }
export interface TableItemProps { export interface TableItemProps {
adjustedRowIndexMap?: Map<number, number>; // Maps rowIndex to adjustedRowIndex (1-indexed, excluding group rows) activeRowId?: string; // Active row's uniqueId for QUEUE_SONG performance optimization
adjustedRowIndexMap?: Map<number, number>;
calculatedColumnWidths?: number[]; calculatedColumnWidths?: number[];
cellPadding?: ItemTableListProps['cellPadding']; cellPadding?: ItemTableListProps['cellPadding'];
columns: ItemTableListColumnConfig[]; columns: ItemTableListColumnConfig[];
@@ -653,6 +658,7 @@ export interface TableItemProps {
} }
interface ItemTableListProps { interface ItemTableListProps {
activeRowId?: string;
autoFitColumns?: boolean; autoFitColumns?: boolean;
CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>; CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>;
cellPadding?: 'lg' | 'md' | 'sm' | 'xl' | 'xs'; cellPadding?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
@@ -692,6 +698,7 @@ interface ItemTableListProps {
} }
export const ItemTableList = ({ export const ItemTableList = ({
activeRowId,
autoFitColumns = false, autoFitColumns = false,
CellComponent, CellComponent,
cellPadding = 'sm', cellPadding = 'sm',
@@ -2026,6 +2033,7 @@ export const ItemTableList = ({
{StickyHeader} {StickyHeader}
{StickyGroupRow} {StickyGroupRow}
<VirtualizedTableGrid <VirtualizedTableGrid
activeRowId={activeRowId}
calculatedColumnWidths={calculatedColumnWidths} calculatedColumnWidths={calculatedColumnWidths}
CellComponent={CellComponent} CellComponent={CellComponent}
cellPadding={cellPadding} cellPadding={cellPadding}
@@ -24,6 +24,7 @@ import {
useListSettings, useListSettings,
usePlayerActions, usePlayerActions,
usePlayerQueueType, usePlayerQueueType,
usePlayerSong,
} from '/@/renderer/store'; } from '/@/renderer/store';
import { searchSongs } from '/@/renderer/utils/search-songs'; import { searchSongs } from '/@/renderer/utils/search-songs';
import { Flex } from '/@/shared/components/flex/flex'; import { Flex } from '/@/shared/components/flex/flex';
@@ -156,10 +157,14 @@ export const PlayQueue = forwardRef<ItemListHandle, QueueProps>(({ listKey, sear
itemListKey: listKey, itemListKey: listKey,
}); });
const currentSong = usePlayerSong();
const currentSongUniqueId = currentSong?._uniqueId;
return ( return (
<div className={styles.container}> <div className={styles.container}>
<LoadingOverlay pos="absolute" visible={isFetching} /> <LoadingOverlay pos="absolute" visible={isFetching} />
<ItemTableList <ItemTableList
activeRowId={currentSongUniqueId}
autoFitColumns={table.autoFitColumns} autoFitColumns={table.autoFitColumns}
CellComponent={ItemTableListColumn} CellComponent={ItemTableListColumn}
columns={table.columns} columns={table.columns}