mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 11:56:01 +02:00
Say which blue a colour mismatch is about (issue #2941)
A print was refused a colour match between two filaments the dialog itself labelled "Blue". The comparison was right: the slicer profile asked for a near-pure #0028FF and the slot held Bambu's navy #0A2989, 118 apart in the blue channel alone and a CIEDE2000 distance of 15, where 1 is a just-noticeable difference. Nothing on screen said so. A hex that misses the colour catalogue is named by a coarse family bucket, so both sides resolved to the same word, and the warning sat between two identical labels with nothing to reconcile it against. Read as a broken matcher, which is what the report said, and a fair reading of what was shown. Where both sides of a mismatch carry the same name they are now qualified by their hex, and the tooltip names them together: "Same type, different color: needs Blue (#0028FF), slot has Blue (#0A2989)". Names that already differ are left alone -- the hex is noise once the words separate them -- and a side with no name falls back to its hex rather than growing an empty bracket. The comparison is untouched. It was correct, and its tolerance is not something to widen on one report: a difference that size would start matching navy to cyan, and eligibility is the same rule the queue scheduler dispatches on, so loosening it would change which spool gets printed rather than only which warning gets shown. This issue was about being able to see why the warning fired, and a test pins that it still fires. The strings around it were hardcoded English: the panel's status line, the required-filament tooltip, the auto-matched marker, the slot placeholder, the mismatch detail and the type-not-found message. All nine now go through translation, in all thirteen locales. Two of them -- "Same type, different color" and "Filament type not loaded" -- turned out to have had translations sitting in every locale file the whole time, unused, while the component rendered the English literal beside them. The parity gate could not have caught any of this: keys that were never added have nothing to compare against.
This commit is contained in:
@@ -251,6 +251,46 @@ export function getColorName(hexColor: string, material?: string | null): string
|
||||
return hexToColorName(hexColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Label two colours so a reader can tell which is which.
|
||||
*
|
||||
* `getColorName` resolves a hex against the catalogue and falls back to a
|
||||
* coarse family bucket, so a slicer profile's near-pure `#0028FF` and Bambu's
|
||||
* navy `#0A2989` are both called "Blue". A mismatch warning between those two
|
||||
* then reads as a contradiction of the two identical names printed either side
|
||||
* of it, which is the whole of #2941: the comparison was right, the labels gave
|
||||
* the user no way to see what it was comparing.
|
||||
*
|
||||
* When the names collide the hex is appended to both, because that is what
|
||||
* actually differs. Distinct names are returned untouched -- once the words
|
||||
* separate them the hex is noise. A side with no name falls back to its hex, and
|
||||
* a pair with no usable hex at all keeps the bare names rather than growing an
|
||||
* empty "()".
|
||||
*/
|
||||
export function disambiguateColorNames(
|
||||
first: { name?: string | null; hex?: string | null },
|
||||
second: { name?: string | null; hex?: string | null },
|
||||
): [string, string] {
|
||||
const hexLabel = (hex?: string | null): string => {
|
||||
const clean = (hex ?? '').replace('#', '').trim().slice(0, 6).toUpperCase();
|
||||
return /^[0-9A-F]{6}$/.test(clean) ? `#${clean}` : '';
|
||||
};
|
||||
|
||||
const firstName = (first.name ?? '').trim();
|
||||
const secondName = (second.name ?? '').trim();
|
||||
const firstHex = hexLabel(first.hex);
|
||||
const secondHex = hexLabel(second.hex);
|
||||
|
||||
if (!firstName || !secondName) return [firstName || firstHex, secondName || secondHex];
|
||||
if (firstName.toLowerCase() !== secondName.toLowerCase()) return [firstName, secondName];
|
||||
if (!firstHex && !secondHex) return [firstName, secondName];
|
||||
|
||||
return [
|
||||
firstHex ? `${firstName} (${firstHex})` : firstName,
|
||||
secondHex ? `${secondName} (${secondHex})` : secondName,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a spool's display color name.
|
||||
* Tries: stored color_name (if it's a readable name) → runtime catalog via rgba → null.
|
||||
|
||||
Reference in New Issue
Block a user