mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
remove scroll shadows from fullscreen player
This commit is contained in:
@@ -103,6 +103,7 @@ interface VirtualizedTableGridProps {
|
|||||||
enableHeader: boolean;
|
enableHeader: boolean;
|
||||||
enableHorizontalBorders: boolean;
|
enableHorizontalBorders: boolean;
|
||||||
enableRowHoverHighlight: boolean;
|
enableRowHoverHighlight: boolean;
|
||||||
|
enableScrollShadow: boolean;
|
||||||
enableSelection: boolean;
|
enableSelection: boolean;
|
||||||
enableVerticalBorders: boolean;
|
enableVerticalBorders: boolean;
|
||||||
getRowHeight: (index: number, cellProps: TableItemProps) => number;
|
getRowHeight: (index: number, cellProps: TableItemProps) => number;
|
||||||
@@ -146,6 +147,7 @@ const VirtualizedTableGrid = ({
|
|||||||
enableHeader,
|
enableHeader,
|
||||||
enableHorizontalBorders,
|
enableHorizontalBorders,
|
||||||
enableRowHoverHighlight,
|
enableRowHoverHighlight,
|
||||||
|
enableScrollShadow,
|
||||||
enableSelection,
|
enableSelection,
|
||||||
enableVerticalBorders,
|
enableVerticalBorders,
|
||||||
getRowHeight,
|
getRowHeight,
|
||||||
@@ -429,7 +431,7 @@ const VirtualizedTableGrid = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{enableHeader && showTopShadow && (
|
{enableHeader && enableScrollShadow && showTopShadow && (
|
||||||
<div className={styles.itemTableTopScrollShadow} />
|
<div className={styles.itemTableTopScrollShadow} />
|
||||||
)}
|
)}
|
||||||
{!!pinnedLeftColumnCount && (
|
{!!pinnedLeftColumnCount && (
|
||||||
@@ -489,7 +491,7 @@ const VirtualizedTableGrid = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{enableHeader && showTopShadow && (
|
{enableHeader && enableScrollShadow && showTopShadow && (
|
||||||
<div className={styles.itemTableTopScrollShadow} />
|
<div className={styles.itemTableTopScrollShadow} />
|
||||||
)}
|
)}
|
||||||
<div className={styles.itemTableGridContainer} ref={mergedRowRef}>
|
<div className={styles.itemTableGridContainer} ref={mergedRowRef}>
|
||||||
@@ -507,10 +509,10 @@ const VirtualizedTableGrid = ({
|
|||||||
return getRowHeight(index + pinnedRowCount, cellProps);
|
return getRowHeight(index + pinnedRowCount, cellProps);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{pinnedLeftColumnCount > 0 && showLeftShadow && (
|
{pinnedLeftColumnCount > 0 && enableScrollShadow && showLeftShadow && (
|
||||||
<div className={styles.itemTableLeftScrollShadow} />
|
<div className={styles.itemTableLeftScrollShadow} />
|
||||||
)}
|
)}
|
||||||
{pinnedRightColumnCount > 0 && showRightShadow && (
|
{pinnedRightColumnCount > 0 && enableScrollShadow && showRightShadow && (
|
||||||
<div className={styles.itemTableRightScrollShadow} />
|
<div className={styles.itemTableRightScrollShadow} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -560,7 +562,7 @@ const VirtualizedTableGrid = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{enableHeader && showTopShadow && (
|
{enableHeader && enableScrollShadow && showTopShadow && (
|
||||||
<div className={styles.itemTableTopScrollShadow} />
|
<div className={styles.itemTableTopScrollShadow} />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
@@ -607,6 +609,7 @@ const MemoizedVirtualizedTableGrid = memo(VirtualizedTableGrid, (prevProps, next
|
|||||||
prevProps.enableHeader === nextProps.enableHeader &&
|
prevProps.enableHeader === nextProps.enableHeader &&
|
||||||
prevProps.enableHorizontalBorders === nextProps.enableHorizontalBorders &&
|
prevProps.enableHorizontalBorders === nextProps.enableHorizontalBorders &&
|
||||||
prevProps.enableRowHoverHighlight === nextProps.enableRowHoverHighlight &&
|
prevProps.enableRowHoverHighlight === nextProps.enableRowHoverHighlight &&
|
||||||
|
prevProps.enableScrollShadow === nextProps.enableScrollShadow &&
|
||||||
prevProps.enableSelection === nextProps.enableSelection &&
|
prevProps.enableSelection === nextProps.enableSelection &&
|
||||||
prevProps.enableVerticalBorders === nextProps.enableVerticalBorders &&
|
prevProps.enableVerticalBorders === nextProps.enableVerticalBorders &&
|
||||||
prevProps.getRowHeight === nextProps.getRowHeight &&
|
prevProps.getRowHeight === nextProps.getRowHeight &&
|
||||||
@@ -695,6 +698,7 @@ interface ItemTableListProps {
|
|||||||
enableHeader?: boolean;
|
enableHeader?: boolean;
|
||||||
enableHorizontalBorders?: boolean;
|
enableHorizontalBorders?: boolean;
|
||||||
enableRowHoverHighlight?: boolean;
|
enableRowHoverHighlight?: boolean;
|
||||||
|
enableScrollShadow?: boolean;
|
||||||
enableSelection?: boolean;
|
enableSelection?: boolean;
|
||||||
enableSelectionDialog?: boolean;
|
enableSelectionDialog?: boolean;
|
||||||
enableStickyGroupRows?: boolean;
|
enableStickyGroupRows?: boolean;
|
||||||
@@ -737,6 +741,7 @@ const BaseItemTableList = ({
|
|||||||
enableHeader = true,
|
enableHeader = true,
|
||||||
enableHorizontalBorders = false,
|
enableHorizontalBorders = false,
|
||||||
enableRowHoverHighlight = true,
|
enableRowHoverHighlight = true,
|
||||||
|
enableScrollShadow = true,
|
||||||
enableSelection = true,
|
enableSelection = true,
|
||||||
enableStickyGroupRows = false,
|
enableStickyGroupRows = false,
|
||||||
enableStickyHeader = false,
|
enableStickyHeader = false,
|
||||||
@@ -2386,6 +2391,7 @@ const BaseItemTableList = ({
|
|||||||
enableHeader={enableHeader}
|
enableHeader={enableHeader}
|
||||||
enableHorizontalBorders={enableHorizontalBorders}
|
enableHorizontalBorders={enableHorizontalBorders}
|
||||||
enableRowHoverHighlight={enableRowHoverHighlight}
|
enableRowHoverHighlight={enableRowHoverHighlight}
|
||||||
|
enableScrollShadow={enableScrollShadow}
|
||||||
enableSelection={enableSelection}
|
enableSelection={enableSelection}
|
||||||
enableVerticalBorders={enableVerticalBorders}
|
enableVerticalBorders={enableVerticalBorders}
|
||||||
getRowHeight={getRowHeight}
|
getRowHeight={getRowHeight}
|
||||||
|
|||||||
@@ -39,182 +39,190 @@ import { DragTarget } from '/@/shared/types/drag-and-drop';
|
|||||||
import { ItemListKey, Play, PlayerQueueType } from '/@/shared/types/types';
|
import { ItemListKey, Play, PlayerQueueType } from '/@/shared/types/types';
|
||||||
|
|
||||||
type QueueProps = {
|
type QueueProps = {
|
||||||
|
enableScrollShadow?: boolean;
|
||||||
listKey: ItemListKey;
|
listKey: ItemListKey;
|
||||||
searchTerm: string | undefined;
|
searchTerm: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PlayQueue = forwardRef<ItemListHandle, QueueProps>(({ listKey, searchTerm }, ref) => {
|
export const PlayQueue = forwardRef<ItemListHandle, QueueProps>(
|
||||||
const { table } = useListSettings(listKey) || {};
|
({ enableScrollShadow = true, listKey, searchTerm }, ref) => {
|
||||||
|
const { table } = useListSettings(listKey) || {};
|
||||||
|
|
||||||
const isFetching = useIsPlayerFetching();
|
const isFetching = useIsPlayerFetching();
|
||||||
const tableRef = useRef<ItemListHandle>(null);
|
const tableRef = useRef<ItemListHandle>(null);
|
||||||
const mergedRef = useMergedRef(ref, tableRef);
|
const mergedRef = useMergedRef(ref, tableRef);
|
||||||
const { getQueue } = usePlayerActions();
|
const { getQueue } = usePlayerActions();
|
||||||
const queueType = usePlayerQueueType();
|
const queueType = usePlayerQueueType();
|
||||||
const followCurrentSong = useFollowCurrentSong();
|
const followCurrentSong = useFollowCurrentSong();
|
||||||
|
|
||||||
const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 200);
|
const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 200);
|
||||||
|
|
||||||
const [data, setData] = useState<QueueSong[]>([]);
|
const [data, setData] = useState<QueueSong[]>([]);
|
||||||
const [groups, setGroups] = useState<TableGroupHeader[]>([]);
|
const [groups, setGroups] = useState<TableGroupHeader[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const setQueue = () => {
|
const setQueue = () => {
|
||||||
const queue = getQueue() || { groups: [], items: [] };
|
const queue = getQueue() || { groups: [], items: [] };
|
||||||
|
|
||||||
setData(queue.items);
|
setData(queue.items);
|
||||||
|
|
||||||
if (queueType === PlayerQueueType.PRIORITY && queue.groups && queue.groups.length > 0) {
|
if (
|
||||||
const transformedGroups: TableGroupHeader[] = queue.groups.map((group) => ({
|
queueType === PlayerQueueType.PRIORITY &&
|
||||||
itemCount: group.count,
|
queue.groups &&
|
||||||
render: (): ReactElement => {
|
queue.groups.length > 0
|
||||||
return (
|
) {
|
||||||
<div className={styles.groupRow}>
|
const transformedGroups: TableGroupHeader[] = queue.groups.map((group) => ({
|
||||||
<Text
|
itemCount: group.count,
|
||||||
fw={600}
|
render: (): ReactElement => {
|
||||||
overflow="visible"
|
return (
|
||||||
size="md"
|
<div className={styles.groupRow}>
|
||||||
style={{
|
<Text
|
||||||
textWrap: 'nowrap',
|
fw={600}
|
||||||
whiteSpace: 'nowrap',
|
overflow="visible"
|
||||||
}}
|
size="md"
|
||||||
>
|
style={{
|
||||||
{group.name}
|
textWrap: 'nowrap',
|
||||||
</Text>
|
whiteSpace: 'nowrap',
|
||||||
</div>
|
}}
|
||||||
);
|
>
|
||||||
},
|
{group.name}
|
||||||
rowHeight: 40,
|
</Text>
|
||||||
}));
|
</div>
|
||||||
setGroups(transformedGroups);
|
);
|
||||||
} else {
|
},
|
||||||
setGroups([]);
|
rowHeight: 40,
|
||||||
}
|
}));
|
||||||
};
|
setGroups(transformedGroups);
|
||||||
|
} else {
|
||||||
const unsub = subscribePlayerQueue(() => {
|
setGroups([]);
|
||||||
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 (index !== -1) {
|
const unsub = subscribePlayerQueue(() => {
|
||||||
// Use setTimeout to ensure the DOM has updated with the new queue items
|
setQueue();
|
||||||
setTimeout(() => {
|
});
|
||||||
tableRef.current?.scrollToIndex(index, {
|
|
||||||
align: 'center',
|
const unsubCurrentTrack = subscribeCurrentTrack((e) => {
|
||||||
behavior: 'auto',
|
if (followCurrentSong && e.index !== -1) {
|
||||||
});
|
tableRef.current?.scrollToIndex(e.index, {
|
||||||
}, 0);
|
align: 'center',
|
||||||
|
behavior: 'auto',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
eventEmitter.on('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
|
const handleAutoDJQueueAdded = () => {
|
||||||
|
if (followCurrentSong) {
|
||||||
|
const state = usePlayerStore.getState();
|
||||||
|
let index = state.player.index;
|
||||||
|
|
||||||
setQueue();
|
if (isShuffleEnabled(state)) {
|
||||||
|
index = mapShuffledToQueueIndex(index, state.queue.shuffled);
|
||||||
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);
|
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 (
|
eventEmitter.on('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
|
||||||
<div className={styles.container} ref={containerFocusRef}>
|
|
||||||
<LoadingOverlay pos="absolute" visible={isFetching} />
|
setQueue();
|
||||||
<ItemTableList
|
|
||||||
activeRowId={currentSongUniqueId}
|
return () => {
|
||||||
autoFitColumns={table.autoFitColumns}
|
unsub();
|
||||||
CellComponent={ItemTableListColumn}
|
unsubCurrentTrack();
|
||||||
columns={table.columns}
|
eventEmitter.off('AUTODJ_QUEUE_ADDED', handleAutoDJQueueAdded);
|
||||||
data={filteredData}
|
};
|
||||||
enableAlternateRowColors={table.enableAlternateRowColors}
|
}, [getQueue, queueType, tableRef, followCurrentSong]);
|
||||||
enableDrag
|
|
||||||
enableExpansion={false}
|
const filteredData: QueueSong[] = useMemo(() => {
|
||||||
enableHeader
|
if (debouncedSearchTerm) {
|
||||||
enableHorizontalBorders={table.enableHorizontalBorders}
|
const searched = searchLibraryItems(data, debouncedSearchTerm, LibraryItem.SONG);
|
||||||
enableRowHoverHighlight={table.enableRowHoverHighlight}
|
return searched;
|
||||||
enableSelection
|
}
|
||||||
enableSelectionDialog={false}
|
|
||||||
enableVerticalBorders={table.enableVerticalBorders}
|
return data;
|
||||||
getRowId="_uniqueId"
|
}, [data, debouncedSearchTerm]);
|
||||||
groups={groups.length > 0 ? groups : undefined}
|
|
||||||
initialTop={{
|
const isEmpty = filteredData.length === 0;
|
||||||
to: 0,
|
|
||||||
type: 'offset',
|
const { handleColumnReordered } = useItemListColumnReorder({
|
||||||
}}
|
itemListKey: listKey,
|
||||||
itemType={LibraryItem.QUEUE_SONG}
|
});
|
||||||
onColumnReordered={handleColumnReordered}
|
|
||||||
onColumnResized={handleColumnResized}
|
const { handleColumnResized } = useItemListColumnResize({
|
||||||
ref={mergedRef}
|
itemListKey: listKey,
|
||||||
size={table.size}
|
});
|
||||||
/>
|
|
||||||
{isEmpty && <EmptyQueueDropZone />}
|
const currentSong = usePlayerSong();
|
||||||
</div>
|
|
||||||
);
|
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 (
|
||||||
|
<div className={styles.container} ref={containerFocusRef}>
|
||||||
|
<LoadingOverlay pos="absolute" visible={isFetching} />
|
||||||
|
<ItemTableList
|
||||||
|
activeRowId={currentSongUniqueId}
|
||||||
|
autoFitColumns={table.autoFitColumns}
|
||||||
|
CellComponent={ItemTableListColumn}
|
||||||
|
columns={table.columns}
|
||||||
|
data={filteredData}
|
||||||
|
enableAlternateRowColors={table.enableAlternateRowColors}
|
||||||
|
enableDrag
|
||||||
|
enableExpansion={false}
|
||||||
|
enableHeader
|
||||||
|
enableHorizontalBorders={table.enableHorizontalBorders}
|
||||||
|
enableRowHoverHighlight={table.enableRowHoverHighlight}
|
||||||
|
enableScrollShadow={enableScrollShadow}
|
||||||
|
enableSelection
|
||||||
|
enableSelectionDialog={false}
|
||||||
|
enableVerticalBorders={table.enableVerticalBorders}
|
||||||
|
getRowId="_uniqueId"
|
||||||
|
groups={groups.length > 0 ? groups : undefined}
|
||||||
|
initialTop={{
|
||||||
|
to: 0,
|
||||||
|
type: 'offset',
|
||||||
|
}}
|
||||||
|
itemType={LibraryItem.QUEUE_SONG}
|
||||||
|
onColumnReordered={handleColumnReordered}
|
||||||
|
onColumnResized={handleColumnResized}
|
||||||
|
ref={mergedRef}
|
||||||
|
size={table.size}
|
||||||
|
/>
|
||||||
|
{isEmpty && <EmptyQueueDropZone />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const EmptyQueueDropZone = () => {
|
const EmptyQueueDropZone = () => {
|
||||||
const playerContext = usePlayer();
|
const playerContext = usePlayer();
|
||||||
|
|||||||
@@ -106,7 +106,11 @@ export const FullScreenPlayerQueue = () => {
|
|||||||
</Group>
|
</Group>
|
||||||
{activeTab === 'queue' ? (
|
{activeTab === 'queue' ? (
|
||||||
<div className={styles.queueContainer}>
|
<div className={styles.queueContainer}>
|
||||||
<PlayQueue listKey={ItemListKey.FULL_SCREEN} searchTerm={undefined} />
|
<PlayQueue
|
||||||
|
enableScrollShadow={false}
|
||||||
|
listKey={ItemListKey.FULL_SCREEN}
|
||||||
|
searchTerm={undefined}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : activeTab === 'related' ? (
|
) : activeTab === 'related' ? (
|
||||||
<div className={styles.queueContainer}>
|
<div className={styles.queueContainer}>
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export const SimilarSongsList = ({ count, song }: SimilarSongsListProps) => {
|
|||||||
enableHeader
|
enableHeader
|
||||||
enableHorizontalBorders={fullScreenTable?.enableHorizontalBorders}
|
enableHorizontalBorders={fullScreenTable?.enableHorizontalBorders}
|
||||||
enableRowHoverHighlight={fullScreenTable?.enableRowHoverHighlight}
|
enableRowHoverHighlight={fullScreenTable?.enableRowHoverHighlight}
|
||||||
|
enableScrollShadow={false}
|
||||||
enableSelection
|
enableSelection
|
||||||
enableSelectionDialog={false}
|
enableSelectionDialog={false}
|
||||||
enableVerticalBorders={fullScreenTable?.enableVerticalBorders}
|
enableVerticalBorders={fullScreenTable?.enableVerticalBorders}
|
||||||
|
|||||||
Reference in New Issue
Block a user