single track drag-and-drop ghost
This commit is contained in:
@@ -39,6 +39,7 @@ import type { DragPayload } from '@utils/drag-controller';
|
|||||||
import {
|
import {
|
||||||
createAlbumArtDragImage,
|
createAlbumArtDragImage,
|
||||||
createDragImage,
|
createDragImage,
|
||||||
|
createTrackCardDragImage,
|
||||||
removeDragImage,
|
removeDragImage,
|
||||||
} from '@utils/drag-image';
|
} from '@utils/drag-image';
|
||||||
|
|
||||||
@@ -2850,9 +2851,16 @@ export class CoverGrid extends LitElement {
|
|||||||
JSON.stringify(payload),
|
JSON.stringify(payload),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.dragImageEl = createDragImage(
|
this.dragImageEl =
|
||||||
filePaths.length,
|
filePaths.length === 1
|
||||||
);
|
? createTrackCardDragImage(
|
||||||
|
track.TrackName,
|
||||||
|
track.ArtistName,
|
||||||
|
track.FilePath,
|
||||||
|
)
|
||||||
|
: createDragImage(
|
||||||
|
filePaths.length,
|
||||||
|
);
|
||||||
dataTransfer.setDragImage(
|
dataTransfer.setDragImage(
|
||||||
this.dragImageEl,
|
this.dragImageEl,
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
} from '@utils/drag-controller';
|
} from '@utils/drag-controller';
|
||||||
import {
|
import {
|
||||||
createDragImage,
|
createDragImage,
|
||||||
|
createTrackCardDragImage,
|
||||||
removeDragImage,
|
removeDragImage,
|
||||||
} from '@utils/drag-image';
|
} from '@utils/drag-image';
|
||||||
|
|
||||||
@@ -1143,9 +1144,14 @@ export class PlaylistView
|
|||||||
sourcePlaylistId: entry.summary.ID,
|
sourcePlaylistId: entry.summary.ID,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dragImageEl = createDragImage(
|
this.dragImageEl =
|
||||||
filePaths.length,
|
filePaths.length === 1
|
||||||
);
|
? createTrackCardDragImage(
|
||||||
|
track.Title,
|
||||||
|
track.Artist,
|
||||||
|
track.FilePath,
|
||||||
|
)
|
||||||
|
: createDragImage(filePaths.length);
|
||||||
e.dataTransfer?.setDragImage(
|
e.dataTransfer?.setDragImage(
|
||||||
this.dragImageEl,
|
this.dragImageEl,
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
} from '@utils/drag-controller';
|
} from '@utils/drag-controller';
|
||||||
import {
|
import {
|
||||||
createDragImage,
|
createDragImage,
|
||||||
|
createTrackCardDragImage,
|
||||||
removeDragImage,
|
removeDragImage,
|
||||||
} from '@utils/drag-image';
|
} from '@utils/drag-image';
|
||||||
|
|
||||||
@@ -1096,9 +1097,21 @@ export class QueuePanel
|
|||||||
source: 'queue',
|
source: 'queue',
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dragImageEl = createDragImage(
|
if (filePaths.length === 1) {
|
||||||
filePaths.length,
|
const t = tracks[index]!;
|
||||||
);
|
|
||||||
|
this.dragImageEl =
|
||||||
|
createTrackCardDragImage(
|
||||||
|
t.title,
|
||||||
|
t.artist,
|
||||||
|
t.filePath,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.dragImageEl = createDragImage(
|
||||||
|
filePaths.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
e.dataTransfer?.setDragImage(
|
e.dataTransfer?.setDragImage(
|
||||||
this.dragImageEl,
|
this.dragImageEl,
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
} from '@utils/drag-controller';
|
} from '@utils/drag-controller';
|
||||||
import {
|
import {
|
||||||
createDragImage,
|
createDragImage,
|
||||||
|
createTrackCardDragImage,
|
||||||
removeDragImage,
|
removeDragImage,
|
||||||
} from '@utils/drag-image';
|
} from '@utils/drag-image';
|
||||||
import '@lit-labs/virtualizer';
|
import '@lit-labs/virtualizer';
|
||||||
@@ -1135,9 +1136,14 @@ export class TrackList extends LitElement implements SelectionHost {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Custom drag image.
|
// Custom drag image.
|
||||||
this.dragImageEl = createDragImage(
|
this.dragImageEl =
|
||||||
filePaths.length,
|
filePaths.length === 1
|
||||||
);
|
? createTrackCardDragImage(
|
||||||
|
track.TrackName,
|
||||||
|
track.ArtistName,
|
||||||
|
track.FilePath,
|
||||||
|
)
|
||||||
|
: createDragImage(filePaths.length);
|
||||||
e.dataTransfer?.setDragImage(
|
e.dataTransfer?.setDragImage(
|
||||||
this.dragImageEl,
|
this.dragImageEl,
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -66,6 +66,83 @@ export function createAlbumArtDragImage(
|
|||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a drag image styled like a queue track card showing the
|
||||||
|
* track title and artist. Used when dragging a single track.
|
||||||
|
*
|
||||||
|
* If `title` is empty and `filePath` is provided the filename
|
||||||
|
* (without extension) is used as a fallback. An empty `artist`
|
||||||
|
* falls back to "Unknown Artist".
|
||||||
|
*/
|
||||||
|
export function createTrackCardDragImage(
|
||||||
|
title: string,
|
||||||
|
artist: string,
|
||||||
|
filePath?: string,
|
||||||
|
): HTMLElement {
|
||||||
|
let displayTitle = title;
|
||||||
|
|
||||||
|
if (!displayTitle && filePath) {
|
||||||
|
const parts = filePath.split(/[\\/]/);
|
||||||
|
const filename =
|
||||||
|
parts[parts.length - 1] ?? filePath;
|
||||||
|
|
||||||
|
displayTitle = filename.replace(/\.[^.]+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!displayTitle) {
|
||||||
|
displayTitle = 'Unknown Title';
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayArtist = artist || 'Unknown Artist';
|
||||||
|
|
||||||
|
const card = document.createElement('div');
|
||||||
|
|
||||||
|
card.style.cssText = [
|
||||||
|
'position: fixed',
|
||||||
|
'top: -1000px',
|
||||||
|
'left: -1000px',
|
||||||
|
'max-width: 220px',
|
||||||
|
'padding: 8px 14px',
|
||||||
|
'border-radius: 6px',
|
||||||
|
'background: #2a2a2a',
|
||||||
|
'box-shadow: 0 2px 8px rgba(0,0,0,0.4)',
|
||||||
|
'pointer-events: none',
|
||||||
|
'z-index: 9999',
|
||||||
|
'display: flex',
|
||||||
|
'flex-direction: column',
|
||||||
|
'gap: 2px',
|
||||||
|
'font-family: inherit',
|
||||||
|
].join(';');
|
||||||
|
|
||||||
|
const titleEl = document.createElement('span');
|
||||||
|
|
||||||
|
titleEl.textContent = displayTitle;
|
||||||
|
titleEl.style.cssText = [
|
||||||
|
'font-size: 13px',
|
||||||
|
'color: #fff',
|
||||||
|
'white-space: nowrap',
|
||||||
|
'overflow: hidden',
|
||||||
|
'text-overflow: ellipsis',
|
||||||
|
].join(';');
|
||||||
|
|
||||||
|
const artistEl = document.createElement('span');
|
||||||
|
|
||||||
|
artistEl.textContent = displayArtist;
|
||||||
|
artistEl.style.cssText = [
|
||||||
|
'font-size: 11px',
|
||||||
|
'color: #b3b3b3',
|
||||||
|
'white-space: nowrap',
|
||||||
|
'overflow: hidden',
|
||||||
|
'text-overflow: ellipsis',
|
||||||
|
].join(';');
|
||||||
|
|
||||||
|
card.appendChild(titleEl);
|
||||||
|
card.appendChild(artistEl);
|
||||||
|
document.body.appendChild(card);
|
||||||
|
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove a drag image element created by createDragImage. */
|
/** Remove a drag image element created by createDragImage. */
|
||||||
export function removeDragImage(el: HTMLElement): void {
|
export function removeDragImage(el: HTMLElement): void {
|
||||||
el.remove();
|
el.remove();
|
||||||
|
|||||||
Reference in New Issue
Block a user