fix(ams): surface active K-profile when no slot preset is resolvable (#1689 follow-up)

Configure Slot dropped to "default 0.020" on reopen for slots that were
  physically loaded but unconfigured (tray_type="", no slot_preset_mappings
  row). The #1689 cali_idx safety net was unreachable from that path —
  matchingKProfiles early-returned [] on !selectedPresetInfo before the
  safety net ran.

  Split the early return so the cali_idx fallback survives the no-preset
  case: when selectedPresetInfo is null but slotInfo.caliIdx > 0, return
  the active profile as a single-item list (extruder-matched when known).
  Strictly additive; caliIdx == 0/null still returns [], existing matcher
  unchanged when a preset is resolvable.
This commit is contained in:
maziggy
2026-06-09 12:45:36 +02:00
parent f87b5bb3b8
commit 53b318c797
5 changed files with 61 additions and 3 deletions
+2
View File
File diff suppressed because one or more lines are too long
@@ -497,6 +497,45 @@ describe('ConfigureAmsSlotModal', () => {
});
});
it("surfaces the slot's active K-profile when no preset is resolvable (#1689 follow-up)", async () => {
// Repro from Spionkiller01: slot is physically loaded but unconfigured —
// tray_type='', tray_info_idx='', no slot_preset_mappings row — so
// selectedPresetInfo resolves to null. Before the patch the main matcher's
// early return on !selectedPresetInfo skipped past the cali_idx safety net
// entirely; on reopen the dropdown went back to default 0.020 even though
// the printer still holds the active profile at cali_idx=6.
(api.getKProfiles as ReturnType<typeof vi.fn>).mockResolvedValue({
profiles: [
{
slot_id: 6,
extruder_id: 0,
nozzle_id: 'HH00-0.4',
nozzle_diameter: '0.4',
filament_id: 'GFG98',
name: 'active-on-unconfigured-slot',
k_value: '0.030',
n_coef: '0',
ams_id: 0,
tray_id: 0,
setting_id: '',
},
],
});
const slotInfo = {
...defaultProps.slotInfo,
trayType: '',
traySubBrands: '',
caliIdx: 6,
extruderId: 0,
// savedPresetId intentionally omitted — no preset bound yet
};
render(<ConfigureAmsSlotModal {...defaultProps} slotInfo={slotInfo} />);
await waitFor(() => {
expect(screen.getByRole('option', { name: /active-on-unconfigured-slot/ })).toBeInTheDocument();
});
});
it('does not include the active K-profile when caliIdx is 0 or null (#1689 guard)', async () => {
// cali_idx == 0 / null means no profile is active (printer default 0.020).
// The safety net only triggers for activeIdx > 0 — otherwise unrelated
@@ -748,7 +748,24 @@ export function ConfigureAmsSlotModal({
}, [colorCatalog, selectedPresetInfo]);
const matchingKProfiles = useMemo(() => {
if (!kprofilesData?.profiles || !selectedPresetInfo) return [];
if (!kprofilesData?.profiles) return [];
if (!selectedPresetInfo) {
// Assigned-but-unconfigured slot (filament loaded but the printer hasn't
// bound a preset yet: tray_type=""/tray_info_idx=""/no slot_preset_mappings
// row). The cali_idx safety net further down lives past the main name+id
// matcher and never runs from here, so surface the slot's currently-active
// K-profile directly so Configure Slot keeps showing it across reopen
// instead of dropping to default 0.020 (#1689 follow-up).
const activeIdx = slotInfo.caliIdx;
if (activeIdx != null && activeIdx > 0) {
const active = kprofilesData.profiles.find(
p => p.slot_id === activeIdx
&& (slotInfo.extruderId === undefined || p.extruder_id === slotInfo.extruderId),
);
if (active) return [active];
}
return [];
}
const { fullName, material, brand, filamentId } = selectedPresetInfo;
const upperFullName = fullName.toUpperCase();
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -26,7 +26,7 @@
<!-- Splash screens for iOS -->
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
<script type="module" crossorigin src="/assets/index-kb-CgWpZ.js"></script>
<script type="module" crossorigin src="/assets/index-QVjYxA_R.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-7s3X35pi.css">
</head>
<body>