diff --git a/CHANGELOG.md b/CHANGELOG.md index 535488888..562598204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to Bambuddy will be documented in this file. - **Git backup now actually writes cloud profiles (#2717, reporter @jmoore-skild)** — Enabling **Cloud Profiles** for a Git backup produced nothing. The collector looked for a `setting` list in the Bambu Cloud response, which is keyed by preset type instead, so the loop never ran once — and it asked for the credential store used when authentication is *disabled*, so on any install with authentication on it found no account to collect from in the first place. Neither failure was visible: `backup_metadata.json` still recorded `cloud_profiles: true`, and the log line read `Collected cloud profiles: 0 filament, 0 printer, 0 process`, which looks like a successful backup of an empty account. Cloud profiles are now collected from **every connected account across both Bambu Cloud and Orca Cloud**, one directory per cloud per account, keyed by user ID so no email address is written into a backup repository. Bambu presets are stored with the payload needed to recreate them rather than just their names, and Bambu's bundled public catalogue is skipped — it is identical for everyone, re-downloadable, and would rewrite the repository on every run. The metadata now records what was actually collected, per cloud and per account, and a run that collects nothing while the category is enabled says so as a warning instead of an INFO line that reads like success. The Cloud Profiles checkbox no longer keys off your own Bambu sign-in — it enables when *any* account is connected and shows how many are in scope, which matters on a multi-user install where the presets being backed up are other people's. A backup also no longer disconnects an Orca Cloud account whose session it can't refresh: Orca reports every rejection with one composite reason, so a genuine revocation is indistinguishable from a lost token-rotation race, and an unattended job should not be the thing that guesses. The account is skipped with a warning, and the dead credentials are cleared the next time you open Orca Cloud Profiles — where you can pair again on the spot. Translated in all locales; wiki updated. Covered by backend tests. ### Added +- **The print queue now shows when each job would finish (#2736, contributor @mpl1337)** — A queue row carried a job's print duration but not the clock time that maps to, so "if I start this one now, when is it done?" meant doing the arithmetic yourself, once per row — while the card for the running print has shown an ETA all along. Pending and staged rows now show one too, beside the duration, in your configured 12/24-hour format and styled to match the live one. It is deliberately a per-job answer and not a forecast of the whole queue: "start this now and it finishes at 14:30", not a projection of everything ahead of it. That only means anything for a job that could actually start now, so the ETA appears on exactly those. A job sits behind whatever is printing on its printer, and behind anything the scheduler would dispatch ahead of it — resolved in the same order the scheduler itself uses, including **Shortest Job First** when that is on — and stays quiet until it is genuinely next up, so three jobs stacked on one printer no longer quote the same finishing time three times over. Staged jobs are the exception in both directions: the scheduler skips them without claiming the printer, so they neither hold up the job behind them nor wait for it, and they show an ETA whenever their printer is free — which is the honest answer to "what happens if I press Start". Jobs scheduled for later, jobs blocked with a stated reason, jobs conditional on an earlier print succeeding, and jobs with no duration in their metadata show nothing at all. The time also keeps up with the clock instead of freezing at the moment the page was opened, and every row on screen is measured from the same instant, so two rows are always comparable. Frontend-only. Translated in all locales; wiki updated. Covered by frontend tests. - **Configure an OIDC provider from environment variables (#2593, contributor @munin92)** — Single Sign-On could only be set up by clicking through Settings → Authentication, which does not exist as a step in a deployment driven by a compose file, a Helm chart or a GitOps repository: every fresh install of the same stack needed someone to log in and re-enter the same issuer, client ID and secret by hand. One provider can now be defined entirely from `BAMBUDDY_OIDC_*` variables. It is written on startup and re-applied on every boot, so the file in your repository is the source of truth, and providers created in the UI keep working alongside it, untouched. Only the four required variables — name, issuer URL, client ID and client secret — activate it, and all four or none: a half-configured provider is refused at boot with a log line naming what was wrong, rather than appearing on the login page and failing when somebody clicks it. Values are validated by exactly the same rules the settings UI enforces, including the one that refuses account auto-linking on an unverified email address, so the environment cannot reach a configuration the UI would have rejected. A typo never stops the app from booting and never takes a working provider down: the previous configuration keeps running and the reason is logged. In the UI the provider is shown with a lock badge and no edit, delete or enable controls, because startup would overwrite any change at the next restart. Removing the variables disables the provider instead of deleting it — deleting would permanently unlink every account bound to it — and re-adding them brings it back with those links intact. `BAMBUDDY_LOCAL_LOGIN=true` remains the way back in if a misconfigured provider ever locks you out. All thirteen variables are documented in `.env.example`; wiki updated. Covered by backend and frontend tests. - **Keep the AMS slots the slicer picked (#2700, contributor @Striker72rus)** — Bambu Studio and OrcaSlicer resolve which physical AMS tray feeds each filament themselves, right before sending. Bambuddy threw that away: a queue-mode virtual printer worked the mapping out again at dispatch time, from the filament type and colour baked into the 3MF. That is usually the better answer — it is computed against the printer's live trays and it respects **Prefer lowest filament** and the AMS-backup gate that goes with it — but it has nothing to go on when the match isn't unique. Two spools of the same red PLA, and the slot you deliberately chose in the slicer is a coin toss. A new per-virtual-printer **Save AMS mapping** toggle keeps the slicer's pick instead: the print dispatches to exactly those trays, and the mapping is stored on the archive so a reprint can reuse the same physical spools — a **Mapping** button in the print modal selects every slot from it in one click, and the archive card and queue row say so. Because a tray number only means something on the AMS it was resolved against, the mapping records its printer and is only ever offered on that same printer; a model-based ("Any [model]") virtual printer has no fixed printer and is unaffected. Off by default, so nothing changes for existing virtual printers until you turn it on, and **Force color match** still wins for the print being dispatched when both are on. Translated in all locales; wiki updated. Covered by backend and frontend tests. - **P2S/X2D accessory fans: left auxiliary cooling and chamber exhaust (#2691, contributor @gzimbric, requested in #2660)** — The P2S and X2D have two fans Bambuddy could not show or drive. The **left auxiliary part cooling fan** had no tile and no control at all, because the printer only reports it inside its air-duct data and never in the ordinary fan fields Bambuddy was reading. The **chamber exhaust fan** had the opposite problem: its tile appeared on every P2S whether or not the fan was fitted, so owners of a base machine had a control that did nothing. Both are add-on kits on the P2S and fitted at the factory on the X2D. Both tiles now appear only when the printer itself reports the hardware, so a base P2S looks exactly as it does today and a kitted one gains the fans it actually has. The left auxiliary fan is set from the same speed popover as the others, and the enclosure fan is labelled **Exhaust** on the P2S and X2D — matching the printer's own screen and Bambu Studio — while every other enclosed model keeps **Chamber Fan**. The confirmation message after changing a speed uses the same name as the tile that was clicked. The four tiles are ordered part cooling, left auxiliary, auxiliary, exhaust, so they read left to right in the same order as the physical fans. Both fields are also published through the status endpoint, the WebSocket feed and the MQTT relay, so external automations can read them. Translated in all locales; wiki updated. Covered by backend and frontend tests, including the case where the printer sends a partial fan report — a tile must not disappear mid-print just because one update didn't mention it.