The printed command only works from the directory holding the compose
file, which is the thing the user came to the page not knowing. Adds a
copy button, a saved Compose directory setting, BAMBUDDY_COMPOSE_DIR,
and best-effort detection from a bind mount's host path.
Compose records the directory on every container it creates, but reading
that label needs the Docker socket mounted in — root-equivalent access
for a convenience string. The mountinfo guess is a prefill only: its root
field is relative to the mounted device, so a compose dir on its own
mount loses that prefix, and nothing in the container can detect it.
The field is restricted to path characters. It is the one setting whose
purpose is to be pasted into a root shell, so "/opt/bambuddy; rm -rf /"
would otherwise render as a plausible update command.
The app was built dark-first, so hundreds of hardcoded Tailwind semantic
text/icon utilities at light shades (text-amber-400, text-blue-300, ...) had
no dark: variant. With darkMode:'class' they applied in light theme too,
producing washed-out text on pale tints and white cards — including the three
reported spots (AMS Drying banner, Archives no-3MF warning, debug-logging
banner). Give each a theme-aware pair: a darker readable shade in light theme
with the original pinned to dark:, so dark theme is unchanged. ~100 files.
The bambu-* CSS-variable palette (self-correcting) and the dark-only SpoolBuddy
kiosk are left untouched. Plain text-white is already theme-aware via the
existing index.css .text-white override, so it needed no changes.
PrinterInfoModal's CopyButton only tried navigator.clipboard.writeText(),
which is gated by the secure-context requirement (HTTPS or localhost).
On the typical Bambuddy deployment shape — bare-IP HTTP on the LAN —
navigator.clipboard is undefined; the existing try/catch swallowed the
TypeError, the icon never flipped to the tick, and nothing landed on
the user's clipboard.
Fixed by adding the same off-screen-textarea + document.execCommand('copy')
fallback that CameraTokensPage's plaintext-token modal already uses for
plain-HTTP LAN deployments. Gate on `navigator.clipboard && window.isSecureContext`,
fall back to the legacy path otherwise, and surface the success-tick only
when the copy actually landed (return early without flipping `copied` if
execCommand returns false). The try/finally around the textarea guarantees
DOM cleanup even when the browser throws on a restricted context.
3 new component tests in PrinterInfoModal.test.tsx cover the secure-context
happy path (navigator.clipboard.writeText is called with the correct value),
the plain-HTTP fallback path (execCommand is invoked, no leaked textarea
left in the DOM), and the finally cleanup when execCommand throws
synthetically.
Four attempts at making the printer-card SD badge stable on H2D all failed:
the final straw was powering on an A1 causing every connected H2D to flip to
red simultaneously. Bambu firmware SD signaling is not reliably derivable
from MQTT — the legacy `sdcard` field is sporadic and inconsistently typed,
and home_flag bits 8-9 are cleared on heartbeat pushes regardless of card
state with no clean way to distinguish heartbeats from full status reports.
Remove the badge from the Printers page card and the Printer Info modal,
drop `sdcard` from the frontend PrinterStatus type, and strip all home_flag
derivation and heartbeat-handling code from the MQTT parser.
`state.sdcard` is retained on the backend and populated only from a plain
truthy read of the `sdcard` field, because firmware_update.py uses it as a
precondition before starting firmware installs.
home_flag bit 18 is set on all printers regardless of hardware,
causing the ethernet badge to appear on WiFi-only models (A1, P1P,
etc.). The previous fix removed the feature entirely, so ethernet
printers lost their badge too.
Now only trusts bit 18 on models with an ethernet port (X1C, X1E,
P1S, P2S, H2D, H2D Pro, H2C, H2S). WiFi-only models always show
the WiFi signal badge.
home_flag bit 18 was incorrectly interpreted as "wired/ethernet
connection", causing the ethernet badge to always show — even on
printers without an ethernet port (e.g. A1, P1S). This hid the
WiFi signal indicator entirely.
Removed the wired_network field and ethernet badge UI. The WiFi
signal badge now shows correctly whenever the printer reports
signal strength.
Parse home_flag bit 18 (0x00040000) from MQTT to detect ethernet
connections. When set, the printer card shows a green "Ethernet"
badge with a cable icon instead of WiFi signal strength in dBm.
The printer info modal also displays "Ethernet" instead of WiFi
signal details.
* Add printer card print flow with drag-drop and reusable LibraryUploadModal
Extract inline upload modal from FileManagerPage into a reusable
LibraryUploadModal component. Add a Print button and drag-drop zone
to printer cards that upload files to the library and open PrintModal
with the printer pre-selected. Only .gcode/.gcode.3mf files are
accepted for printing. PrintModal hides printer selector when a
printer is provided via initialSelectedPrinterIds prop.
* Add printer compatibility check for drag-drop and upload-to-print flows
Validates sliced_for_model from file metadata against the target printer model
before opening the print modal, preventing users from printing with incompatible files.
* Improve FileUploadModal: auto-close on success, inline errors, file validation, and i18n
- Close modal automatically after successful upload instead of showing summary
- Show printer compatibility errors inline in the modal instead of closing
- Add validateFile and accept props to restrict file types for print flow
- Add onFileUploaded error return to prevent modal close on incompatible files
- Internationalize all hardcoded error/warning strings across 6 locales
* Clean up incompatible files from library and fix print button i18n
- Delete uploaded file from library when printer compatibility check fails
in both drag-drop and modal upload flows
- Fix print button tooltip to use existing common.print i18n key
- Fix accept attribute to use .gcode,.3mf for proper browser support
* Add printer information modal accessible from card 3-dot menu
Replace inline IP/serial display at bottom of printer card with a
dedicated "Printer Information" modal opened via the card menu. The
modal shows model, status, state, IP address (copyable), serial number
(copyable), WiFi signal, firmware, developer mode, nozzle count, SD
card, auto-archive, total print hours, location, and added date, along
with the printer image. Includes full i18n support across all 6 locales
and accessibility attributes (role="dialog", aria-modal).
* Extract getPrinterImage and getWifiStrength into shared printer utils
---------
Co-authored-by: MartinNYHC <mz@v8w.de>