Skip to content

Commit 4f61eca

Browse files
committed
fix(guesscase-improver): align guess feat partial matching against original seeded artists
1 parent a9ed148 commit 4f61eca

1 file changed

Lines changed: 40 additions & 16 deletions

File tree

src/MusicBrainz Guess Case Improver.user.js

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
// We use a WeakMap to store the "pristine" (original) value of an input,
4141
// side-stepping any event race conditions with native preview handlers.
4242
const pristineValues = new WeakMap();
43+
const pristineArtistNames = new WeakMap();
4344

4445
// ====================================================================================
4546
// --- ✨ USER CONFIGURATION ✨ ---
@@ -187,17 +188,18 @@
187188
})).filter(item => item.name !== '');
188189
}
189190

190-
function mergeArtistCredits(currentNames, parsedTitleArtists) {
191-
// Flatten all current editor names into individual lowercase names for matching
192-
const currentIndividualNamesLower = [];
193-
currentNames.forEach(n => {
194-
const parsed = parseArtistNamesFromString(n.name);
195-
currentIndividualNamesLower.push(...parsed);
191+
function mergeArtistCredits(currentNames, parsedTitleArtists, seededArtists) {
192+
// Flatten all seeded names into individual lowercase names for matching
193+
const seededIndividualNamesLower = [];
194+
const artistsToCheck = seededArtists || [];
195+
artistsToCheck.forEach(name => {
196+
const parsed = parseArtistNamesFromString(name);
197+
seededIndividualNamesLower.push(...parsed);
196198
});
197199

198-
// Check if any parsed title artist is in the editor's individual names
199-
const hasPartialMatch = parsedTitleArtists.some(ta =>
200-
currentIndividualNamesLower.includes(ta.name.trim().toLowerCase())
200+
// Check if any parsed title artist is in the editor's individual seeded names
201+
const hasPartialMatch = parsedTitleArtists.some(ta =>
202+
seededIndividualNamesLower.includes(ta.name.trim().toLowerCase())
201203
);
202204

203205
if (hasPartialMatch) {
@@ -335,7 +337,7 @@
335337

336338
function removeArtistFromTitle(input, button) {
337339
if (!input || !button) return;
338-
let newText = input.value;
340+
let newText = pristineValues.get(input) || input.value;
339341

340342
// Handle native MB mis-guess in ETI (flattening)
341343
// This ensures the separator split can correctly identify the artist part
@@ -431,7 +433,8 @@
431433
// Knockout Model Mode: merge and strip completely
432434
const currentAC = acObservable();
433435
if (currentAC?.names) {
434-
const updatedNames = mergeArtistCredits(currentAC.names, parsedTitleArtists);
436+
const seededArtists = pristineArtistNames.get(input) || getCurrentArtistNames(button);
437+
const updatedNames = mergeArtistCredits(currentAC.names, parsedTitleArtists, seededArtists);
435438
if (updatedNames !== currentAC.names) {
436439
log('Updating AC observable with merged artists:', updatedNames);
437440
acObservable({
@@ -451,6 +454,7 @@
451454
}
452455
log(`Removed artist part from title: "${input.value}" -> "${finalTitle}"`);
453456
setInputValue(input, finalTitle.trim());
457+
pristineValues.set(input, input.value);
454458
} else {
455459
// Fallback DOM Mode: only strip if all parsed artists are already in editor
456460
const allArtistsInTitle = parsedTitleArtists.map(n => n.name.toLowerCase());
@@ -463,9 +467,11 @@
463467
}
464468
log(`Removed artist part from title (fallback): "${input.value}" -> "${finalTitle}"`);
465469
setInputValue(input, finalTitle.trim());
470+
pristineValues.set(input, input.value);
466471
} else {
467472
// Keep current value intact
468473
setInputValue(input, reassembleOriginal());
474+
pristineValues.set(input, input.value);
469475
}
470476
}
471477
}
@@ -694,9 +700,13 @@
694700

695701
button.addEventListener('click', () => {
696702
log(`'Guess Feat.' click detected for track. Allowing native script to run first.`);
703+
const input = trackRow.querySelector('input.track-name');
704+
if (input) {
705+
pristineValues.set(input, input.value);
706+
pristineArtistNames.set(input, getCurrentArtistNames(button));
707+
}
697708
setTimeout(() => {
698709
deduplicateTrackAC(trackRow);
699-
const input = trackRow.querySelector('input.track-name');
700710
if (input) removeArtistFromTitle(input, button);
701711
}, 100);
702712
}, true);
@@ -710,10 +720,17 @@
710720

711721
button.addEventListener('click', () => {
712722
log('Medium-wide "Guess Feat." clicked. Allowing native script to run first.');
713-
setTimeout(() => {
714-
const medium = button.closest('fieldset.advanced-medium');
715-
if (!medium) return;
723+
const medium = button.closest('fieldset.advanced-medium');
724+
if (!medium) return;
725+
726+
// Capture all pristine values before native script modifies them
727+
const inputs = Array.from(medium.querySelectorAll('tr.track input.track-name'));
728+
inputs.forEach(input => {
729+
pristineValues.set(input, input.value);
730+
pristineArtistNames.set(input, getCurrentArtistNames(button));
731+
});
716732

733+
setTimeout(() => {
717734
log('Applying de-duplication and title cleanup to all tracks in this medium.');
718735
medium.querySelectorAll('tr.track').forEach(trackRow => {
719736
deduplicateTrackAC(trackRow);
@@ -733,6 +750,10 @@
733750

734751
button.addEventListener('click', (event) => {
735752
const input = findAssociatedInput(button);
753+
if (input) {
754+
pristineValues.set(input, input.value);
755+
pristineArtistNames.set(input, getCurrentArtistNames(button));
756+
}
736757

737758
// --- Standalone Form Advanced Correction Interception ---
738759
if (input && /[\/.]recording\/create/.test(window.location.pathname)) {
@@ -870,6 +891,7 @@
870891

871892
setTimeout(() => {
872893
pristineValues.set(input, input.value);
894+
pristineArtistNames.set(input, getCurrentArtistNames(button));
873895
}, 50);
874896
return;
875897
}
@@ -901,6 +923,7 @@
901923
removeArtistFromTitle(input, button);
902924
// Update pristine value state for the guesscase button
903925
pristineValues.set(input, input.value);
926+
pristineArtistNames.set(input, getCurrentArtistNames(button));
904927
log(`Updated pristine value for ${input.name || input.id} after Guess Feat cleanup: "${input.value}"`);
905928
}
906929
}, 100);
@@ -927,7 +950,8 @@
927950
log(`Set initial pristine value for ${input.name || input.id}: "${input.value}"`);
928951
}
929952

930-
const updatePristineValue = () => {
953+
const updatePristineValue = (event) => {
954+
if (event && !event.isTrusted) return;
931955
pristineValues.set(input, input.value);
932956
log(`Updated pristine value for ${input.name || input.id}: "${input.value}"`);
933957
};

0 commit comments

Comments
 (0)