mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-22 03:49:18 +02:00
● fix(ams): restore Configure/Assign actions on reset slots + relax Assign Spool filtering (#1047)
Three related fixes reported together:
(1) After resetting an AMS slot, the printer card showed "Empty Slot"
with no Configure or Assign Spool actions while SpoolBuddy's AMS page
still let the user re-configure the same slot. Commit c9efa4b8 (#784)
added a `tray?.state === 10` gate to the EmptySlotHoverCard actions,
intended to hide them on physically-empty slots (state=9). In practice
firmware often reports state=9 (or omits state entirely) after a
user-initiated reset even when a spool is still present, so the gate
hit the wrong case. The gate was redundant anyway — EmptySlotHoverCard
only renders when tray_type is empty — so it's removed at both the
standard-AMS and AMS-HT render paths.
(2) After configuring a slot with a Generic profile, the Assign Spool
modal hid manually-added inventory spools even when material matched,
unless the user flipped "Show all spools". The filter required exact
slicer_filament_name equality, which manually-added spools don't
populate. Filter now prefers exact slicer-profile match when both
sides have one, and falls back to partial material match in either
direction (so a "PLA" spool shows up for a "PLA Basic" slot).
(3) On assign, the mismatch dialog fired on every Generic spool
because Bambu Studio / OrcaSlicer profile names carry an @printer
nozzle (variant) qualifier while the tray stores the bare base name.
Both the filter and checkProfileMatch now strip everything from @
onward before comparing.
Adds 3 regression tests covering each path.
This commit is contained in:
@@ -111,12 +111,18 @@ export function AssignSpoolModal({ isOpen, onClose, printerId, amsId, trayId, tr
|
||||
return 'none';
|
||||
};
|
||||
|
||||
// Bambu Studio / OrcaSlicer profile names carry a printer/nozzle/variant qualifier after
|
||||
// `@` (e.g. "Devil Design PLA Basic @Bambu Lab H2D 0.4 nozzle (Custom)"), while the tray's
|
||||
// profile is typically the bare base name. Strip the qualifier before comparing so identical
|
||||
// base profiles don't trigger a mismatch warning (#1047).
|
||||
const stripProfileQualifier = (value: string) => value.split('@')[0].trim();
|
||||
|
||||
const checkProfileMatch = (
|
||||
spoolProfile: string | undefined | null,
|
||||
trayProfile: string | undefined | null
|
||||
): boolean => {
|
||||
const normalizedSpoolProfile = normalizeValue(spoolProfile);
|
||||
const normalizedTrayProfile = normalizeValue(trayProfile);
|
||||
const normalizedSpoolProfile = stripProfileQualifier(normalizeValue(spoolProfile));
|
||||
const normalizedTrayProfile = stripProfileQualifier(normalizeValue(trayProfile));
|
||||
|
||||
if (!normalizedSpoolProfile || !normalizedTrayProfile) return false;
|
||||
|
||||
@@ -138,14 +144,29 @@ export function AssignSpoolModal({ isOpen, onClose, printerId, amsId, trayId, tr
|
||||
!assignedSpoolIds.has(spool.id) && (isExternalSlot || (!spool.tag_uid && !spool.tray_uuid))
|
||||
);
|
||||
|
||||
// Filtering logic with toggle: search filter always applies, AMS tray profile filter is optional
|
||||
// Filtering logic with toggle: search filter always applies, AMS tray profile filter is optional.
|
||||
// Show a spool if EITHER the slicer profile matches exactly OR the material overlaps with the
|
||||
// tray's material (partial-match both directions — "PLA" spool accepts a "PLA Basic" slot and
|
||||
// vice versa). Manually-added inventory spools typically have no slicer_filament_name; gating
|
||||
// on strict profile equality alone hid them even when the material matched (#1047).
|
||||
let filteredSpools = manualSpools;
|
||||
if (!disableFiltering) {
|
||||
if (trayInfo?.profile || trayInfo?.type) {
|
||||
const trayProfile = normalizeValue(trayInfo.profile || trayInfo.type);
|
||||
const trayProfile = stripProfileQualifier(normalizeValue(trayInfo?.profile));
|
||||
const trayMaterial = normalizeValue(trayInfo?.material || trayInfo?.type);
|
||||
if (trayProfile || trayMaterial) {
|
||||
filteredSpools = filteredSpools?.filter((spool: InventorySpool) => {
|
||||
const spoolProfile = normalizeValue(spool.slicer_filament_name || spool.slicer_filament);
|
||||
return trayProfile && spoolProfile && spoolProfile === trayProfile;
|
||||
const spoolProfile = stripProfileQualifier(normalizeValue(spool.slicer_filament_name || spool.slicer_filament));
|
||||
const spoolMaterial = normalizeValue(spool.material);
|
||||
if (trayProfile && spoolProfile && spoolProfile === trayProfile) return true;
|
||||
if (trayMaterial && spoolMaterial) {
|
||||
return (
|
||||
spoolMaterial === trayMaterial ||
|
||||
trayMaterial.includes(spoolMaterial) ||
|
||||
spoolMaterial.includes(trayMaterial)
|
||||
);
|
||||
}
|
||||
// Neither side has filterable info on whatever dimension remains — show it.
|
||||
return !spoolProfile && !spoolMaterial;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user