mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-20 17:50:12 +02:00
feat(print-modal): show each printer slot's colour in the filament mapping (issue #3159)
The Print / Schedule dialog's filament mapping is where the colour a slice asked for is compared against the colour actually loaded, and only the left-hand side of that comparison had a swatch. The slot, and every slot in its dropdown, was text -- and the text cannot be trusted: a slot's colour name is resolved from the Color Catalog or, failing that, from hue, so a third-party beige is announced as "Orange". A "Color mismatch" warning then gives no way to tell a real mismatch from two names for the same hex without opening the printer card in another tab, which on a farm swapping twenty or thirty non-Bambu colours between machines is a check made many times a day. Each slot now carries its colour and its hex, and the slot whose colour is exactly the one the slice asked for is ticked. This works for a slot bound to an inventory spool and for one configured through Configure Slot or on the printer itself: the second kind has no inventory row behind it, and the printer's own tray colour is then what draws. A bound spool contributes what a tray record cannot -- SlotSpoolIdentity gains extra_colors and effect_type, so a two-tone or glittery spool draws as itself rather than as its base colour. The same treatment goes to the filament-override picker used for model-based assignment. It is the same choice on the other dispatch path, and leaving it text-only would have made one decision read two ways. Both controls stop being <select>s to do it, because an <option> renders text and nothing else. SlotPicker keeps what the select gave for free -- arrow, Home/End, Enter and Escape keys, listbox semantics, and the border colouring that encodes match, same-type-different-colour and not-loaded -- and is portaled with position:fixed so it is not clipped by the dialog's own scroll container, flipping above the row when there is no room below.
This commit is contained in:
@@ -342,6 +342,15 @@ class SlotSpoolIdentity:
|
||||
subtype: str | None
|
||||
color_name: str | None
|
||||
rgba: str | None
|
||||
# The rest of the spool's colour, for drawing it rather than naming it
|
||||
# (#3159). A tray record carries one hex and nothing else, so a two-tone
|
||||
# or glittery spool renders as its base colour unless the binding says
|
||||
# otherwise -- and on a farm of third-party spools that is exactly the
|
||||
# swatch somebody is comparing against the slicer's colour. Same shape the
|
||||
# inventory row stores: ``extra_colors`` a comma-separated hex list,
|
||||
# ``effect_type`` one of the client's FilamentEffect names.
|
||||
extra_colors: str | None = None
|
||||
effect_type: str | None = None
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
@@ -350,6 +359,8 @@ class SlotSpoolIdentity:
|
||||
"subtype": self.subtype,
|
||||
"color_name": self.color_name,
|
||||
"rgba": self.rgba,
|
||||
"extra_colors": self.extra_colors,
|
||||
"effect_type": self.effect_type,
|
||||
}
|
||||
|
||||
|
||||
@@ -367,6 +378,8 @@ def _identity_from_internal(spool) -> SlotSpoolIdentity:
|
||||
subtype=_clean(spool.subtype),
|
||||
color_name=_clean(spool.color_name),
|
||||
rgba=_clean(spool.rgba),
|
||||
extra_colors=_clean(spool.extra_colors),
|
||||
effect_type=_clean(spool.effect_type),
|
||||
)
|
||||
|
||||
|
||||
@@ -408,6 +421,11 @@ def _identity_from_spoolman(spool_dict: dict) -> SlotSpoolIdentity | None:
|
||||
subtype=_clean(mapped.get("subtype")),
|
||||
color_name=color_name,
|
||||
rgba=_clean(mapped.get("rgba")),
|
||||
# `_map_spoolman_spool` builds `extra_colors` from Spoolman's own
|
||||
# multi-colour hexes and pins `effect_type` to None, because Spoolman
|
||||
# has no field for it -- see the note there.
|
||||
extra_colors=_clean(mapped.get("extra_colors")),
|
||||
effect_type=_clean(mapped.get("effect_type")),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -991,8 +991,52 @@ class TestSlotSpoolIdentity:
|
||||
# naming this slot from the hex is exactly the bug.
|
||||
"color_name": "Orange",
|
||||
"rgba": "FEC600FF",
|
||||
# A plain single-colour spool: nothing extra to draw (#3159).
|
||||
"extra_colors": None,
|
||||
"effect_type": None,
|
||||
}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_internal_mode_carries_the_rest_of_the_colour(self, db_session, printer_factory):
|
||||
"""A tray record holds one hex, so the binding is the only source for the rest.
|
||||
|
||||
Without this the Print dialog's slot picker (#3159) draws a two-tone or
|
||||
glittery spool as its base colour -- the one comparison the picker
|
||||
exists to make, made against the wrong swatch.
|
||||
"""
|
||||
from backend.app.services.filament_deficit import build_slot_materials
|
||||
|
||||
printer = await printer_factory(model="H2C")
|
||||
spool = Spool(
|
||||
brand="eSUN",
|
||||
material="PLA",
|
||||
subtype="Multicolor",
|
||||
color_name="Rainbow",
|
||||
rgba="FF0000FF",
|
||||
extra_colors="00FF00,0000FF",
|
||||
effect_type="Glitter",
|
||||
label_weight=1000,
|
||||
weight_used=0.0,
|
||||
)
|
||||
db_session.add(spool)
|
||||
await db_session.commit()
|
||||
await db_session.refresh(spool)
|
||||
await _assign(db_session, printer_id=printer.id, spool_id=spool.id, ams_id=2, tray_id=0)
|
||||
|
||||
patches = TestFilamentDeficitBackupAware._patch_status(printer_id=printer.id, backup_on=False, model="H2C")
|
||||
for p in patches:
|
||||
p.start()
|
||||
try:
|
||||
slots = await build_slot_materials(db_session, printer.id)
|
||||
finally:
|
||||
for p in patches:
|
||||
p.stop()
|
||||
|
||||
identity = slots[0].spool
|
||||
assert identity is not None
|
||||
assert identity.extra_colors == "00FF00,0000FF"
|
||||
assert identity.effect_type == "Glitter"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_blank_fields_become_null_so_the_client_can_fall_back(self, db_session, printer_factory):
|
||||
"""Per-field, not all-or-nothing: an unnamed colour still falls back to
|
||||
|
||||
@@ -206,4 +206,8 @@ class TestGetInventoryRemain:
|
||||
"subtype": "Basic",
|
||||
"color_name": "Orange",
|
||||
"rgba": "FEC600FF",
|
||||
# The rest of the colour, for the slot picker's swatch (#3159).
|
||||
# None here: this spool is a single flat colour.
|
||||
"extra_colors": None,
|
||||
"effect_type": None,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user