refactor item list to use accessor function

This commit is contained in:
jeffvli
2026-01-16 16:34:31 -08:00
parent e2b20eb89b
commit d1aed5007f
39 changed files with 528 additions and 324 deletions
@@ -6,7 +6,7 @@ import { ItemListItem } from '/@/renderer/components/item-list/types';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
export const ActionsColumn = (props: ItemTableListInnerColumn) => {
const row: any = (props.data as (any | undefined)[])[props.rowIndex];
const row: any = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const handleActionClick = (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
@@ -13,11 +13,10 @@ import { JoinedArtists } from '/@/renderer/features/albums/components/joined-art
import { Album, RelatedAlbumArtist, Song } from '/@/shared/types/domain-types';
const AlbumArtistsColumn = (props: ItemTableListInnerColumn) => {
const row: RelatedAlbumArtist[] | undefined = (
props.data as (RelatedAlbumArtist[] | undefined)[]
)[props.rowIndex]?.[props.columns[props.columnIndex].id];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: RelatedAlbumArtist[] | undefined = rowItem?.[props.columns[props.columnIndex].id];
const item = props.data[props.rowIndex] as Album | Song | undefined;
const item = rowItem as Album | Song | undefined;
const albumArtistString = item && 'albumArtistName' in item ? item.albumArtistName : '';
if (Array.isArray(row)) {
@@ -15,11 +15,10 @@ import { Text } from '/@/shared/components/text/text';
import { Song } from '/@/shared/types/domain-types';
const AlbumColumn = (props: ItemTableListInnerColumn) => {
const row: null | string | undefined = (props.data as (null | string | undefined)[])[
props.rowIndex
]?.[props.columns[props.columnIndex].id];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: null | string | undefined = rowItem?.[props.columns[props.columnIndex].id];
const song = props.data[props.rowIndex] as Song | undefined;
const song = rowItem as Song | undefined;
const albumId = song?.albumId;
const albumPath = useMemo(() => {
@@ -16,9 +16,8 @@ import { Text } from '/@/shared/components/text/text';
import { LibraryItem, RelatedAlbumArtist, Song } from '/@/shared/types/domain-types';
const AlbumArtistsColumn = (props: ItemTableListInnerColumn) => {
const row: RelatedAlbumArtist[] | undefined = (
props.data as (RelatedAlbumArtist[] | undefined)[]
)[props.rowIndex]?.[props.columns[props.columnIndex].id];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: RelatedAlbumArtist[] | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
const artists = useMemo(() => {
if (!row) return [];
@@ -67,7 +66,8 @@ const AlbumArtistsColumn = (props: ItemTableListInnerColumn) => {
};
const SongArtistsColumn = (props: ItemTableListInnerColumn) => {
const row: Song | undefined = (props.data as (Song | undefined)[])[props.rowIndex];
const row: Song | undefined =
(props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex]) as Song | undefined;
if (row) {
return (
@@ -6,9 +6,8 @@ import {
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
export const CountColumn = (props: ItemTableListInnerColumn) => {
const row: number | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: number | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'number') {
return (
@@ -30,9 +30,8 @@ const getDateTooltipLabel = (utcString: string) => {
};
export const DateColumn = (props: ItemTableListInnerColumn) => {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'string' && row) {
return (
@@ -52,12 +51,11 @@ export const DateColumn = (props: ItemTableListInnerColumn) => {
};
export const AbsoluteDateColumn = (props: ItemTableListInnerColumn) => {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (props.type === TableColumn.RELEASE_DATE) {
const item = (props.data as (any | undefined)[])[props.rowIndex];
const item = rowItem as any;
if (item && 'releaseDate' in item && item.releaseDate) {
const releaseDate = item.releaseDate;
const originalDate =
@@ -115,9 +113,8 @@ export const AbsoluteDateColumn = (props: ItemTableListInnerColumn) => {
};
export const RelativeDateColumn = (props: ItemTableListInnerColumn) => {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'string') {
return (
@@ -6,9 +6,8 @@ import {
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
export const DefaultColumn = (props: ItemTableListInnerColumn) => {
const row: any | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: any | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'string') {
return <TableColumnTextContainer {...props}>{row}</TableColumnTextContainer>;
@@ -8,9 +8,8 @@ import {
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
export const DurationColumn = (props: ItemTableListInnerColumn) => {
const row: number | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: number | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'number') {
return (
@@ -8,9 +8,8 @@ import { useIsMutatingDeleteFavorite } from '/@/renderer/features/shared/mutatio
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
export const FavoriteColumn = (props: ItemTableListInnerColumn) => {
const row: boolean | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: boolean | undefined = rowItem?.[props.columns[props.columnIndex].id];
const isMutatingCreateFavorite = useIsMutatingCreateFavorite();
const isMutatingDeleteFavorite = useIsMutatingDeleteFavorite();
@@ -31,7 +30,7 @@ export const FavoriteColumn = (props: ItemTableListInnerColumn) => {
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
const item = props.data[props.rowIndex] as ItemListItem;
const item = rowItem as ItemListItem;
const rowId = props.internalState.extractRowId(item);
const index = rowId ? props.internalState.findItemIndex(rowId) : -1;
props.controls.onFavorite?.({
@@ -18,9 +18,8 @@ import { stringToColor } from '/@/shared/utils/string-to-color';
const MAX_GENRES = 4;
const GenreBadgeColumn = (props: ItemTableListInnerColumn) => {
const row: Genre[] | undefined = (props.data as (Genre[] | undefined)[])[props.rowIndex]?.[
'genres'
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: Genre[] | undefined = (rowItem as any)?.genres;
const genres = useMemo(() => {
if (!row) return [];
@@ -15,9 +15,8 @@ import { Text } from '/@/shared/components/text/text';
import { Genre } from '/@/shared/types/domain-types';
const GenreColumn = (props: ItemTableListInnerColumn) => {
const row: Genre[] | undefined = (props.data as (Genre[] | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: Genre[] | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
const genres = useMemo(() => {
if (!row) return [];
@@ -20,8 +20,9 @@ import { Folder, LibraryItem } from '/@/shared/types/domain-types';
import { Play } from '/@/shared/types/types';
export const ImageColumn = (props: ItemTableListInnerColumn) => {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.id;
const item = props.data[props.rowIndex] as any;
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = rowItem?.id;
const item = rowItem as any;
const playButtonBehavior = usePlayButtonBehavior();
const internalState = (props as any).internalState;
const [isHovered, setIsHovered] = useState(false);
@@ -113,7 +114,7 @@ export const ImageColumn = (props: ItemTableListInnerColumn) => {
);
}
if ((props.data[props.rowIndex] as unknown as Folder)?._itemType === LibraryItem.FOLDER) {
if ((rowItem as unknown as Folder)?._itemType === LibraryItem.FOLDER) {
return (
<TableColumnContainer {...props}>
<Icon className={styles.folderIcon} icon="folder" size="2xl" />
@@ -6,9 +6,8 @@ import {
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
export const NumericColumn = (props: ItemTableListInnerColumn) => {
const row: number | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: number | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'number') {
return <TableColumnTextContainer {...props}>{row}</TableColumnTextContainer>;
@@ -6,9 +6,8 @@ import {
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
export const PathColumn = (props: ItemTableListInnerColumn) => {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'string' && row) {
return (
@@ -24,7 +24,9 @@ export const PlaylistReorderColumn = (props: ItemTableListInnerColumn) => {
const { playlistId } = useParams() as { playlistId?: string };
const isHeaderEnabled = !!props.enableHeader;
const isDataRow = isHeaderEnabled ? props.rowIndex > 0 : true;
const item = isDataRow ? props.data[props.rowIndex] : null;
const item = isDataRow
? (props.getRowItem?.(props.rowIndex) ?? props.data[props.rowIndex])
: null;
const isPlaylistSong = props.itemType === LibraryItem.PLAYLIST_SONG;
@@ -153,8 +155,8 @@ export const PlaylistReorderColumn = (props: ItemTableListInnerColumn) => {
const isDragging = props.internalState ? isDraggingState : isDraggingLocal;
const getValidDataItems = useCallback(() => {
return props.data.filter((d) => d !== null && (d as any).id);
}, [props.data]);
return props.internalState.getData().filter((d) => d !== null && (d as any).id);
}, [props.internalState]);
const handleMoveUp = useCallback(() => {
if (!item || !isDataRow || !isPlaylistSong || !playlistId) {
@@ -7,9 +7,8 @@ import { useIsMutatingRating } from '/@/renderer/features/shared/mutations/set-r
import { Rating } from '/@/shared/components/rating/rating';
export const RatingColumn = (props: ItemTableListInnerColumn) => {
const row: null | number | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: null | number | undefined = rowItem?.[props.columns[props.columnIndex].id];
const isMutatingRating = useIsMutatingRating();
@@ -19,7 +18,7 @@ export const RatingColumn = (props: ItemTableListInnerColumn) => {
<Rating
className={row ? undefined : 'hover-only-flex'}
onChange={(rating) => {
const item = props.data[props.rowIndex] as ItemListItem;
const item = rowItem as ItemListItem;
const rowId = props.internalState.extractRowId(item);
const index = rowId ? props.internalState.findItemIndex(rowId) : -1;
props.controls.onRating?.({
@@ -61,7 +61,7 @@ const DefaultRowIndexColumn = (props: ItemTableListInnerColumn) => {
icon="arrowDownS"
iconProps={{ color: 'muted', size: 'md' }}
onClick={(e) => {
const item = data[rowIndex] as ItemListItem;
const item = (props.getRowItem?.(rowIndex) ?? data[rowIndex]) as ItemListItem;
const rowId = internalState.extractRowId(item);
const index = rowId ? internalState.findItemIndex(rowId) : -1;
controls.onExpand?.({
@@ -87,7 +87,7 @@ const DefaultRowIndexColumn = (props: ItemTableListInnerColumn) => {
const QueueSongRowIndexColumn = (props: ItemTableListInnerColumn) => {
const status = usePlayerStatus();
const song = props.data[props.rowIndex] as QueueSong;
const song = (props.getRowItem?.(props.rowIndex) ?? props.data[props.rowIndex]) as QueueSong;
const isActive = useIsActiveRow(song?.id, song?._uniqueId);
const isActiveAndPlaying = isActive && status === PlayerStatus.PLAYING;
@@ -7,9 +7,8 @@ import {
import { formatSizeString } from '/@/renderer/utils/format';
export const SizeColumn = (props: ItemTableListInnerColumn) => {
const row: number | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: number | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'number') {
return (
@@ -10,9 +10,8 @@ import {
} from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
export const TextColumn = (props: ItemTableListInnerColumn) => {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (typeof row === 'string' && row) {
return (
@@ -29,13 +29,12 @@ export const TitleColumn = (props: ItemTableListInnerColumn) => {
};
function DefaultTitleColumn(props: ItemTableListInnerColumn) {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = rowItem?.[props.columns[props.columnIndex].id];
if (typeof row === 'string') {
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const item = props.data[props.rowIndex] as any;
const path = getTitlePath(props.itemType, (rowItem as any).id as string);
const item = rowItem as any;
const titleLinkProps = path
? {
@@ -71,16 +70,15 @@ function DefaultTitleColumn(props: ItemTableListInnerColumn) {
}
function QueueSongTitleColumn(props: ItemTableListInnerColumn) {
const row: string | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: string | undefined = rowItem?.[props.columns[props.columnIndex].id];
const song = props.data[props.rowIndex] as QueueSong;
const song = rowItem as QueueSong;
const isActive = useIsActiveRow(song?.id, song?._uniqueId);
if (typeof row === 'string') {
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const item = props.data[props.rowIndex] as any;
const path = getTitlePath(props.itemType, (rowItem as any).id as string);
const item = rowItem as any;
const titleLinkProps = path
? {
@@ -26,8 +26,9 @@ import { Folder, LibraryItem, QueueSong } from '/@/shared/types/domain-types';
import { Play } from '/@/shared/types/types';
export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
const row: object | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.id;
const item = props.data[props.rowIndex] as any;
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: object | undefined = (rowItem as any)?.id;
const item = rowItem as any;
const internalState = (props as any).internalState;
const playButtonBehavior = usePlayButtonBehavior();
const [isHovered, setIsHovered] = useState(false);
@@ -76,9 +77,9 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
if (item && 'name' in item && 'imageUrl' in item && 'artists' in item) {
const rowHeight = props.getRowHeight(props.rowIndex, props);
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const path = getTitlePath(props.itemType, (rowItem as any).id as string);
const item = props.data[props.rowIndex] as any;
const item = rowItem as any;
const titleLinkProps = path
? {
component: Link,
@@ -156,10 +157,11 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
};
export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
const row: object | undefined = (props.data as (any | undefined)[])[props.rowIndex];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const row: object | undefined = rowItem as any;
const song = props.data[props.rowIndex] as QueueSong;
const item = props.data[props.rowIndex] as any;
const song = rowItem as QueueSong;
const item = rowItem as any;
const internalState = (props as any).internalState;
const playButtonBehavior = usePlayButtonBehavior();
const [isHovered, setIsHovered] = useState(false);
@@ -209,9 +211,9 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) =>
if (row && 'name' in row && 'imageUrl' in row && 'artists' in row) {
const rowHeight = props.getRowHeight(props.rowIndex, props);
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const path = getTitlePath(props.itemType, (rowItem as any).id as string);
const item = props.data[props.rowIndex] as any;
const item = rowItem as any;
const titleLinkProps = path
? {
@@ -306,11 +308,11 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) =>
);
}
if ((props.data[props.rowIndex] as unknown as Folder)?._itemType === LibraryItem.FOLDER) {
if ((rowItem as unknown as Folder)?._itemType === LibraryItem.FOLDER) {
const rowHeight = props.getRowHeight(props.rowIndex, props);
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const path = getTitlePath(props.itemType, (rowItem as any).id as string);
const item = props.data[props.rowIndex] as any;
const item = rowItem as any;
const textStyles = isActive ? { color: 'var(--theme-colors-primary)' } : {};
const titleLinkProps = path
@@ -322,7 +324,7 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) =>
}
: {};
const title = (props.data[props.rowIndex] as unknown as Folder)?.name;
const title = (rowItem as unknown as Folder)?.name;
return (
<TableColumnContainer
@@ -7,7 +7,8 @@ import {
import { SEPARATOR_STRING } from '/@/shared/api/utils';
export const YearColumn = (props: ItemTableListInnerColumn) => {
const item = (props.data as (any | undefined)[])[props.rowIndex];
const rowItem = props.getRowItem?.(props.rowIndex) ?? (props.data as any[])[props.rowIndex];
const item = rowItem as any;
if (item && 'releaseYear' in item && item.releaseYear !== null) {
const releaseYear = item.releaseYear;
@@ -29,9 +30,7 @@ export const YearColumn = (props: ItemTableListInnerColumn) => {
}
}
const row: number | undefined = (props.data as (any | undefined)[])[props.rowIndex]?.[
props.columns[props.columnIndex].id
];
const row: number | undefined = (rowItem as any)?.[props.columns[props.columnIndex].id];
if (row === null) {
return <ColumnNullFallback {...props} />;