From 1d8e1957bae2fa2d71414e51620227c9861f6d02 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Thu, 12 Feb 2026 01:37:59 -0800 Subject: [PATCH] handle image drag from item detail list --- .../item-detail-list.module.css | 11 ++ .../item-detail-list/item-detail-list.tsx | 129 +++++++++++++----- 2 files changed, 109 insertions(+), 31 deletions(-) diff --git a/src/renderer/components/item-list/item-detail-list/item-detail-list.module.css b/src/renderer/components/item-list/item-detail-list/item-detail-list.module.css index 374f9869c..27e262d28 100644 --- a/src/renderer/components/item-list/item-detail-list/item-detail-list.module.css +++ b/src/renderer/components/item-list/item-detail-list/item-detail-list.module.css @@ -196,6 +196,17 @@ min-width: 0; } +.image-wrapper-outer { + position: relative; + display: block; + width: 100%; + aspect-ratio: 1; +} + +.image-wrapper-outer.image-wrapper-dragging { + opacity: 0.5; +} + .image-wrapper { position: relative; display: block; diff --git a/src/renderer/components/item-list/item-detail-list/item-detail-list.tsx b/src/renderer/components/item-list/item-detail-list/item-detail-list.tsx index 04730f875..da01ba207 100644 --- a/src/renderer/components/item-list/item-detail-list/item-detail-list.tsx +++ b/src/renderer/components/item-list/item-detail-list/item-detail-list.tsx @@ -32,10 +32,12 @@ import styles from './item-detail-list.module.css'; import { ItemCardControls } from '/@/renderer/components/item-card/item-card-controls'; import { ItemImage } from '/@/renderer/components/item-image/item-image'; +import { getDraggedItems } from '/@/renderer/components/item-list/helpers/get-dragged-items'; import { useDefaultItemListControls } from '/@/renderer/components/item-list/helpers/item-list-controls'; import { ItemListStateActions, ItemListStateItemWithRequiredProperties, + useItemDraggingState, useItemListState, useItemSelectionState, } from '/@/renderer/components/item-list/helpers/item-list-state'; @@ -62,6 +64,7 @@ import { usePlayer } from '/@/renderer/features/player/context/player-context'; import { useIsMutatingCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation'; import { useIsMutatingDeleteFavorite } from '/@/renderer/features/shared/mutations/delete-favorite-mutation'; import { songsQueries } from '/@/renderer/features/songs/api/songs-api'; +import { useDragDrop } from '/@/renderer/hooks/use-drag-drop'; import { AppRoute } from '/@/renderer/router/routes'; import { useSettingsStore, useShowRatings } from '/@/renderer/store'; import { formatDateAbsoluteUTC, formatDurationString } from '/@/renderer/utils'; @@ -422,6 +425,61 @@ const MetadataSection = memo( const [isImageHovered, setIsImageHovered] = useState(false); const [isMetadataHovered, setIsMetadataHovered] = useState(false); + const getId = useCallback(() => { + const draggedItems = getDraggedItems(item, internalState, false); + return draggedItems.map((i) => i.id); + }, [item, internalState]); + + const getItem = useCallback(() => { + return getDraggedItems(item, internalState, false); + }, [item, internalState]); + + const onDragStart = useCallback(() => { + const draggedItems = getDraggedItems(item, internalState, false); + internalState?.setDragging(draggedItems); + }, [item, internalState]); + + const onDrop = useCallback(() => { + internalState?.setDragging([]); + }, [internalState]); + + const drag = useMemo(() => { + const playlistSongs = (item as { _playlistSongs?: Song[] })._playlistSongs; + if (playlistSongs && playlistSongs.length > 0) { + return { + getId, + getItem: () => playlistSongs, + itemType: LibraryItem.SONG, + onDragStart, + onDrop, + operation: [DragOperation.ADD], + target: DragTarget.SONG, + }; + } + + return { + getId, + getItem, + itemType: item._itemType, + onDragStart, + onDrop, + operation: [DragOperation.ADD], + target: DragTarget.ALBUM, + }; + }, [getId, getItem, item, onDragStart, onDrop]); + + const { isDragging: isDraggingLocal, ref: dragRef } = useDragDrop({ + drag, + isEnabled: !!item, + }); + const isDraggingState = useItemDraggingState(internalState, item.id); + const isDragging = isDraggingState || isDraggingLocal; + + const handleLinkDragStart = useCallback((e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + }, []); + const isFavorite = item.userFavorite ?? false; const userRating = item.userRating ?? null; const hasRating = showRatings && userRating !== null && userRating > 0; @@ -483,39 +541,48 @@ const MetadataSection = memo( onMouseEnter={() => setIsMetadataHovered(true)} onMouseLeave={() => setIsMetadataHovered(false)} > - setIsImageHovered(true)} - onMouseLeave={() => setIsImageHovered(false)} - state={{ item }} - to={generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, { - albumId: item.id, +
- - {isFavorite &&
} - {hasRating &&
{userRating}
} - - {controls && isImageHovered && ( - - )} - - + setIsImageHovered(true)} + onMouseLeave={() => setIsImageHovered(false)} + state={{ item }} + to={generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, { + albumId: item.id, + })} + > + + {isFavorite &&
} + {hasRating &&
{userRating}
} + + {controls && isImageHovered && ( + + )} + + +