Skip to content

Commit 6a6c9f4

Browse files
authored
feat(web): Hide ISRC submission link if ISRCs were already added
1 parent cc4282c commit 6a6c9f4

File tree

2 files changed

+73
-23
lines changed

2 files changed

+73
-23
lines changed

server/components/ISRCSubmission.tsx

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,68 @@
1+
import { SpriteIcon } from './SpriteIcon.tsx';
2+
13
import { musicbrainzTargetServer } from '@/config.ts';
2-
import type { HarmonyRelease } from '@/harmonizer/types.ts';
4+
import type { HarmonyRelease, HarmonyTrack, ProviderInfo } from '@/harmonizer/types.ts';
35
import { join } from 'std/url/join.ts';
6+
import type { EntityWithMbid } from '@kellnerd/musicbrainz/api-types';
47

5-
export function MagicISRC({ release, targetMbid }: { release: HarmonyRelease; targetMbid?: string }) {
6-
const allTracks = release.media.flatMap((medium) => medium.tracklist);
8+
// TODO: incomplete type, expose a suitable type from @kellnerd/musicbrainz?
9+
export interface EntityWithISRCs extends EntityWithMbid {
10+
isrcs?: string[];
11+
}
12+
13+
function getISRCProvider(release: HarmonyRelease): ProviderInfo | undefined {
714
const isrcSource = release.info.sourceMap?.isrc;
8-
const isrcProvider = release.info.providers.find((provider) => provider.name === isrcSource);
9-
if (!(allTracks.some((track) => track.isrc) && isrcProvider)) {
10-
return null;
11-
}
15+
if (!isrcSource) return undefined;
16+
return release.info.providers.find((provider) => provider.name === isrcSource);
17+
}
18+
19+
export function ISRCSubmission(
20+
{ release, targetMbid, recordingsCache }: {
21+
release: HarmonyRelease;
22+
targetMbid?: string;
23+
recordingsCache?: EntityWithISRCs[];
24+
},
25+
) {
26+
const isrcProvider = getISRCProvider(release);
27+
28+
if (!isrcProvider) return null;
29+
const allTracks = release.media.flatMap((medium) => medium.tracklist);
30+
31+
const needsSubmission = (track: HarmonyTrack): boolean => {
32+
// If there's no ISRC, nothing to submit
33+
if (!track.isrc) return false;
34+
35+
const recordingMbid = track.recording?.mbid;
36+
// If there's no recording MBID, consider the ISRC as new (needs submission)
37+
if (!recordingMbid) return true;
38+
39+
const mbEntity = recordingsCache?.find((e) => e.id === recordingMbid);
40+
// If MB entity is missing or doesn't include the ISRC, it's new
41+
return !mbEntity?.isrcs?.includes(track.isrc);
42+
};
43+
44+
const noPendingISRCSubmissions = !allTracks.some(needsSubmission);
45+
46+
if (noPendingISRCSubmissions) return null;
47+
48+
return (
49+
<div class='action'>
50+
<SpriteIcon name='disc' />
51+
<p>
52+
<MagicISRC allTracks={allTracks} targetMbid={targetMbid} isrcProvider={isrcProvider} />
53+
: Submit ISRCs from <a href={isrcProvider.url}>{isrcProvider.name}</a> to MusicBrainz
54+
</p>
55+
</div>
56+
);
57+
}
1258

59+
function MagicISRC(
60+
{ allTracks, targetMbid, isrcProvider }: {
61+
allTracks: HarmonyTrack[];
62+
targetMbid?: string;
63+
isrcProvider: ProviderInfo;
64+
},
65+
) {
1366
const query = new URLSearchParams(
1467
allTracks.map((track, index) => [`isrc${index + 1}`, track.isrc ?? '']),
1568
);

server/routes/release/actions.tsx

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ArtistCredit } from '@/server/components/ArtistCredit.tsx';
22
import { CoverImage } from '@/server/components/CoverImage.tsx';
3-
import { MagicISRC } from '@/server/components/ISRCSubmission.tsx';
3+
import { ISRCSubmission } from '@/server/components/ISRCSubmission.tsx';
44
import { LinkWithMusicBrainz } from '@/server/components/LinkWithMusicBrainz.tsx';
55
import { MBIDInput } from '@/server/components/MBIDInput.tsx';
66
import { MessageBox } from '@/server/components/MessageBox.tsx';
@@ -13,7 +13,6 @@ import type {
1313
ArtistCreditName,
1414
Artwork,
1515
HarmonyRelease,
16-
ProviderInfo,
1716
ReleaseOptions,
1817
ResolvableEntity,
1918
} from '@/harmonizer/types.ts';
@@ -37,7 +36,6 @@ export default defineRoute(async (req, ctx) => {
3736
let release: HarmonyRelease | undefined = undefined;
3837
let releaseMbid: string | undefined;
3938
let releaseUrl: URL | undefined;
40-
let isrcProvider: ProviderInfo | undefined;
4139
let allArtists: ArtistCreditName[] = [];
4240
let mbArtists: EntityWithUrlRels[] = [];
4341
let mbLabels: EntityWithUrlRels[] = [];
@@ -94,10 +92,6 @@ export default defineRoute(async (req, ctx) => {
9492
release.images?.map((image) => ({ ...image, provider })) ?? []
9593
);
9694

97-
const { info } = release;
98-
const isrcSource = info.sourceMap?.isrc;
99-
isrcProvider = info.providers.find((provider) => provider.name === isrcSource);
100-
10195
const allTracks = release.media.flatMap((medium) => medium.tracklist);
10296

10397
// Fallback to track title, Harmony recordings are usually unnamed.
@@ -113,9 +107,14 @@ export default defineRoute(async (req, ctx) => {
113107

114108
// Load URL relationships for related artists, recordings and labels of the release.
115109
// These will be used to skip suggestions to seed external links which already exist.
110+
// For recordings it also includes ISRCs to determine if there are new ones to submit.
116111
const mbArtistBrowseResult = await MB.get('artist', { release: releaseMbid, inc: 'url-rels', limit: 100 });
117112
mbArtists = mbArtistBrowseResult.artists;
118-
const mbRecordingBrowseResult = await MB.get('recording', { release: releaseMbid, inc: 'url-rels', limit: 100 });
113+
const mbRecordingBrowseResult = await MB.get('recording', {
114+
release: releaseMbid,
115+
inc: 'url-rels+isrcs',
116+
limit: 100,
117+
});
119118
mbRecordings = mbRecordingBrowseResult.recordings;
120119
// Labels often have no external links which could be linked, save pointless API call.
121120
if (release.labels?.some((label) => label.externalIds?.length)) {
@@ -185,14 +184,12 @@ export default defineRoute(async (req, ctx) => {
185184
</p>
186185
</div>
187186
)}
188-
{release && isrcProvider && (
189-
<div class='action'>
190-
<SpriteIcon name='disc' />
191-
<p>
192-
<MagicISRC release={release} targetMbid={releaseMbid!} />
193-
: Submit ISRCs from <a href={isrcProvider.url}>{isrcProvider.name}</a> to MusicBrainz
194-
</p>
195-
</div>
187+
{release && (
188+
<ISRCSubmission
189+
release={release}
190+
targetMbid={releaseMbid}
191+
recordingsCache={mbRecordings}
192+
/>
196193
)}
197194
{releaseUrl && (
198195
<LinkWithMusicBrainz

0 commit comments

Comments
 (0)