mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
add grid item card size presets
This commit is contained in:
@@ -135,6 +135,7 @@ export interface ItemCardDerivativeProps extends Omit<ItemCardProps, 'type'> {
|
|||||||
const CompactItemCard = ({
|
const CompactItemCard = ({
|
||||||
controls,
|
controls,
|
||||||
data,
|
data,
|
||||||
|
enableDrag,
|
||||||
enableExpansion,
|
enableExpansion,
|
||||||
enableNavigation,
|
enableNavigation,
|
||||||
internalState,
|
internalState,
|
||||||
@@ -150,6 +151,53 @@ const CompactItemCard = ({
|
|||||||
: undefined;
|
: undefined;
|
||||||
const isSelected = useItemSelectionState(internalState, itemRowId || undefined);
|
const isSelected = useItemSelectionState(internalState, itemRowId || undefined);
|
||||||
|
|
||||||
|
const { isDragging: isDraggingLocal, ref } = useDragDrop<HTMLDivElement>({
|
||||||
|
drag: {
|
||||||
|
getId: () => {
|
||||||
|
if (!data) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const draggedItems = getDraggedItems(data, internalState);
|
||||||
|
return draggedItems.map((item) => item.id);
|
||||||
|
},
|
||||||
|
getItem: () => {
|
||||||
|
if (!data) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const draggedItems = getDraggedItems(data, internalState);
|
||||||
|
return draggedItems;
|
||||||
|
},
|
||||||
|
itemType,
|
||||||
|
onDragStart: () => {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const draggedItems = getDraggedItems(data, internalState);
|
||||||
|
if (internalState) {
|
||||||
|
internalState.setDragging(draggedItems);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDrop: () => {
|
||||||
|
if (internalState) {
|
||||||
|
internalState.setDragging([]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
operation:
|
||||||
|
itemType === LibraryItem.QUEUE_SONG
|
||||||
|
? [DragOperation.REORDER, DragOperation.ADD]
|
||||||
|
: [DragOperation.ADD],
|
||||||
|
target: DragTarget.ALBUM,
|
||||||
|
},
|
||||||
|
isEnabled: !!enableDrag && !!data,
|
||||||
|
});
|
||||||
|
|
||||||
|
const itemId = data && internalState ? data.id : undefined;
|
||||||
|
const isDraggingState = useItemDraggingState(internalState, itemId);
|
||||||
|
const isDragging = isDraggingState || isDraggingLocal;
|
||||||
|
|
||||||
const handleClick = useDoubleClick({
|
const handleClick = useDoubleClick({
|
||||||
onDoubleClick: (e: React.MouseEvent<HTMLDivElement>) => {
|
onDoubleClick: (e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
if (!data || !controls || !internalState) {
|
if (!data || !controls || !internalState) {
|
||||||
@@ -289,8 +337,10 @@ const CompactItemCard = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.container, styles.compact, {
|
className={clsx(styles.container, styles.compact, {
|
||||||
|
[styles.dragging]: isDragging,
|
||||||
[styles.selected]: isSelected,
|
[styles.selected]: isSelected,
|
||||||
})}
|
})}
|
||||||
|
ref={ref}
|
||||||
>
|
>
|
||||||
{enableNavigation && navigationPath && !internalState ? (
|
{enableNavigation && navigationPath && !internalState ? (
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ interface VirtualizedGridListProps {
|
|||||||
outerRef: RefObject<any>;
|
outerRef: RefObject<any>;
|
||||||
ref: RefObject<FixedSizeList<GridItemProps> | null>;
|
ref: RefObject<FixedSizeList<GridItemProps> | null>;
|
||||||
rows?: ItemCardProps['rows'];
|
rows?: ItemCardProps['rows'];
|
||||||
|
size?: 'compact' | 'default' | 'large';
|
||||||
tableMetaRef: RefObject<null | {
|
tableMetaRef: RefObject<null | {
|
||||||
columnCount: number;
|
columnCount: number;
|
||||||
itemHeight: number;
|
itemHeight: number;
|
||||||
@@ -95,6 +96,7 @@ const VirtualizedGridList = React.memo(
|
|||||||
outerRef,
|
outerRef,
|
||||||
ref,
|
ref,
|
||||||
rows,
|
rows,
|
||||||
|
size,
|
||||||
tableMetaRef,
|
tableMetaRef,
|
||||||
width,
|
width,
|
||||||
}: VirtualizedGridListProps) => {
|
}: VirtualizedGridListProps) => {
|
||||||
@@ -113,6 +115,7 @@ const VirtualizedGridList = React.memo(
|
|||||||
internalState,
|
internalState,
|
||||||
itemType,
|
itemType,
|
||||||
rows,
|
rows,
|
||||||
|
size,
|
||||||
tableMeta,
|
tableMeta,
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
@@ -126,6 +129,7 @@ const VirtualizedGridList = React.memo(
|
|||||||
gap,
|
gap,
|
||||||
internalState,
|
internalState,
|
||||||
itemType,
|
itemType,
|
||||||
|
size,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleOnScroll = useCallback(
|
const handleOnScroll = useCallback(
|
||||||
@@ -215,7 +219,11 @@ const VirtualizedGridList = React.memo(
|
|||||||
|
|
||||||
VirtualizedGridList.displayName = 'VirtualizedGridList';
|
VirtualizedGridList.displayName = 'VirtualizedGridList';
|
||||||
|
|
||||||
const createThrottledSetTableMeta = (itemsPerRow?: number, rowsCount?: number) => {
|
const createThrottledSetTableMeta = (
|
||||||
|
itemsPerRow?: number,
|
||||||
|
rowsCount?: number,
|
||||||
|
size?: 'compact' | 'default' | 'large',
|
||||||
|
) => {
|
||||||
return throttle((width: number, dataLength: number, setTableMeta: (meta: any) => void) => {
|
return throttle((width: number, dataLength: number, setTableMeta: (meta: any) => void) => {
|
||||||
const isSm = width >= 600;
|
const isSm = width >= 600;
|
||||||
const isMd = width >= 768;
|
const isMd = width >= 768;
|
||||||
@@ -245,10 +253,22 @@ const createThrottledSetTableMeta = (itemsPerRow?: number, rowsCount?: number) =
|
|||||||
dynamicItemsPerRow = 2;
|
dynamicItemsPerRow = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size === 'large') {
|
||||||
|
dynamicItemsPerRow = Math.round(dynamicItemsPerRow * 0.75);
|
||||||
|
if (dynamicItemsPerRow < 1) {
|
||||||
|
dynamicItemsPerRow = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const setItemsPerRow = itemsPerRow || dynamicItemsPerRow;
|
const setItemsPerRow = itemsPerRow || dynamicItemsPerRow;
|
||||||
|
|
||||||
const widthPerItem = Number(width) / setItemsPerRow;
|
const widthPerItem = Number(width) / setItemsPerRow;
|
||||||
const itemHeight = widthPerItem + (rowsCount || getDataRowsCount()) * 26;
|
// For compact size, don't include text lines in height calculation
|
||||||
|
// CompactItemCard has a different layout that doesn't need the extra space
|
||||||
|
const itemHeight =
|
||||||
|
size === 'compact'
|
||||||
|
? widthPerItem
|
||||||
|
: widthPerItem + (rowsCount || getDataRowsCount()) * 26;
|
||||||
|
|
||||||
if (widthPerItem === 0) {
|
if (widthPerItem === 0) {
|
||||||
return;
|
return;
|
||||||
@@ -273,6 +293,7 @@ export interface GridItemProps {
|
|||||||
internalState: ItemListStateActions;
|
internalState: ItemListStateActions;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
rows?: ItemCardProps['rows'];
|
rows?: ItemCardProps['rows'];
|
||||||
|
size?: 'compact' | 'default' | 'large';
|
||||||
tableMeta: null | {
|
tableMeta: null | {
|
||||||
columnCount: number;
|
columnCount: number;
|
||||||
itemHeight: number;
|
itemHeight: number;
|
||||||
@@ -301,6 +322,7 @@ export interface ItemGridListProps {
|
|||||||
overrideControls?: Partial<ItemControls>;
|
overrideControls?: Partial<ItemControls>;
|
||||||
ref?: Ref<ItemListHandle>;
|
ref?: Ref<ItemListHandle>;
|
||||||
rows?: ItemCardProps['rows'];
|
rows?: ItemCardProps['rows'];
|
||||||
|
size?: 'compact' | 'default' | 'large';
|
||||||
}
|
}
|
||||||
|
|
||||||
const BaseItemGridList = ({
|
const BaseItemGridList = ({
|
||||||
@@ -320,6 +342,7 @@ const BaseItemGridList = ({
|
|||||||
overrideControls,
|
overrideControls,
|
||||||
ref,
|
ref,
|
||||||
rows,
|
rows,
|
||||||
|
size = 'default',
|
||||||
}: ItemGridListProps) => {
|
}: ItemGridListProps) => {
|
||||||
const rootRef = useRef(null);
|
const rootRef = useRef(null);
|
||||||
const outerRef = useRef(null);
|
const outerRef = useRef(null);
|
||||||
@@ -410,8 +433,8 @@ const BaseItemGridList = ({
|
|||||||
}, [osInstance]);
|
}, [osInstance]);
|
||||||
|
|
||||||
const throttledSetTableMeta = useMemo(() => {
|
const throttledSetTableMeta = useMemo(() => {
|
||||||
return createThrottledSetTableMeta(itemsPerRow, rows?.length);
|
return createThrottledSetTableMeta(itemsPerRow, rows?.length, size);
|
||||||
}, [itemsPerRow, rows?.length]);
|
}, [itemsPerRow, rows?.length, size]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const { current: container } = containerRef;
|
const { current: container } = containerRef;
|
||||||
@@ -738,6 +761,7 @@ const BaseItemGridList = ({
|
|||||||
outerRef={outerRef}
|
outerRef={outerRef}
|
||||||
ref={listRef}
|
ref={listRef}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
tableMetaRef={tableMetaRef}
|
tableMetaRef={tableMetaRef}
|
||||||
width={width}
|
width={width}
|
||||||
/>
|
/>
|
||||||
@@ -753,7 +777,7 @@ const BaseItemGridList = ({
|
|||||||
|
|
||||||
const ListComponent = memo((props: ListChildComponentProps<GridItemProps>) => {
|
const ListComponent = memo((props: ListChildComponentProps<GridItemProps>) => {
|
||||||
const { index, style } = props;
|
const { index, style } = props;
|
||||||
const { columns, controls, data, enableDrag, gap, itemType, rows } = props.data;
|
const { columns, controls, data, enableDrag, gap, itemType, rows, size } = props.data;
|
||||||
|
|
||||||
const items: ReactNode[] = [];
|
const items: ReactNode[] = [];
|
||||||
const itemCount = data.length;
|
const itemCount = data.length;
|
||||||
@@ -784,6 +808,7 @@ const ListComponent = memo((props: ListChildComponentProps<GridItemProps>) => {
|
|||||||
internalState={props.data.internalState}
|
internalState={props.data.internalState}
|
||||||
itemType={itemType}
|
itemType={itemType}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
type={size === 'compact' ? 'compact' : 'poster'}
|
||||||
withControls
|
withControls
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export interface ItemListComponentProps<TQuery> {
|
|||||||
export interface ItemListGridComponentProps<TQuery> extends ItemListComponentProps<TQuery> {
|
export interface ItemListGridComponentProps<TQuery> extends ItemListComponentProps<TQuery> {
|
||||||
gap?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
|
gap?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
|
||||||
itemsPerRow?: number;
|
itemsPerRow?: number;
|
||||||
|
size?: 'compact' | 'default' | 'large';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemListHandle {
|
export interface ItemListHandle {
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ export const AlbumListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -126,6 +127,7 @@ export const AlbumListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export const AlbumListInfiniteGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: AlbumListInfiniteGridProps) => {
|
}: AlbumListInfiniteGridProps) => {
|
||||||
const listCountQuery = albumQueries.listCount({
|
const listCountQuery = albumQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -65,6 +66,7 @@ export const AlbumListInfiniteGrid = ({
|
|||||||
onRangeChanged={onRangeChanged}
|
onRangeChanged={onRangeChanged}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const AlbumListPaginatedGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: AlbumListPaginatedGridProps) => {
|
}: AlbumListPaginatedGridProps) => {
|
||||||
const listCountQuery = albumQueries.listCount({
|
const listCountQuery = albumQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -77,6 +78,7 @@ export const AlbumListPaginatedGrid = ({
|
|||||||
itemType={LibraryItem.ALBUM}
|
itemType={LibraryItem.ALBUM}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
</ItemListWithPagination>
|
</ItemListWithPagination>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ export const AlbumArtistListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -105,6 +106,7 @@ export const AlbumArtistListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const AlbumArtistListInfiniteGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: AlbumArtistListInfiniteGridProps) => {
|
}: AlbumArtistListInfiniteGridProps) => {
|
||||||
const listCountQuery = artistsQueries.albumArtistListCount({
|
const listCountQuery = artistsQueries.albumArtistListCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -65,6 +66,7 @@ export const AlbumArtistListInfiniteGrid = ({
|
|||||||
onRangeChanged={onRangeChanged}
|
onRangeChanged={onRangeChanged}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export const AlbumArtistListPaginatedGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: AlbumArtistListPaginatedGridProps) => {
|
}: AlbumArtistListPaginatedGridProps) => {
|
||||||
const listCountQuery = artistsQueries.albumArtistListCount({
|
const listCountQuery = artistsQueries.albumArtistListCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -77,6 +78,7 @@ export const AlbumArtistListPaginatedGrid = ({
|
|||||||
itemType={LibraryItem.ALBUM_ARTIST}
|
itemType={LibraryItem.ALBUM_ARTIST}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
</ItemListWithPagination>
|
</ItemListWithPagination>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export const ArtistListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -97,6 +98,7 @@ export const ArtistListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export const ArtistListInfiniteGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: ArtistListInfiniteGridProps) => {
|
}: ArtistListInfiniteGridProps) => {
|
||||||
const listCountQuery = artistsQueries.artistListCount({
|
const listCountQuery = artistsQueries.artistListCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -64,6 +65,7 @@ export const ArtistListInfiniteGrid = ({
|
|||||||
onRangeChanged={onRangeChanged}
|
onRangeChanged={onRangeChanged}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const ArtistListPaginatedGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: ArtistListPaginatedGridProps) => {
|
}: ArtistListPaginatedGridProps) => {
|
||||||
const listCountQuery = artistsQueries.artistListCount({
|
const listCountQuery = artistsQueries.artistListCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -76,6 +77,7 @@ export const ArtistListPaginatedGrid = ({
|
|||||||
itemType={LibraryItem.ARTIST}
|
itemType={LibraryItem.ARTIST}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
</ItemListWithPagination>
|
</ItemListWithPagination>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ export const GenreListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -93,6 +94,7 @@ export const GenreListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export const GenreListInfiniteGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: GenreListInfiniteGridProps) => {
|
}: GenreListInfiniteGridProps) => {
|
||||||
const listCountQuery = genresQueries.listCount({
|
const listCountQuery = genresQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -64,6 +65,7 @@ export const GenreListInfiniteGrid = ({
|
|||||||
onRangeChanged={onRangeChanged}
|
onRangeChanged={onRangeChanged}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const GenreListPaginatedGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: GenreListPaginatedGridProps) => {
|
}: GenreListPaginatedGridProps) => {
|
||||||
const listCountQuery = genresQueries.listCount({
|
const listCountQuery = genresQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -76,6 +77,7 @@ export const GenreListPaginatedGrid = ({
|
|||||||
itemType={LibraryItem.GENRE}
|
itemType={LibraryItem.GENRE}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
</ItemListWithPagination>
|
</ItemListWithPagination>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ export const PlaylistListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -103,6 +104,7 @@ export const PlaylistListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export const PlaylistListInfiniteGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: PlaylistListInfiniteGridProps) => {
|
}: PlaylistListInfiniteGridProps) => {
|
||||||
const listCountQuery = playlistsQueries.listCount({
|
const listCountQuery = playlistsQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -64,6 +65,7 @@ export const PlaylistListInfiniteGrid = ({
|
|||||||
onRangeChanged={onRangeChanged}
|
onRangeChanged={onRangeChanged}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const PlaylistListPaginatedGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: PlaylistListPaginatedGridProps) => {
|
}: PlaylistListPaginatedGridProps) => {
|
||||||
const listCountQuery = playlistsQueries.listCount({
|
const listCountQuery = playlistsQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -76,6 +77,7 @@ export const PlaylistListPaginatedGrid = ({
|
|||||||
itemType={LibraryItem.PLAYLIST}
|
itemType={LibraryItem.PLAYLIST}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
</ItemListWithPagination>
|
</ItemListWithPagination>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -223,6 +223,43 @@ export const GridConfig = ({
|
|||||||
</Group>
|
</Group>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: (
|
||||||
|
<SegmentedControl
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: t('table.config.general.size_compact', {
|
||||||
|
postProcess: 'titleCase',
|
||||||
|
}),
|
||||||
|
value: 'compact',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('table.config.general.size_default', {
|
||||||
|
postProcess: 'titleCase',
|
||||||
|
}),
|
||||||
|
value: 'default',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('table.config.general.size_large', {
|
||||||
|
postProcess: 'titleCase',
|
||||||
|
}),
|
||||||
|
value: 'large',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onChange={(value) =>
|
||||||
|
setList(listKey, {
|
||||||
|
grid: { size: value as 'compact' | 'default' | 'large' },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
size="sm"
|
||||||
|
value={grid.size || 'default'}
|
||||||
|
w="100%"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
id: 'size',
|
||||||
|
label: t('table.config.general.size', { postProcess: 'sentenceCase' }),
|
||||||
|
size: 'sm',
|
||||||
|
},
|
||||||
|
|
||||||
...(extraOptions || []),
|
...(extraOptions || []),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ export const SongListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case ListPaginationType.PAGINATED:
|
case ListPaginationType.PAGINATED:
|
||||||
@@ -122,6 +123,7 @@ export const SongListView = ({
|
|||||||
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
itemsPerRow={grid.itemsPerRowEnabled ? grid.itemsPerRow : undefined}
|
||||||
query={mergedQuery}
|
query={mergedQuery}
|
||||||
serverId={server.id}
|
serverId={server.id}
|
||||||
|
size={grid.size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export const SongListInfiniteGrid = ({
|
|||||||
},
|
},
|
||||||
saveScrollOffset = true,
|
saveScrollOffset = true,
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: SongListInfiniteGridProps) => {
|
}: SongListInfiniteGridProps) => {
|
||||||
const listCountQuery = songsQueries.listCount({
|
const listCountQuery = songsQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -59,6 +60,7 @@ export const SongListInfiniteGrid = ({
|
|||||||
onRangeChanged={onRangeChanged}
|
onRangeChanged={onRangeChanged}
|
||||||
onScrollEnd={handleOnScrollEnd}
|
onScrollEnd={handleOnScrollEnd}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export const SongListPaginatedGrid = ({
|
|||||||
sortOrder: SortOrder.ASC,
|
sortOrder: SortOrder.ASC,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
|
size,
|
||||||
}: SongListPaginatedGridProps) => {
|
}: SongListPaginatedGridProps) => {
|
||||||
const listCountQuery = songsQueries.listCount({
|
const listCountQuery = songsQueries.listCount({
|
||||||
query: { ...query },
|
query: { ...query },
|
||||||
@@ -60,6 +61,7 @@ export const SongListPaginatedGrid = ({
|
|||||||
itemsPerRow={itemsPerRow}
|
itemsPerRow={itemsPerRow}
|
||||||
itemType={LibraryItem.SONG}
|
itemType={LibraryItem.SONG}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
size={size}
|
||||||
/>
|
/>
|
||||||
</ItemListWithPagination>
|
</ItemListWithPagination>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ const ItemListConfigSchema = z.object({
|
|||||||
itemsPerRow: z.number(),
|
itemsPerRow: z.number(),
|
||||||
itemsPerRowEnabled: z.boolean(),
|
itemsPerRowEnabled: z.boolean(),
|
||||||
rows: z.array(ItemGridListRowConfigSchema),
|
rows: z.array(ItemGridListRowConfigSchema),
|
||||||
|
size: z.enum(['compact', 'default', 'large']),
|
||||||
}),
|
}),
|
||||||
itemsPerPage: z.number(),
|
itemsPerPage: z.number(),
|
||||||
pagination: z.nativeEnum(ListPaginationType),
|
pagination: z.nativeEnum(ListPaginationType),
|
||||||
@@ -539,6 +540,7 @@ export type DataGridProps = {
|
|||||||
itemsPerRow: number;
|
itemsPerRow: number;
|
||||||
itemsPerRowEnabled: boolean;
|
itemsPerRowEnabled: boolean;
|
||||||
rows: ItemGridListRowConfig[];
|
rows: ItemGridListRowConfig[];
|
||||||
|
size: 'compact' | 'default' | 'large';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DataTableProps = z.infer<typeof ItemTableListPropsSchema>;
|
export type DataTableProps = z.infer<typeof ItemTableListPropsSchema>;
|
||||||
@@ -823,6 +825,7 @@ const initialState: SettingsState = {
|
|||||||
itemsPerRow: 6,
|
itemsPerRow: 6,
|
||||||
itemsPerRowEnabled: false,
|
itemsPerRowEnabled: false,
|
||||||
rows: [],
|
rows: [],
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -860,6 +863,7 @@ const initialState: SettingsState = {
|
|||||||
itemsPerRow: 6,
|
itemsPerRow: 6,
|
||||||
itemsPerRowEnabled: false,
|
itemsPerRowEnabled: false,
|
||||||
rows: [],
|
rows: [],
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -908,6 +912,7 @@ const initialState: SettingsState = {
|
|||||||
TableColumn.YEAR,
|
TableColumn.YEAR,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -945,6 +950,7 @@ const initialState: SettingsState = {
|
|||||||
TableColumn.SONG_COUNT,
|
TableColumn.SONG_COUNT,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -989,6 +995,7 @@ const initialState: SettingsState = {
|
|||||||
TableColumn.SONG_COUNT,
|
TableColumn.SONG_COUNT,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -1040,6 +1047,7 @@ const initialState: SettingsState = {
|
|||||||
TableColumn.SONG_COUNT,
|
TableColumn.SONG_COUNT,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -1072,6 +1080,7 @@ const initialState: SettingsState = {
|
|||||||
enabledColumns: [TableColumn.TITLE],
|
enabledColumns: [TableColumn.TITLE],
|
||||||
pickColumns: [TableColumn.TITLE, TableColumn.SONG_COUNT],
|
pickColumns: [TableColumn.TITLE, TableColumn.SONG_COUNT],
|
||||||
}),
|
}),
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -1101,6 +1110,7 @@ const initialState: SettingsState = {
|
|||||||
itemsPerRow: 6,
|
itemsPerRow: 6,
|
||||||
itemsPerRowEnabled: false,
|
itemsPerRowEnabled: false,
|
||||||
rows: [],
|
rows: [],
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -1128,6 +1138,7 @@ const initialState: SettingsState = {
|
|||||||
itemsPerRow: 6,
|
itemsPerRow: 6,
|
||||||
itemsPerRowEnabled: false,
|
itemsPerRowEnabled: false,
|
||||||
rows: [],
|
rows: [],
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
@@ -1173,6 +1184,7 @@ const initialState: SettingsState = {
|
|||||||
TableColumn.TRACK_NUMBER,
|
TableColumn.TRACK_NUMBER,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.PAGINATED,
|
pagination: ListPaginationType.PAGINATED,
|
||||||
@@ -1200,6 +1212,7 @@ const initialState: SettingsState = {
|
|||||||
itemsPerRow: 6,
|
itemsPerRow: 6,
|
||||||
itemsPerRowEnabled: false,
|
itemsPerRowEnabled: false,
|
||||||
rows: [],
|
rows: [],
|
||||||
|
size: 'default',
|
||||||
},
|
},
|
||||||
itemsPerPage: 100,
|
itemsPerPage: 100,
|
||||||
pagination: ListPaginationType.INFINITE,
|
pagination: ListPaginationType.INFINITE,
|
||||||
|
|||||||
Reference in New Issue
Block a user