diff --git a/CHANGELOG.md b/CHANGELOG.md index bffd0dfe4..f8ab68b16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to Bambuddy will be documented in this file. - **H2D Tray Disambiguation Triggers on Single-Nozzle Printers** — The `tray_now <= 3` check for H2D dual-nozzle disambiguation matched any printer loading from AMS 0 (trays 0-3). On P2S, X1C, and X1E with multiple AMS units, this caused warning log spam every second. Now uses a persistent `_is_dual_nozzle` flag detected from `device.extruder.info` (>= 2 entries), which only dual-nozzle printers (H2D, H2D Pro) report. - **AMS-HT Snow Slot Mismatch Log Spam on H2D** — The snow-based tray_now disambiguation computed `snow_slot = -1` for AMS-HT trays (IDs 128-135), causing a "slot mismatch" debug log on every MQTT update even though the result was correct. Now correctly computes `snow_slot = 0` for AMS-HT single-slot units. - **Color Tooltip Clipped Behind Adjacent Swatches** — Color swatch hover tooltips in the spool form were rendered behind neighboring swatches due to missing z-index on the hover state. Added `hover:z-20` and tooltip `z-20` classes. +- **Print Queue Shows UUID Hash Instead of Filename** ([#438](https://github.com/maziggy/bambuddy/issues/438)) — When printing a library file, the Print Queue and archive displayed the UUID-hex disk filename (e.g., `c65887535303404eba1525176a0f78dc`) instead of the original human-readable name. Library files are stored on disk with UUID filenames for uniqueness, but `archive_print()` used the disk path as the display name. Now passes the original `LibraryFile.filename` through to `archive_print()` from both the print scheduler and the direct-print-from-library flow, so the archive's `filename`, `print_name`, and directory name all use the human-readable name. - **Usage Tracking Wrong Spool on Dual-Nozzle / Multi-AMS Printers** ([#364](https://github.com/maziggy/bambuddy/issues/364)) — On H2C, H2D Pro, and other dual-nozzle printers with multiple AMS units, the usage tracker attributed filament consumption to the wrong spools. The MQTT `mapping` field — a per-print array that maps slicer filament slots to physical AMS trays — was preserved in state but never parsed or used. The tracker fell back to `slot_id - 1` as the global tray ID, which is incorrect when AMS hardware IDs differ from sequential indices (e.g., AMS-HT units with ID 128). Now decodes the MQTT mapping field from its snow encoding (`ams_hw_id * 256 + local_slot`) into bambuddy global tray IDs and uses it as a universal mapping source — working for all printer models and all print sources (slicer, queue, reprint) without relying on `tray_now` disambiguation. For printers that don't provide the MQTT mapping field (A1, A1 Mini, P1S, P2S), a color-matching fallback compares 3MF filament slot colors against AMS tray colors to resolve the correct slot-to-tray mapping. Gracefully returns no match when colors are ambiguous (duplicate tray colors) or unavailable. - **npm audit: suppress moderate ajv ReDoS finding** — Added `audit-level=high` to `frontend/.npmrc` so `npm audit` exits cleanly. The ajv@6 ReDoS (GHSA-2g4f-4pwh-qvx6) is a transitive dependency of eslint@9 with no patched v6 release; ajv@8 override breaks eslint. The vulnerability requires crafted `$data` schema input — not an attack vector in a linting config. diff --git a/backend/app/api/routes/library.py b/backend/app/api/routes/library.py index dac910fcc..69d7f5233 100644 --- a/backend/app/api/routes/library.py +++ b/backend/app/api/routes/library.py @@ -1795,6 +1795,7 @@ async def print_library_file( archive = await archive_service.archive_print( printer_id=printer_id, source_file=file_path, + original_filename=lib_file.filename, ) if not archive: diff --git a/backend/app/services/archive.py b/backend/app/services/archive.py index dafa5911a..147cbc26f 100644 --- a/backend/app/services/archive.py +++ b/backend/app/services/archive.py @@ -831,6 +831,7 @@ class ArchiveService: source_file: Path, print_data: dict | None = None, created_by_id: int | None = None, + original_filename: str | None = None, ) -> PrintArchive | None: """Archive a 3MF file with metadata. @@ -839,6 +840,8 @@ class ArchiveService: source_file: Path to the 3MF file print_data: Print data from MQTT (optional) created_by_id: User ID who created this archive (optional, for user tracking) + original_filename: Original human-readable filename (optional, for library files + stored with UUID names) """ # Verify printer exists if specified if printer_id is not None: @@ -849,7 +852,8 @@ class ArchiveService: # Create archive directory structure timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - archive_name = f"{timestamp}_{source_file.stem}" + display_stem = Path(original_filename).stem if original_filename else source_file.stem + archive_name = f"{timestamp}_{display_stem}" # Use "unassigned" folder for archives without a printer printer_folder = str(printer_id) if printer_id is not None else "unassigned" archive_dir = settings.archive_dir / printer_folder / archive_name @@ -923,12 +927,12 @@ class ArchiveService: # Create archive record archive = PrintArchive( printer_id=printer_id, - filename=source_file.name, + filename=original_filename or source_file.name, file_path=str(dest_file.relative_to(settings.base_dir)), file_size=dest_file.stat().st_size, content_hash=content_hash, thumbnail_path=thumbnail_path, - print_name=metadata.get("print_name") or source_file.stem, + print_name=metadata.get("print_name") or display_stem, print_time_seconds=metadata.get("print_time_seconds"), filament_used_grams=metadata.get("filament_used_grams"), filament_type=metadata.get("filament_type"), diff --git a/backend/app/services/print_scheduler.py b/backend/app/services/print_scheduler.py index bc510d76f..d5fb3afc6 100644 --- a/backend/app/services/print_scheduler.py +++ b/backend/app/services/print_scheduler.py @@ -915,6 +915,7 @@ class PrintScheduler: archive = await archive_service.archive_print( printer_id=item.printer_id, source_file=file_path, + original_filename=filename, ) if archive: item.archive_id = archive.id