fix: CD metadata dialog search/images/Weiter button
- Remove auto MusicBrainz search from analyzeCd; user triggers search manually - Dialog uses single results state (replaced per search, not appended) - Add cover-art-archive to MB search includes so cover images load - Weiter button only blocked by track selection when tracks actually exist Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -92,7 +92,7 @@ class MusicBrainzService {
|
|||||||
url.searchParams.set('query', q);
|
url.searchParams.set('query', q);
|
||||||
url.searchParams.set('fmt', 'json');
|
url.searchParams.set('fmt', 'json');
|
||||||
url.searchParams.set('limit', '10');
|
url.searchParams.set('limit', '10');
|
||||||
url.searchParams.set('inc', 'artist-credits+labels+recordings');
|
url.searchParams.set('inc', 'artist-credits+labels+recordings+cover-art-archive');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await mbFetch(url.toString());
|
const data = await mbFetch(url.toString());
|
||||||
|
|||||||
@@ -9794,11 +9794,6 @@ class PipelineService extends EventEmitter {
|
|||||||
const tracks = await cdRipService.readToc(devicePath, cdparanoiaCmd);
|
const tracks = await cdRipService.readToc(devicePath, cdparanoiaCmd);
|
||||||
logger.info('cd:analyze:toc', { jobId: job.id, trackCount: tracks.length });
|
logger.info('cd:analyze:toc', { jobId: job.id, trackCount: tracks.length });
|
||||||
|
|
||||||
// Search MusicBrainz
|
|
||||||
const mbCandidates = await musicBrainzService
|
|
||||||
.searchByDiscLabel(detectedTitle)
|
|
||||||
.catch(() => []);
|
|
||||||
|
|
||||||
const cdInfo = {
|
const cdInfo = {
|
||||||
phase: 'PREPARE',
|
phase: 'PREPARE',
|
||||||
mediaProfile: 'cd',
|
mediaProfile: 'cd',
|
||||||
@@ -9816,7 +9811,7 @@ class PipelineService extends EventEmitter {
|
|||||||
await historyService.appendLog(
|
await historyService.appendLog(
|
||||||
job.id,
|
job.id,
|
||||||
'SYSTEM',
|
'SYSTEM',
|
||||||
`CD analysiert: ${tracks.length} Track(s) gefunden. MusicBrainz: ${mbCandidates.length} Treffer.`
|
`CD analysiert: ${tracks.length} Track(s) gefunden.`
|
||||||
);
|
);
|
||||||
|
|
||||||
const runningJobs = await historyService.getRunningJobs();
|
const runningJobs = await historyService.getRunningJobs();
|
||||||
@@ -9832,13 +9827,12 @@ class PipelineService extends EventEmitter {
|
|||||||
device,
|
device,
|
||||||
mediaProfile: 'cd',
|
mediaProfile: 'cd',
|
||||||
detectedTitle,
|
detectedTitle,
|
||||||
tracks,
|
tracks
|
||||||
mbCandidates
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { jobId: job.id, detectedTitle, tracks, mbCandidates };
|
return { jobId: job.id, detectedTitle, tracks };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('cd:analyze:failed', { jobId: job.id, error: errorToMeta(error) });
|
logger.error('cd:analyze:failed', { jobId: job.id, error: errorToMeta(error) });
|
||||||
await this.failJob(job.id, 'CD_ANALYZING', error);
|
await this.failJob(job.id, 'CD_ANALYZING', error);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export default function CdMetadataDialog({
|
|||||||
}) {
|
}) {
|
||||||
const [selected, setSelected] = useState(null);
|
const [selected, setSelected] = useState(null);
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [extraResults, setExtraResults] = useState([]);
|
const [results, setResults] = useState([]);
|
||||||
|
|
||||||
// Manual metadata inputs
|
// Manual metadata inputs
|
||||||
const [manualTitle, setManualTitle] = useState('');
|
const [manualTitle, setManualTitle] = useState('');
|
||||||
@@ -46,7 +46,7 @@ export default function CdMetadataDialog({
|
|||||||
setManualTitle(context?.detectedTitle || '');
|
setManualTitle(context?.detectedTitle || '');
|
||||||
setManualArtist('');
|
setManualArtist('');
|
||||||
setManualYear(null);
|
setManualYear(null);
|
||||||
setExtraResults([]);
|
setResults([]);
|
||||||
|
|
||||||
const titles = {};
|
const titles = {};
|
||||||
const positions = new Set();
|
const positions = new Set();
|
||||||
@@ -84,27 +84,13 @@ export default function CdMetadataDialog({
|
|||||||
}
|
}
|
||||||
}, [selected]);
|
}, [selected]);
|
||||||
|
|
||||||
const allMbRows = [
|
|
||||||
...(Array.isArray(context?.mbCandidates) ? context.mbCandidates : []),
|
|
||||||
...extraResults
|
|
||||||
].filter(Boolean);
|
|
||||||
|
|
||||||
// Deduplicate by mbId
|
|
||||||
const mbRows = [];
|
|
||||||
const seen = new Set();
|
|
||||||
for (const r of allMbRows) {
|
|
||||||
if (r.mbId && !seen.has(r.mbId)) {
|
|
||||||
seen.add(r.mbId);
|
|
||||||
mbRows.push(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
if (!query.trim()) {
|
if (!query.trim()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const results = await onSearch(query.trim());
|
const searchResults = await onSearch(query.trim());
|
||||||
setExtraResults(results || []);
|
setResults(searchResults || []);
|
||||||
|
setSelected(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleTrack = (position) => {
|
const handleToggleTrack = (position) => {
|
||||||
@@ -163,7 +149,7 @@ export default function CdMetadataDialog({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const allSelected = tocTracks.length > 0 && selectedTrackPositions.size === tocTracks.length;
|
const allSelected = tocTracks.length > 0 && selectedTrackPositions.size === tocTracks.length;
|
||||||
const noneSelected = selectedTrackPositions.size === 0;
|
const tracksBlocking = tocTracks.length > 0 && selectedTrackPositions.size === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
@@ -186,10 +172,10 @@ export default function CdMetadataDialog({
|
|||||||
<Button label="MusicBrainz Suche" icon="pi pi-search" onClick={handleSearch} loading={busy} />
|
<Button label="MusicBrainz Suche" icon="pi pi-search" onClick={handleSearch} loading={busy} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{mbRows.length > 0 ? (
|
{results.length > 0 ? (
|
||||||
<div className="table-scroll-wrap table-scroll-medium">
|
<div className="table-scroll-wrap table-scroll-medium">
|
||||||
<DataTable
|
<DataTable
|
||||||
value={mbRows}
|
value={results}
|
||||||
selectionMode="single"
|
selectionMode="single"
|
||||||
selection={selected}
|
selection={selected}
|
||||||
onSelectionChange={(e) => setSelected(e.value)}
|
onSelectionChange={(e) => setSelected(e.value)}
|
||||||
@@ -274,7 +260,7 @@ export default function CdMetadataDialog({
|
|||||||
icon="pi pi-arrow-right"
|
icon="pi pi-arrow-right"
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
loading={busy}
|
loading={busy}
|
||||||
disabled={noneSelected || (!manualTitle.trim() && !context?.detectedTitle)}
|
disabled={tracksBlocking || (!manualTitle.trim() && !context?.detectedTitle)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
Reference in New Issue
Block a user