A round of launch-time and connect-time UX polish plus home-screen widget polish: the Klipper recovery dialog no longer flashes briefly when starting the app or adding a printer, the home panel no longer renders blank after switching printers, and the Snapmaker U1 wizard correctly identifies a U1 instead of showing UNKNOWN. Tapping a fan tile now opens fan control instead of the picker, the fan dial debounces drag-induced Moonraker sends, and the rest of the icon widgets center their icon+label as a group when labels are on. Plus a fix for the M300 sound feedback loop on hosts without a Klipper-declared beeper, the AD5X Method not found toast on the recovery probe, and a wake-from-sleep regression during prints when sleep-while-printing is disabled.
-
Android: "Keep Navigation Bar" setting — Display & Sound > Appearance now has a toggle (Android only) that pins the system nav bar onscreen instead of using immersive mode + swipe-to-reveal. For users who prefer 3-button nav over gesture controls (#908).
-
Display stays asleep mid-print when
sleep_while_printing=false(bundle RYAQGL6C) —check_display_sleep()returned early when a print was active, but the early return also skipped the wake-on-touch path. If the display had entered sleep before the print started, the user was stranded on a blank screen for the duration of the print (RYAQGL6C: 8 touch events, 18-minute wake delay). Wake requests now fire during prints; only the entering of sleep is suppressed. -
Klipper recovery dialog no longer flashes briefly at launch or after Add Printer —
PrinterNetworkStateinitializesklippy_stateto SHUTDOWN as a conservative default; the EmergencyStopOverlay observer fired once with this placeholder at subscribe time, briefly showing the recovery dialog before Moonraker reported real state. Same placeholder also injected thefirmware_restartwidget on the home panel for a few frames. Two targeted guards: the overlay drops the initial placeholder fire on every (re)subscription (singleton flag was sticky after the first launch, so Add Printer's soft restart re-triggered the flash), andPanelWidgetManagergatesfirmware_restartwidget injection onprinter_connection_state == CONNECTED. Genuine shutdown-at-startup is still surfaced via the parallelKLIPPY_SHUTDOWNevent path. Regression introduced by 1d13ed6's freeze-buffering rework, which was previously masking the placeholder fire. -
"Request Failed: Method not found" toast on recovery probe (bundle VHXPB8A3) —
PrinterRecoveryServiceprobesshell_command:helix_recoverand falls back toprinter.firmware_restartif the macro isn't defined; the probe surfaced a scary toast even though the fallback succeeded (AD5X without the macro).MoonrakerAPI::run_shell_commandgains asilentflag; the recovery probe uses it so the global RPC_ERROR event is suppressed for that one call. -
Home panel blank after switching printers —
tear_down_printer_state()destroys the HomePanel singleton; the re-created instance hasfinalized_=false. The cold-launch path callsfinalize_setup()aftercreate_overlays(), but the soft-restart path used by switch_printer didn't, so the home panel rendered as an empty container until next navigation. -
Snapmaker U1 wizard now identifies as Snapmaker U1, not "UNKNOWN" — original heuristics matched a hypothetical RFID-extended firmware (
fm175xx_reader,FILAMENT_DT_UPDATE/QUERY) that doesn't exist on stock U1s. Replaced with patterns verified against a live device:homing_precise_corexy,extruder_offset_calibration,filament_entangle_detect,machine_state_manager,defect_detection,purifier, plus theFEEDING_RUNOUT_EVENT_HANDLEandEXTRUDER_OFFSET_ACTION_PROBE_CALIBRATE_ALLmacros. Old RFID heuristics retained as secondary path for future firmware variants. Kinematics corrected from cartesian to corexy (matcheshoming_precise_corexy+ tmc2240 stepper_x/y wiring). -
M300 sound feedback loop on hosts without a Klipper-declared beeper —
SoundManager::create_backend()fell through to the M300 (Klipper gcode beeper) backend whenever Moonraker was connected and no host audio backend (SDL/ALSA/PWM) initialized. On any printer whose Klipper config lacks[output_pin BEEPER]+[gcode_macro M300], every UI sound triggeredM300→!! Unknown command:M300→ gcode error toast → error_tone sound → M300 feedback loop. Surfaced as "no audio + spam of unknown command M300" on hosts where local audio fails (e.g. Pi where ALSAdefaultfails to open). M300 is now installed lazily fromPrinterCapabilitiesState::set_hardware()only whenhardware.has_speaker()is true (PrinterDiscovery detects[output_pin BEEPER/BUZZER/SPEAKER]in the Klipper config).set_moonraker_client(nullptr)drops an active M300 backend so printer switches don't carry it across. -
Modal dialog sized too tall for short messages — Save Hardware, Reset to defaults, and similar short confirmations were stuck at 200px regardless of message length, with content stretched to fill (two regressions in
modal_dialog.xml:style_min_height=200from f48ceb7,flex_grow=1oncontent_containerfrom 3482bb9). Content container is nowheight=contentwith a responsive#dialog_content_maxtoken (140/200/260/320/440/600/800 across breakpoints), keeping OK/Cancel on-screen with long content. -
L081 Mechanism C anti-pattern in
PrintHistoryManagerandControlsPanel::handle_home_all— bareif (token.expired()) return;on a bg thread followed bythis/member access is a TOCTOU race; detector hit on v0.99.60/ad5x for both callsites.PrintHistoryManager::subscribe_to_notificationsdrops the bare expired check in the WSnotify_history_changedcallback (defer's own guard runs atomically on the main thread).ControlsPanel::handle_home_allrewrites thehome_axessuccess/error callbacks to uselifetime_.bg_cb()instead of manualtok.deferwith the forbidden bg-thread expired prelude. -
Tapping a fan widget now opens fan control, not the fan picker — the fan tile's normal tap showed the which fan to monitor picker on every click. That picker is a configuration choice and belongs behind the edit-mode gear; mirrors the FanStackWidget pattern. Normal tap now pushes the fan control overlay;
on_edit_configurestill opens the picker. -
Fan dial drag debounces SET_FAN_SPEED instead of flooding Moonraker — dragging the fan dial fired
SET_FAN_SPEEDon everyVALUE_CHANGEDtick, flooding Moonraker mid-drag. Latest value is stashed in a 500ms one-shot timer that resets on each tick;RELEASED(orPRESS_LOST) flushes immediately so letting go feels responsive. Timer is cancelled in dtor and move ops to keep itsthisuser_data safe. -
Belt-tension panel's orphaned "Freq Graph" button removed — the button toasted coming soon on every press; gone, along with its handler stub and calibration-doc reference.
-
Icon widgets center icon and label as a vertically-stacked group when labels are on — macros, favorite_macro, motion, lock, led, led_controls, gcode_console, shutdown, network, firmware_restart, and notifications now use the same flex-column layout as temperature: icon and label flow as a centered pair when
show_widget_labelsis on; the label drops out of layout (LV_OBJ_FLAG_HIDDEN) when off so the icon re-centers alone in the cell.panel_widget_amsandpanel_widget_active_spoolare intentionally left alone (their inner content fills 100%/100% and would clip in a flex column). -
Hardware Issues moved from Settings > System to Settings > Hardware & Devices — the Hardware Issues row (visible when hardware validation detects missing/changed hardware) lived next to network/telemetry/factory-reset, but it's about printer hardware; it now sits above Printers in the Hardware & Devices overlay where users actually look. User docs and TROUBLESHOOTING.md updated for the new path (
Settings > Hardware Health→Settings > Hardware & Devices > Hardware Issues). -
Docs refresh — README, USER_GUIDE, FAQ, INSTALL, ROADMAP, and PRINTER_MANAGER updated with current counts (80+ printers, 7 filament backends, 300+ XML components) and aligned hardware-frugality framing for the 1.0 hero/bullet/FAQ language.