mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-17 19:36:28 +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:
@@ -5,7 +5,7 @@ import { Circle, Check, AlertTriangle, RefreshCw, ChevronDown, ChevronUp, Palett
|
||||
import { api } from '../../api/client';
|
||||
import { useFilamentMapping } from '../../hooks/useFilamentMapping';
|
||||
import { getGlobalTrayId, effectivePreferLowest, FTS_INLET_SIDE } from '../../utils/amsHelpers';
|
||||
import { getColorName } from '../../utils/colors';
|
||||
import { disambiguateColorNames, getColorName } from '../../utils/colors';
|
||||
import { useFilamentLabels } from './useFilamentLabels';
|
||||
import { autoAssignRackPositions, rackOptionsForGroup } from '../../utils/nozzleRack';
|
||||
import type { FilamentMappingProps, RackGroupInfo } from './types';
|
||||
@@ -324,11 +324,11 @@ export function FilamentMapping({
|
||||
<Circle className="w-4 h-4" fill={statusColor} stroke="none" />
|
||||
<span>{plateLabel ? `${t('printModal.filamentMapping')} — ${plateLabel}` : t('printModal.filamentMapping')}</span>
|
||||
{hasTypeMismatch ? (
|
||||
<span className="text-xs text-orange-700 dark:text-orange-400">(Type not found)</span>
|
||||
<span className="text-xs text-orange-700 dark:text-orange-400">({t('printModal.statusTypeNotFound')})</span>
|
||||
) : hasColorMismatch ? (
|
||||
<span className="text-xs text-yellow-700 dark:text-yellow-400">(Color mismatch)</span>
|
||||
<span className="text-xs text-yellow-700 dark:text-yellow-400">({t('printModal.statusColorMismatch')})</span>
|
||||
) : (
|
||||
<span className="text-xs text-bambu-green">(Ready)</span>
|
||||
<span className="text-xs text-bambu-green">({t('printModal.statusReady')})</span>
|
||||
)}
|
||||
{isExpanded ? (
|
||||
<ChevronUp className="w-4 h-4 ml-auto" />
|
||||
@@ -385,6 +385,14 @@ export function FilamentMapping({
|
||||
// array shape; defensive fallback covers the empty-reqs render
|
||||
// path that shouldn't reach here anyway.
|
||||
const { resolvedName, colorLabel } = filamentLabels[idx] ?? { resolvedName: item.type, colorLabel: getColorName(item.color) };
|
||||
// Both sides of a colour mismatch routinely resolve to the same
|
||||
// name -- a slicer's pure blue and a spool's navy are both "Blue" --
|
||||
// which made the warning look like it was contradicting itself
|
||||
// (#2941). Qualify them with their hex when the names collide.
|
||||
const [requiredColorLabel, loadedColorLabel] = disambiguateColorNames(
|
||||
{ name: colorLabel, hex: item.color },
|
||||
{ name: item.loaded?.colorName, hex: item.loaded?.color },
|
||||
);
|
||||
return (
|
||||
<div key={idx} className="space-y-1">
|
||||
<div
|
||||
@@ -402,7 +410,7 @@ export function FilamentMapping({
|
||||
}}
|
||||
>
|
||||
{/* Required color */}
|
||||
<span title={`Required: ${resolvedName} - ${colorLabel}`}>
|
||||
<span title={t('printModal.requiredTooltip', { name: resolvedName, color: requiredColorLabel })}>
|
||||
<Circle className="w-3 h-3" fill={item.color} stroke={item.color} />
|
||||
</span>
|
||||
{/* Required type + grams + nozzle badge. Only the name
|
||||
@@ -463,10 +471,10 @@ export function FilamentMapping({
|
||||
? 'border-yellow-500 dark:border-yellow-400/50 text-yellow-700 dark:text-yellow-400'
|
||||
: 'border-orange-500 dark:border-orange-400/50 text-orange-700 dark:text-orange-400'
|
||||
} ${item.isManual ? 'ring-1 ring-blue-400/50' : ''}`}
|
||||
title={item.isManual ? 'Manually selected' : 'Auto-matched'}
|
||||
title={item.isManual ? t('printModal.manuallySelected') : t('printModal.autoMatched')}
|
||||
>
|
||||
<option value="" className="bg-bambu-dark text-bambu-gray">
|
||||
-- Select slot --
|
||||
-- {t('printModal.selectSlot')} --
|
||||
</option>
|
||||
{/*
|
||||
#1722: every loaded slot is offered for every filament row,
|
||||
@@ -509,11 +517,20 @@ export function FilamentMapping({
|
||||
{item.status === 'match' ? (
|
||||
<Check className="w-3 h-3 text-bambu-green" />
|
||||
) : item.status === 'type_only' ? (
|
||||
<span title="Same type, different color">
|
||||
<span
|
||||
title={
|
||||
requiredColorLabel && loadedColorLabel
|
||||
? t('printModal.sameTypeDifferentColorDetail', {
|
||||
required: requiredColorLabel,
|
||||
loaded: loadedColorLabel,
|
||||
})
|
||||
: t('printModal.sameTypeDifferentColor')
|
||||
}
|
||||
>
|
||||
<AlertTriangle className="w-3 h-3 text-yellow-600 dark:text-yellow-400" />
|
||||
</span>
|
||||
) : (
|
||||
<span title="Filament type not loaded">
|
||||
<span title={t('printModal.filamentTypeNotLoaded')}>
|
||||
<AlertTriangle className="w-3 h-3 text-orange-600 dark:text-orange-400" />
|
||||
</span>
|
||||
)}
|
||||
@@ -553,7 +570,9 @@ export function FilamentMapping({
|
||||
</p>
|
||||
)}
|
||||
{hasTypeMismatch && (
|
||||
<p className="text-xs text-orange-700 dark:text-orange-400 mt-2">Required filament type not found in printer.</p>
|
||||
<p className="text-xs text-orange-700 dark:text-orange-400 mt-2">
|
||||
{t('printModal.requiredTypeNotInPrinter')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user