feat(18-02): wire batch track-details to all 4 view context menus
- track-list: branch on selection count, resolve tracks from this.tracks - cover-grid: branch on selection count, resolve from expandedTracks - queue-panel: branch on indices count, resolve via libraryStore.getCachedTracks - playlist-details: branch on selection count, resolve via libraryStore - Each view determines coverArt/coverArtMixed state and calls showBatch()
This commit is contained in:
@@ -26,6 +26,7 @@ import '@awesome.me/webawesome/dist/components/icon/icon.js';
|
|||||||
import '@components/playlist-picker/playlist-picker.js';
|
import '@components/playlist-picker/playlist-picker.js';
|
||||||
import '@components/track-details/track-details.js';
|
import '@components/track-details/track-details.js';
|
||||||
import type { TrackDetails } from '@components/track-details/track-details.js';
|
import type { TrackDetails } from '@components/track-details/track-details.js';
|
||||||
|
import type { CoverArtUrls } from '@components/track-details/track-details.js';
|
||||||
import { AlbumSelectionManager } from './album-selection.js';
|
import { AlbumSelectionManager } from './album-selection.js';
|
||||||
import { ScrollManager } from './scroll-manager.js';
|
import { ScrollManager } from './scroll-manager.js';
|
||||||
import type { ScrollManagerHost } from './scroll-manager.js';
|
import type { ScrollManagerHost } from './scroll-manager.js';
|
||||||
@@ -1524,7 +1525,11 @@ export class CoverGrid
|
|||||||
queueStore.playTracksNext(filePaths);
|
queueStore.playTracksNext(filePaths);
|
||||||
break;
|
break;
|
||||||
case 'track-details':
|
case 'track-details':
|
||||||
this.openTrackDetails(filePaths[0]!);
|
if (filePaths.length === 1) {
|
||||||
|
this.openTrackDetails(filePaths[0]!);
|
||||||
|
} else {
|
||||||
|
this.openBatchTrackDetails(filePaths);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1580,6 +1585,45 @@ export class CoverGrid
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private openBatchTrackDetails(
|
||||||
|
filePaths: string[],
|
||||||
|
) {
|
||||||
|
const tracks = filePaths
|
||||||
|
.map((fp) =>
|
||||||
|
this.expandedTracks.find(
|
||||||
|
(t) => t.FilePath === fp,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
(t): t is library.Track => t != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tracks.length === 0) return;
|
||||||
|
|
||||||
|
const albumNames = new Set(
|
||||||
|
tracks.map((t) => t.Album),
|
||||||
|
);
|
||||||
|
let coverArt: CoverArtUrls | null = null;
|
||||||
|
let coverArtMixed = false;
|
||||||
|
|
||||||
|
if (albumNames.size === 1) {
|
||||||
|
const albumName = [...albumNames][0]!;
|
||||||
|
coverArt =
|
||||||
|
this.selMgr.resolveTrackCoverArt(
|
||||||
|
albumName,
|
||||||
|
this.expandedAlbumId,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
coverArtMixed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trackDetailsDialog?.showBatch(
|
||||||
|
tracks,
|
||||||
|
coverArt,
|
||||||
|
coverArtMixed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** Resolve file paths for the playlist submenu. */
|
/** Resolve file paths for the playlist submenu. */
|
||||||
private async getPlaylistSubmenuFilePaths(): Promise<
|
private async getPlaylistSubmenuFilePaths(): Promise<
|
||||||
string[]
|
string[]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
RemovePhantomTracks,
|
RemovePhantomTracks,
|
||||||
FindDuplicateTracksInPlaylist,
|
FindDuplicateTracksInPlaylist,
|
||||||
} from '@go/playlist/Service';
|
} from '@go/playlist/Service';
|
||||||
import type { playlist } from '@go/models';
|
import type { playlist, library } from '@go/models';
|
||||||
import { EventsOn } from '@runtime/runtime';
|
import { EventsOn } from '@runtime/runtime';
|
||||||
import { Events } from '../../events';
|
import { Events } from '../../events';
|
||||||
import { queueStore } from '@store/queue-store';
|
import { queueStore } from '@store/queue-store';
|
||||||
@@ -350,7 +350,11 @@ export class PlaylistDetails
|
|||||||
void this.removeSelectedTracks();
|
void this.removeSelectedTracks();
|
||||||
break;
|
break;
|
||||||
case 'track-details':
|
case 'track-details':
|
||||||
this.openTrackDetails(filePaths[0]!);
|
if (filePaths.length === 1) {
|
||||||
|
this.openTrackDetails(filePaths[0]!);
|
||||||
|
} else {
|
||||||
|
this.openBatchTrackDetails(filePaths);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'phantom-locate':
|
case 'phantom-locate':
|
||||||
this.openPhantomResolver();
|
this.openPhantomResolver();
|
||||||
@@ -446,6 +450,50 @@ export class PlaylistDetails
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private openBatchTrackDetails(
|
||||||
|
filePaths: string[],
|
||||||
|
) {
|
||||||
|
const cachedTracks =
|
||||||
|
libraryStore.getCachedTracks();
|
||||||
|
|
||||||
|
if (!cachedTracks) return;
|
||||||
|
|
||||||
|
const tracks = filePaths
|
||||||
|
.map((fp) =>
|
||||||
|
cachedTracks.find(
|
||||||
|
(t) => t.FilePath === fp,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
(t): t is library.Track =>
|
||||||
|
t != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tracks.length === 0) return;
|
||||||
|
|
||||||
|
const albumNames = new Set(
|
||||||
|
tracks.map((t) => t.Album),
|
||||||
|
);
|
||||||
|
let coverArt: CoverArtUrls | null = null;
|
||||||
|
let coverArtMixed = false;
|
||||||
|
|
||||||
|
if (albumNames.size === 1) {
|
||||||
|
const albumName = [...albumNames][0]!;
|
||||||
|
coverArt =
|
||||||
|
this.resolvePlaylistCoverArt(
|
||||||
|
albumName,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
coverArtMixed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trackDetailsDialog?.showBatch(
|
||||||
|
tracks,
|
||||||
|
coverArt,
|
||||||
|
coverArtMixed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private resolvePlaylistCoverArt(
|
private resolvePlaylistCoverArt(
|
||||||
albumName: string,
|
albumName: string,
|
||||||
): CoverArtUrls | null {
|
): CoverArtUrls | null {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import {
|
|||||||
removeDragImage,
|
removeDragImage,
|
||||||
} from '@utils/drag-image';
|
} from '@utils/drag-image';
|
||||||
import { libraryStore } from '@store/library-store';
|
import { libraryStore } from '@store/library-store';
|
||||||
|
import type { library } from '@go/models';
|
||||||
import '@components/track-details/track-details.js';
|
import '@components/track-details/track-details.js';
|
||||||
import type { TrackDetails } from '@components/track-details/track-details.js';
|
import type { TrackDetails } from '@components/track-details/track-details.js';
|
||||||
import type { CoverArtUrls } from '@components/track-details/track-details.js';
|
import type { CoverArtUrls } from '@components/track-details/track-details.js';
|
||||||
@@ -817,7 +818,11 @@ export class QueuePanel
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'track-details':
|
case 'track-details':
|
||||||
this.openTrackDetails(indices[0]!);
|
if (indices.length === 1) {
|
||||||
|
this.openTrackDetails(indices[0]!);
|
||||||
|
} else {
|
||||||
|
this.openBatchTrackDetails(indices);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,6 +874,52 @@ export class QueuePanel
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private openBatchTrackDetails(
|
||||||
|
indices: number[],
|
||||||
|
) {
|
||||||
|
const queueTracks = this.queue.tracks;
|
||||||
|
const cachedTracks =
|
||||||
|
libraryStore.getCachedTracks();
|
||||||
|
|
||||||
|
if (!cachedTracks) return;
|
||||||
|
|
||||||
|
const tracks = indices
|
||||||
|
.map((i) => queueTracks[i])
|
||||||
|
.filter((qt) => qt != null)
|
||||||
|
.map((qt) =>
|
||||||
|
cachedTracks.find(
|
||||||
|
(t) =>
|
||||||
|
t.FilePath === qt.filePath,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
(t): t is library.Track =>
|
||||||
|
t != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tracks.length === 0) return;
|
||||||
|
|
||||||
|
const albumNames = new Set(
|
||||||
|
tracks.map((t) => t.Album),
|
||||||
|
);
|
||||||
|
let coverArt: CoverArtUrls | null = null;
|
||||||
|
let coverArtMixed = false;
|
||||||
|
|
||||||
|
if (albumNames.size === 1) {
|
||||||
|
const albumName = [...albumNames][0]!;
|
||||||
|
coverArt =
|
||||||
|
this.resolveQueueCoverArt(albumName);
|
||||||
|
} else {
|
||||||
|
coverArtMixed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trackDetailsDialog?.showBatch(
|
||||||
|
tracks,
|
||||||
|
coverArt,
|
||||||
|
coverArtMixed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private resolveQueueCoverArt(
|
private resolveQueueCoverArt(
|
||||||
albumName: string,
|
albumName: string,
|
||||||
): CoverArtUrls | null {
|
): CoverArtUrls | null {
|
||||||
|
|||||||
@@ -1442,7 +1442,11 @@ export class TrackList extends LitElement implements SelectionHost, ContextMenuH
|
|||||||
queueStore.playTracksNext(filePaths);
|
queueStore.playTracksNext(filePaths);
|
||||||
break;
|
break;
|
||||||
case 'track-details':
|
case 'track-details':
|
||||||
this.openTrackDetails(filePaths[0]!);
|
if (filePaths.length === 1) {
|
||||||
|
this.openTrackDetails(filePaths[0]!);
|
||||||
|
} else {
|
||||||
|
this.openBatchTrackDetails(filePaths);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1486,6 +1490,42 @@ export class TrackList extends LitElement implements SelectionHost, ContextMenuH
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private openBatchTrackDetails(
|
||||||
|
filePaths: string[],
|
||||||
|
) {
|
||||||
|
const tracks = filePaths
|
||||||
|
.map((fp) =>
|
||||||
|
this.tracks.find(
|
||||||
|
(t) => t.FilePath === fp,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
(t): t is library.Track => t != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tracks.length === 0) return;
|
||||||
|
|
||||||
|
const albumNames = new Set(
|
||||||
|
tracks.map((t) => t.Album),
|
||||||
|
);
|
||||||
|
let coverArt: CoverArtUrls | null = null;
|
||||||
|
let coverArtMixed = false;
|
||||||
|
|
||||||
|
if (albumNames.size === 1) {
|
||||||
|
const albumName = [...albumNames][0]!;
|
||||||
|
coverArt =
|
||||||
|
this.resolveCoverArt(albumName);
|
||||||
|
} else {
|
||||||
|
coverArtMixed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trackDetailsDialog?.showBatch(
|
||||||
|
tracks,
|
||||||
|
coverArt,
|
||||||
|
coverArtMixed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private resolveCoverArt(
|
private resolveCoverArt(
|
||||||
albumName: string,
|
albumName: string,
|
||||||
): CoverArtUrls | null {
|
): CoverArtUrls | null {
|
||||||
|
|||||||
Reference in New Issue
Block a user