From cb508c5d165a77d82f252ee4fc3ba861603c5177 Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 5 Aug 2026 07:48:23 +0200 Subject: [PATCH 1/4] brace-expansion override ^5.0.8 -> ^5.0.9 (GHSA-rgw5-rvv9-x895, DoS). 5.0.8's maxLength cap was applied in combine(), where output is merged, but not to the two arrays built before it runs: comma alternatives each got their own full allowance and were concatenated with no running total, and padded sequences never consulted maxLength at all. So a ~25 KB pattern still OOMs the process -- fatally, past the reach of try/catch -- and a ~400 KB one blocks the event loop for over two minutes. 5.0.9 bounds both as they are built. Dev-only and transitive here: it reaches us as eslint -> minimatch@5 -> brace-expansion, the only input it sees is our own lint globs, and it is not in the shipped bundle. The ci.yml audit gate runs --omit=dev, so this never would have failed CI; it surfaced through Dependabot. The overrides floor is bumped alongside the lockfile so a clean install can't resolve back to the vulnerable 5.0.8. --- CHANGELOG.md | 2 +- frontend/package-lock.json | 6 +++--- frontend/package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3dc1ebcb..a52d92e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,7 +107,7 @@ All notable changes to Bambuddy will be documented in this file. - **Force color match dispatched a print onto the wrong PLA variant — Matte jobs went to Basic and Silk printers alike, and the wrong AMS slot on a printer holding two same-colour variants (#2650, reporter @MartinNYHC)** — With **Force color match** on, a job sliced for **White PLA Matte** was dispatched to every printer that had *any* white PLA loaded — the ones holding White PLA **Basic** and White PLA **Silk+** included — so a matte model came out glossy on the wrong machine. **Root cause.** Bambu's MQTT status reports every PLA sub-variant as `tray_type == "PLA"`; the Basic/Matte/Silk distinction is carried only in `tray_info_idx` (`GFA00` = Basic, `GFA01` = Matte, `GFA06` = Silk, …), which the 3MF's `slice_info.config` also records per filament. Three places dropped it: the Virtual-Printer queue built each force override as `{slot_id, type, color, force_color_match}` without the parsed `tray_info_idx`; the scheduler's eligibility check (`_get_missing_force_color_slots`) compared loaded trays on `(type, colour)` only — so `(PLA, #FFFFFF)` matched Basic, Matte and Silk indiscriminately and all three printers looked eligible; and the AMS slot mapper cleared `tray_info_idx` when applying the override, so even on the correct printer it could pick a different-variant tray of the same colour. **Fix.** The force override now carries the 3MF's `tray_info_idx`; a slot counts as satisfied only when a loaded tray matches type **and** colour **and** the variant (identical `tray_info_idx`, *or* either side lacks one); and the slot mapper now keeps the variant for force-colour overrides so it pins the matching tray. A blank idx on either side (custom/third-party spools report none, and older 3MFs carry none) falls back to the historical type+colour behaviour, so those setups are unaffected, and a manual filament *swap* (a preference override) still clears the idx so it matches the swapped-in spool rather than the old one. A job sliced for GFA01 now goes only to a printer with GFA01 loaded, and lands on that printer's GFA01 tray. The printer-card queue-compatibility hint (which printers show a pending job as runnable) now applies the same variant rule. Covered by scheduler tests (Matte requirement rejects Basic/Silk, accepts Matte, blank loaded idx falls back, requirement without an idx unchanged; the mapper pins the GFA01 tray over a same-colour GFA00 on both the 3MF and no-3MF paths; a preference swap still matches by colour), a Virtual-Printer test asserting the override carries `tray_info_idx`, and frontend tests for the variant-aware queue hint (rejects other variants, accepts the match, blank-idx and no-variant-data fall back). ### Security -- **Patched two build-time frontend dependencies flagged by `npm audit` (GHSA-r28c-9q8g-f849, GHSA-mh99-v99m-4gvg)** — `postcss` 8.5.15 → 8.5.23 fixes a path traversal in its source-map auto-loader (`sourceMappingURL`) that could disclose arbitrary `.map` files, and `brace-expansion` (pulled in transitively by `eslint` via `minimatch`) is bumped through the existing `overrides` block (`^5.0.7` → `^5.0.8`) for a denial-of-service via unbounded expansion. Both are build/lint-time tooling only — neither is part of the shipped app, so no running Bambuddy install was exposed. `postcss` moved within its existing range; `brace-expansion` needed the pin because `npm audit fix` can't lift `eslint` to the patched transitive on its own. +- **Patched two build-time frontend dependencies flagged by `npm audit` (GHSA-r28c-9q8g-f849, GHSA-mh99-v99m-4gvg, GHSA-rgw5-rvv9-x895)** — `postcss` 8.5.15 → 8.5.23 fixes a path traversal in its source-map auto-loader (`sourceMappingURL`) that could disclose arbitrary `.map` files, and `brace-expansion` (pulled in transitively by `eslint` via `minimatch`) is bumped through the existing `overrides` block (`^5.0.7` → `^5.0.9`) for a denial-of-service via unbounded expansion. The first `brace-expansion` advisory was answered in 5.0.8 by capping the length of the combined result, but that cap covered only the accumulator the results are merged into and not the two intermediate arrays that feed it — so a small brace pattern could still exhaust the heap, fatally and beyond the reach of a `try`/`catch`, or stall the event loop for minutes. 5.0.9 bounds both arrays as they are built. Both packages are build/lint-time tooling only — neither is part of the shipped app, so no running Bambuddy install was exposed. `postcss` moved within its existing range; `brace-expansion` needed the pin because `npm audit fix` can't lift `eslint` to the patched transitive on its own. - **Pinned `react-router` to its most-patched 7.x (7.18.1) and documented the one remaining, unreachable advisory (GHSA-qwww-vcr4-c8h2)** — Staying current on the 7.x line matters: 7.18.1 clears 14 advisories that older 7.x releases carry, several reachable in a browser SPA (open-redirect XSS in ``/`useNavigate`, route-matching DoS). The single advisory that still flags 7.18.1 — a CSRF bypass — applies only to React Router's **RSC mode**, which requires the server runtime (`@react-router/server`, not installed); Bambuddy is a Vite SPA using `BrowserRouter`, so the vulnerable path is unreachable. There is no non-major fix (the patch landed only in the 8.3.0 major, and `react-router-dom` has no 8.x — adopting it would mean migrating every import to `react-router` plus a React peer bump), so `react-router`/`react-router-dom` are pinned to 7.18.1 and the finding is carried as a documented, fail-closed exception in the CI audit gate: a *different* react-router advisory still fails CI, and the exemption is dropped automatically the moment a non-major fix ships. `npm audit fix --force` is deliberately avoided — its suggested "fix" is a downgrade to 7.11.0, which reintroduces those 14 advisories. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c949c7e1e..40d1cd8b1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3173,9 +3173,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", - "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" diff --git a/frontend/package.json b/frontend/package.json index 9f40df21d..1f0e22d9f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,7 +48,7 @@ }, "overrides": { "minimatch": "^10.2.1", - "brace-expansion": "^5.0.8", + "brace-expansion": "^5.0.9", "js-yaml": "^4.3.0", "react-router": "7.18.1" }, From fce7ea0200f4a7d2458fd037ce9d164023116689 Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 5 Aug 2026 08:12:42 +0200 Subject: [PATCH 2/4] Stop the drying badge inventing a temperature on a uniform AMS (#2759) The follow-up to the same report: a second AMS 2 Pro, no aux power, loaded entirely with PLA and drying at the 45C the reporter picked, showed 45C and then switched to 55C. Bambu never echoes back a cycle's filament or temperature, so both come from the target cached when the command went out, and the fallback for a missing cache reads the loaded trays. The first pass narrowed that fallback to units whose spools agree on a filament, which fixed the mixed-unit case in the original report but left the uniform case answering with the spools' RFID-recommended drying_temp -- 55C here. Agreement across slots is evidence of what is being dried, because the dryer heats all of them. It is no evidence of the temperature, which is picked freely in the popover, so the recommendation was never more than a guess wearing the same confident "PLA @ 55C" as a known target. uniform_tray_drying_hint therefore becomes uniform_tray_filament_hint and returns the filament alone. The badge names a temperature only when we sent it, and otherwise shows the filament and the countdown. Both status builders also stopped filling the two fields independently. Entering the fallback when either was missing let a cached filament pair with a guessed temperature and render as though both were known; the temperature now simply has no fallback to reach. The badge required both fields before rendering anything, so dropping the temperature would have blanked it rather than shortening it -- the frontend now renders each on its own terms. No new translation key: the filament type is a passthrough. This changes what is shown when the cached target is missing, not why it goes missing. If the reporter was on the fixed build, the falling- edge gate is still letting a zero through on an unpowered unit, which needs a log covering the start of the cycle. --- CHANGELOG.md | 2 +- backend/app/api/routes/printers.py | 20 +-- backend/app/services/printer_manager.py | 56 ++++--- .../unit/services/test_printer_manager.py | 45 ++++-- .../pages/PrintersPageDryingBadge.test.tsx | 137 ++++++++++++++++++ frontend/src/pages/PrintersPage.tsx | 16 +- .../{index-B67xFyee.js => index-yKwaHTh1.js} | 2 +- static/index.html | 2 +- 8 files changed, 217 insertions(+), 63 deletions(-) create mode 100644 frontend/src/__tests__/pages/PrintersPageDryingBadge.test.tsx rename static/assets/{index-B67xFyee.js => index-yKwaHTh1.js} (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index a52d92e58..bcfe40548 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ All notable changes to Bambuddy will be documented in this file. - **Error and warning toasts now stay up twice as long** — Every pop-up notification disappeared after three seconds regardless of what it said. That is about right for "Settings saved", which confirms something you just did and is skimmed rather than read, but errors and warnings are a different kind of message: they carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not long enough to finish reading one, and a missed error message is gone for good — there is no notification history to go back to. Errors and warnings now hold for six seconds. Success and informational toasts keep the three-second default, so the common case of clicking something and seeing it confirmed is unchanged, and the close button and the manual dismiss work exactly as before on all of them. The background print-dispatch toast is unaffected: it stays up while it has work in progress and clears itself shortly after the last job settles. Covered by frontend tests. ### Fixed -- **A drying cycle no longer reports itself finished a minute after it starts (#2759)** — Starting the dryer on an AMS 2 Pro holding two PETG and two PLA spools and picking PLA showed "PLA @ 45°C" for about a minute, then switched to "PETG @ 65°C" for the remaining twelve hours. Bambu never echoes back which filament or temperature a cycle is running, so the badge reads the target Bambuddy cached when it sent the command — and that cache had been thrown away. Between accepting the command and settling its countdown the firmware publishes one update with the remaining time at zero while the unit is still in its Checking phase; the reporter's log caught 720 minutes, then 0, then 719. Bambuddy read the zero as the cycle ending. Losing the cached target left the badge to guess the filament from the first loaded slot, which happened to be PETG, and its RFID-recommended 65°C — a confident wrong answer for a cycle running PLA at 45. The same false ending also armed smart-plug auto-off-after-drying, so anyone with that switched on had power scheduled to cut one minute into a twelve-hour dry. A remaining time of zero is now only treated as the end of a cycle when the AMS also reports an idle phase, which the firmware already publishes alongside it; stopping a dry early still ends it immediately, and a unit that reports no phase at all still ends its cycles as before. The fallback guess has been tightened to match: it now answers only when every loaded spool is the same filament, and on a mixed unit the badge shows the countdown alone rather than naming a temperature the cycle isn't using. Covered by backend tests. +- **A drying cycle no longer reports itself finished a minute after it starts (#2759)** — Starting the dryer on an AMS 2 Pro holding two PETG and two PLA spools and picking PLA showed "PLA @ 45°C" for about a minute, then switched to "PETG @ 65°C" for the remaining twelve hours. Bambu never echoes back which filament or temperature a cycle is running, so the badge reads the target Bambuddy cached when it sent the command — and that cache had been thrown away. Between accepting the command and settling its countdown the firmware publishes one update with the remaining time at zero while the unit is still in its Checking phase; the reporter's log caught 720 minutes, then 0, then 719. Bambuddy read the zero as the cycle ending. Losing the cached target left the badge to guess the filament from the first loaded slot, which happened to be PETG, and its RFID-recommended 65°C — a confident wrong answer for a cycle running PLA at 45. The same false ending also armed smart-plug auto-off-after-drying, so anyone with that switched on had power scheduled to cut one minute into a twelve-hour dry. A remaining time of zero is now only treated as the end of a cycle when the AMS also reports an idle phase, which the firmware already publishes alongside it; stopping a dry early still ends it immediately, and a unit that reports no phase at all still ends its cycles as before. The fallback guess has been tightened to match, in both directions. It names a filament only when every loaded spool agrees on one — on a mixed unit the badge shows the countdown alone rather than naming a spool the cycle isn't drying — and it no longer guesses a temperature at all. A unit loaded entirely with PLA does tell you what is being dried, but not at what temperature: that is picked freely when the cycle is started, so the spools' RFID-recommended value is never evidence of it, and a second AMS loaded only with PLA and drying at 45°C still read "PLA @ 55°C" whenever the cached target went missing. The badge now names a temperature only when Bambuddy sent it, and shows the filament and countdown without one otherwise. Covered by backend and frontend tests. - **A print that never starts now says AMS drying was running, instead of blaming the SD card (#2758)** — Sending a job to an X2D with two AMS units mid-drying failed silently: the file uploaded, the printer accepted it and then simply stayed idle. Bambuddy waited out the start watchdog, re-uploaded the whole 3MF, waited again, and after three attempts gave up with advice to check the printer's screen and the SD card — while Bambu Studio, asked directly, said it could not start the job because of the drying. Bambuddy now watches the AMS drying telemetry it already receives across the dispatch window and, when a job never starts while a unit was drying, names the units in the failure message and records the correlation in the log from the first attempt rather than only after the retries are spent. This is deliberately a diagnosis and not a rule: the printers concerned support drying *continuing* through a print, so drying and printing are not in conflict as such, and the report also involved one AMS drying without its external power supply — which would make the start-of-print calibration a power problem rather than a drying one. Stopping the cycle automatically would therefore be acting on a guess, and could tear down drying the hardware was happy to continue. Until it is known which of the two is the real obstacle, Bambuddy tells you what it saw and leaves the call to you. The message for a stalled dispatch with no drying involved is unchanged. Wiki updated. Covered by backend tests. - **A hand-written systemd service left the Virtual Printer unable to start, with nothing obvious to blame (#2549, reporter @Ru3ck3)** — The Virtual Printer binds ports 990 and 322, both below 1024, which a service running as a normal user may not do without the `CAP_NET_BIND_SERVICE` capability. Without it the rest of Bambuddy works perfectly and only the Virtual Printer is dead: its sockets never open, the slicer never finds the printer, and the sole trace is one line in the journal. The reporter lost days to this before someone on Discord spotted the missing line. The install script has carried it since March, but the three other places that define the same service did not — the manual-install template, the combined Bambuddy plus SpoolBuddy installer, and the unit the wiki tells you to paste. All three have it now, and the wiki no longer claims the capability is always included when its own instructions omitted it. Bambuddy also diagnoses this itself: **Diagnose** on the virtual printer card previously reported only that nothing was listening on port 990, which reads identically to an ordinary port conflict. It now checks whether the process actually holds the capability and, when that is what is wrong, says so and gives the line to add. The check stays quiet when the port is answering, since fronting it another way (an iptables redirect is the documented alternative) is a legitimate setup, and it stays quiet when the capability is held, so a port that failed for some other reason is not misattributed. Existing installs are unaffected until reinstalled; the diagnostic tells you whether yours needs the line. Translated in all locales; wiki updated. Covered by backend tests. - **A refused AMS filament setting now says so in the log (#2756, reporter @Jostxxl)** — Configuring a slot publishes an `ams_filament_setting` command, and the printer answers it with a verdict. That answer was received and then thrown away at debug level, so a printer that refused the write left no trace at the log level support bundles are collected at. The reporter hit exactly that: six manual **Configure Slot** attempts on one X1C, every one returning success, every one read back by the #2582 verification as still holding the previous profile, and nothing anywhere to say what the printer had made of the command. A refusal is now logged with the printer's own `result` and `reason` alongside the AMS and tray it concerned. Only refusals are promoted — unlike the K-profile and drying commands this one is not rare, since every spool assignment and every K-profile re-apply sends one, and logging each acknowledgement would bury the line worth reading. The developer-mode probe is excluded as well: it sends this same command to the external slot specifically to watch it be refused on P1 firmware, so its failure is a measurement rather than a fault. Diagnostics only — nothing about which commands are sent or how they are built has changed. Covered by backend tests. diff --git a/backend/app/api/routes/printers.py b/backend/app/api/routes/printers.py index 3608bbe6c..4792fff5a 100644 --- a/backend/app/api/routes/printers.py +++ b/backend/app/api/routes/printers.py @@ -62,7 +62,7 @@ from backend.app.services.printer_manager import ( supports_chamber_temp, supports_drying, supports_drying_while_printing, - uniform_tray_drying_hint, + uniform_tray_filament_hint, ) from backend.app.utils.filament_ids import filament_id_to_setting_id from backend.app.utils.http import build_content_disposition @@ -578,18 +578,12 @@ async def get_printer_status( dry_target_temp = None if target_fil_val: dry_filament = str(target_fil_val) - # Fallback: derive from the loaded trays when there is no cached - # target (drying started in a previous backend session, or the - # cache wasn't seeded), and only when they agree on a filament - # type. See uniform_tray_drying_hint. - if dry_target_temp is None or not dry_filament: - hint_filament, hint_temp = uniform_tray_drying_hint( - [(tray.tray_type or "", tray.drying_temp) for tray in trays] - ) - if not dry_filament: - dry_filament = hint_filament - if dry_target_temp is None: - dry_target_temp = hint_temp + # Fallback: name the filament from the loaded trays when there is no + # cached target (drying started in a previous backend session, or + # the cache wasn't seeded), and only when they agree. The + # temperature has no fallback — see uniform_tray_filament_hint. + if not dry_filament: + dry_filament = uniform_tray_filament_hint([tray.tray_type or "" for tray in trays]) ams_units.append( AMSUnit( diff --git a/backend/app/services/printer_manager.py b/backend/app/services/printer_manager.py index 076bfed3f..654a8878a 100644 --- a/backend/app/services/printer_manager.py +++ b/backend/app/services/printer_manager.py @@ -280,8 +280,8 @@ def display_temperatures(temperatures: dict | None, model: str | None) -> dict[s return out -def uniform_tray_drying_hint(loaded_trays: list[tuple[str, object]]) -> tuple[str | None, int | None]: - """Guess an active cycle's filament + target temperature from the loaded trays. +def uniform_tray_filament_hint(loaded_types: list[str]) -> str | None: + """Guess an active cycle's filament from the loaded trays. Bambu never echoes back which filament or temperature a drying cycle is running, so the badge normally reads the target we cached when we sent the @@ -291,30 +291,31 @@ def uniform_tray_drying_hint(loaded_trays: list[tuple[str, object]]) -> tuple[st It answers only when every loaded tray holds the same filament type. On a mixed unit the first tray is evidence of nothing: an AMS holding two PETG and two PLA spools, drying PLA at the 45°C the user picked, was labelled - "PETG @ 65°C" purely because slot 1 happened to be PETG (#2759). Saying - nothing and letting the badge show just the countdown beats stating a - temperature the cycle isn't using. + "PETG @ 65°C" purely because slot 1 happened to be PETG (#2759). + + Deliberately no temperature. The RFID-recommended ``drying_temp`` used to be + returned alongside a uniform filament, which narrowed #2759 to units whose + spools disagree but left the uniform case stating a temperature just as + invented: a unit loaded entirely with PLA, drying at the 45°C the user + picked, read "PLA @ 55°C" the moment the cached target went missing. The + filament type is real evidence — every spool in the unit agrees on it, and + the dryer heats all of them — but the temperature is a free choice in the + popover, so a recommendation is never evidence of what is running. The badge + shows the filament and the countdown, and names a temperature only when we + actually sent it. Args: - loaded_trays: ``(tray_type, drying_temp)`` for each tray, in slot order. - Empty slots (falsy tray_type) are ignored. ``drying_temp`` is the - RFID-recommended value and may be None or unparseable. + loaded_types: ``tray_type`` for each tray, in slot order. Empty slots + (falsy) are ignored. Returns: - ``(filament, temp)``, either of which may be None. + The shared filament type, or None if the loaded trays disagree or the + unit is empty. """ - types = {str(tray_type) for tray_type, _ in loaded_trays if tray_type} + types = {str(tray_type) for tray_type in loaded_types if tray_type} if len(types) != 1: - return None, None - filament = next(iter(types)) - for tray_type, drying_temp in loaded_trays: - if not tray_type or not drying_temp: - continue - try: - return filament, int(drying_temp) - except (TypeError, ValueError): - continue - return filament, None + return None + return next(iter(types)) def supports_drying(model: str | None, firmware: str | None) -> bool: @@ -1333,8 +1334,9 @@ def printer_state_to_dict( # per-tick AMS push, so prefer the cached target from the last # ``send_drying_command``. When we have no record (drying # started in a previous backend lifetime, or the cache was - # never seeded), fall back to the loaded trays — but only when - # they agree on a filament type. See uniform_tray_drying_hint. + # never seeded), the loaded trays can still name the filament + # if they agree — but never the temperature, which only the + # cache knows. See uniform_tray_filament_hint. ams_id_int = int(ams_data.get("id", 0)) target = (drying_targets or {}).get(ams_id_int) dry_target_temp: int | None = None @@ -1349,14 +1351,8 @@ def printer_state_to_dict( dry_target_temp = None if fil_val: dry_filament = str(fil_val) - if dry_target_temp is None or not dry_filament: - hint_filament, hint_temp = uniform_tray_drying_hint( - [(tray.get("tray_type") or "", tray.get("drying_temp")) for tray in trays] - ) - if not dry_filament: - dry_filament = hint_filament - if dry_target_temp is None: - dry_target_temp = hint_temp + if not dry_filament: + dry_filament = uniform_tray_filament_hint([tray.get("tray_type") or "" for tray in trays]) ams_units.append( { diff --git a/backend/tests/unit/services/test_printer_manager.py b/backend/tests/unit/services/test_printer_manager.py index 48ae70fd9..6ef65cf02 100644 --- a/backend/tests/unit/services/test_printer_manager.py +++ b/backend/tests/unit/services/test_printer_manager.py @@ -1378,9 +1378,10 @@ class TestDryingTargetExposure: assert result["ams"][0]["dry_filament"] == "PETG" assert result["ams"][0]["dry_target_temp"] == 65 - def test_falls_back_to_loaded_tray_when_no_cache(self): - """No cached target → derive from the loaded trays' tray_type + - RFID-recommended drying_temp when they agree on a filament.""" + def test_falls_back_to_loaded_tray_filament_when_no_cache(self): + """No cached target → name the filament from the loaded trays when they + agree on a type. The temperature stays unknown: only the cache records + what we actually sent.""" state = self._state_with_ams( { "id": 0, @@ -1392,7 +1393,7 @@ class TestDryingTargetExposure: ) result = printer_state_to_dict(state, drying_targets=None) assert result["ams"][0]["dry_filament"] == "ABS" - assert result["ams"][0]["dry_target_temp"] == 70 + assert result["ams"][0]["dry_target_temp"] is None def test_returns_none_when_no_cache_and_empty_trays(self): """No cache + no loaded tray with tray_type → both fields are None.""" @@ -1443,8 +1444,8 @@ class TestDryingTargetExposure: assert result["ams"][0]["dry_target_temp"] is None def test_fallback_survives_multiple_trays_of_one_type(self): - """Agreement across slots is still evidence — a unit loaded entirely - with PLA keeps the fallback the mixed case gives up.""" + """Agreement across slots is still evidence of the filament — a unit + loaded entirely with PLA keeps the name the mixed case gives up.""" state = self._state_with_ams( { "id": 0, @@ -1458,24 +1459,42 @@ class TestDryingTargetExposure: ) result = printer_state_to_dict(state, drying_targets={}) assert result["ams"][0]["dry_filament"] == "PLA" - assert result["ams"][0]["dry_target_temp"] == 45 - def test_fallback_takes_temp_from_a_later_tray_when_slot_one_has_none(self): - """Only Bambu spools carry an RFID drying_temp. A third-party spool in - slot 1 alongside a genuine one of the same type should not cost us the - temperature.""" + def test_uniform_unit_never_invents_a_temperature(self): + """#2759 follow-up — the reporter's second AMS held only PLA and was + drying at the 45°C they picked, but with no cached target the badge + answered with the RFID recommendation and read "PLA @ 55°C". Every + spool agreeing tells us the filament; it tells us nothing about a + temperature the user chose freely in the popover.""" state = self._state_with_ams( { "id": 0, "dry_time": 719, "tray": [ - {"id": 0, "tray_type": "PLA", "state": 11}, - {"id": 1, "tray_type": "PLA", "drying_temp": 45, "state": 11}, + {"id": 0, "tray_type": "PLA", "drying_temp": 55, "state": 11}, + {"id": 1, "tray_type": "PLA", "drying_temp": 55, "state": 11}, ], } ) result = printer_state_to_dict(state, drying_targets={}) assert result["ams"][0]["dry_filament"] == "PLA" + assert result["ams"][0]["dry_target_temp"] is None + + def test_cached_temp_survives_a_unit_whose_trays_disagree(self): + """The cache is authoritative for both fields. A mixed unit costs us the + filament fallback but must not touch a target we actually sent.""" + state = self._state_with_ams( + { + "id": 0, + "dry_time": 719, + "tray": [ + {"id": 0, "tray_type": "PETG", "drying_temp": 65, "state": 11}, + {"id": 1, "tray_type": "PLA", "drying_temp": 55, "state": 11}, + ], + } + ) + result = printer_state_to_dict(state, drying_targets={0: {"filament": "PLA", "temp": 45}}) + assert result["ams"][0]["dry_filament"] == "PLA" assert result["ams"][0]["dry_target_temp"] == 45 diff --git a/frontend/src/__tests__/pages/PrintersPageDryingBadge.test.tsx b/frontend/src/__tests__/pages/PrintersPageDryingBadge.test.tsx new file mode 100644 index 000000000..ca3ef478d --- /dev/null +++ b/frontend/src/__tests__/pages/PrintersPageDryingBadge.test.tsx @@ -0,0 +1,137 @@ +/** + * The active-cycle badge on the AMS card (#2759). + * + * Bambu never echoes back which filament or temperature a drying cycle is + * running, so the backend hands us two independent fields: `dry_filament`, + * which it can also infer from a uniformly loaded unit, and `dry_target_temp`, + * which it only knows from the target it cached when sending the command. The + * temperature can therefore go missing while the filament survives, and the + * badge has to render that pairing rather than dropping both. + * + * The reporter's second AMS held only PLA and was drying at the 45°C they + * picked; with no cached target the badge previously showed the RFID + * recommendation and read "PLA @ 55°C". + */ +import { describe, it, expect, beforeEach } from 'vitest'; +import { screen, waitFor } from '@testing-library/react'; +import { render } from '../utils'; +import { PrintersPage } from '../../pages/PrintersPage'; +import { http, HttpResponse } from 'msw'; +import { server } from '../mocks/server'; + +const mockPrinter = { + id: 1, + name: 'X1C', + ip_address: '192.168.1.100', + serial_number: '01P00A000000001', + access_code: '12345678', + model: 'X1C', + enabled: true, + nozzle_diameter: 0.4, + nozzle_type: 'stainless_steel', + location: 'Workshop', + auto_archive: true, + created_at: '2024-01-01T00:00:00Z', + updated_at: '2024-01-01T00:00:00Z', +}; + +const baseTray = { + tray_color: 'FF0000FF', + tray_type: 'PLA', + tray_sub_brands: 'PLA Basic', + tray_id_name: 'A00-R0', + tray_info_idx: 'GFA00', + remain: 80, + k: 0.02, + cali_idx: null, + tag_uid: null, + tray_uuid: null, + nozzle_temp_min: 190, + nozzle_temp_max: 230, + drying_temp: 55, + drying_time: 8, + state: 3, +}; + +/** An AMS 2 Pro twelve hours into a cycle, with the badge fields under test. */ +function makeStatus(target: { dry_filament: string | null; dry_target_temp: number | null }) { + return { + connected: true, + state: 'IDLE', + progress: 0, + layer_num: 0, + total_layers: 0, + temperatures: { nozzle: 25, bed: 25, chamber: 25 }, + remaining_time: 0, + filename: null, + wifi_signal: -29, + speed_level: 2, + supports_drying: true, + drying_screen_only: false, + vt_tray: [], + ams: [ + { + id: 0, + humidity: 30, + temp: 33, + is_ams_ht: false, + serial_number: 'AMS00', + sw_ver: '03.00.21.29', + dry_time: 719, + dry_status: 2, + dry_sub_status: 0, + dry_sf_reason: [], + module_type: 'n3f', + ...target, + tray: [0, 1, 2, 3].map((id) => ({ id, ...baseTray })), + }, + ], + }; +} + +function renderWith(target: { dry_filament: string | null; dry_target_temp: number | null }) { + server.use( + http.get('/api/v1/printers/', () => HttpResponse.json([mockPrinter])), + http.get('/api/v1/printers/:id/status', () => HttpResponse.json(makeStatus(target))), + http.get('/api/v1/queue/', () => HttpResponse.json([])), + ); + render(); +} + +describe('PrintersPage — AMS drying badge (#2759)', () => { + beforeEach(() => { + server.use(http.get('/api/v1/queue/', () => HttpResponse.json([]))); + }); + + it('names the filament and the temperature when the cycle target is known', async () => { + renderWith({ dry_filament: 'PLA', dry_target_temp: 45 }); + + await waitFor(() => { + expect(screen.getAllByText('PLA @ 45°C').length).toBeGreaterThan(0); + }); + }); + + it('still names the filament when only the temperature is unknown', async () => { + renderWith({ dry_filament: 'PLA', dry_target_temp: null }); + + // The filament survives on its own — dropping it too would leave the badge + // showing a bare countdown for a cycle we can still describe. + await waitFor(() => { + expect(screen.getAllByText('PLA').length).toBeGreaterThan(0); + }); + // And it must not fall back to the trays' RFID recommendation (55°C here), + // which is what the user's chosen 45°C was being overwritten with. Scoped + // to the badge's own " @ °C" shape — the card carries + // unrelated nozzle and bed readings in °C. + expect(screen.queryByText(/@ \d+°C/)).toBeNull(); + }); + + it('shows the countdown alone when the unit gives no evidence at all', async () => { + renderWith({ dry_filament: null, dry_target_temp: null }); + + await waitFor(() => { + expect(screen.getAllByText(/11h 59m/).length).toBeGreaterThan(0); + }); + expect(screen.queryByText(/@ \d+°C/)).toBeNull(); + }); +}); diff --git a/frontend/src/pages/PrintersPage.tsx b/frontend/src/pages/PrintersPage.tsx index 80b5e32b0..6a18f1f4c 100644 --- a/frontend/src/pages/PrintersPage.tsx +++ b/frontend/src/pages/PrintersPage.tsx @@ -4911,9 +4911,15 @@ function PrinterCard({
{t('printers.drying.active')} - {ams.dry_filament && ams.dry_target_temp != null && ( + {/* The temperature is only ever known from the target we + cached when sending the command — the filament can also + be read off a uniformly loaded unit, so it can outlive + the temperature (#2759). */} + {ams.dry_filament && ( - {t('printers.drying.targetSummary', { filament: ams.dry_filament, temp: ams.dry_target_temp })} + {ams.dry_target_temp != null + ? t('printers.drying.targetSummary', { filament: ams.dry_filament, temp: ams.dry_target_temp }) + : ams.dry_filament} )} @@ -5453,9 +5459,11 @@ function PrinterCard({ {ams.dry_time > 0 && (
- {ams.dry_filament && ams.dry_target_temp != null && ( + {ams.dry_filament && ( - {t('printers.drying.targetSummary', { filament: ams.dry_filament, temp: ams.dry_target_temp })} + {ams.dry_target_temp != null + ? t('printers.drying.targetSummary', { filament: ams.dry_filament, temp: ams.dry_target_temp }) + : ams.dry_filament} )} diff --git a/static/assets/index-B67xFyee.js b/static/assets/index-yKwaHTh1.js similarity index 98% rename from static/assets/index-B67xFyee.js rename to static/assets/index-yKwaHTh1.js index 75e4a809c..d01aaf18e 100644 --- a/static/assets/index-B67xFyee.js +++ b/static/assets/index-yKwaHTh1.js @@ -8537,7 +8537,7 @@ void main() { `,title:R(`printers:control`)?P(n?`printers.resume`:`printers.pause`):P(`printers.permission.noControl`),children:[n?(0,K.jsx)(Dl,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`}):(0,K.jsx)(Sl,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`}),P(n?`printers.resume`:`printers.pause`)]})})(),(()=>{let e=!r||i||!R(`printers:control`);return(0,K.jsxs)(`button`,{onClick:()=>Se(!0),disabled:e,className:` ${s} ${e?a:`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400 hover:bg-red-500/30`} - `,title:R(`printers:control`)?P(`printers.stop`):P(`printers.permission.noControl`),children:[(0,K.jsx)(pu,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`}),P(`printers.stop`)]})})()]})]})]})})(),(cn?.length>0||G.vt_tray.length>0)&&r===`expanded`&&(()=>{let t=cn.filter(e=>e.tray.length>1),n=cn.filter(e=>e.tray.length===1),r=cn.length>0&&G.vt_tray.length>0,g=!(r&&ve),_=e.nozzle_count===2||G?.temperatures?.nozzle_2!==void 0,v=zW[i]??1,y=e=>`${Math.round(e*v*1e3)/1e3}rem`,b=`3.5rem`,S={minWidth:b},C={minWidth:b,maxWidth:y(7.25)},w=e=>({gridTemplateColumns:`repeat(${e}, minmax(${b}, 1fr))`}),T=(G.state===`RUNNING`||G.state===`PAUSE`)&&Array.isArray(G.ams_mapping)?G.ams_mapping:[],E=e=>{let t=Math.max(1,e),n=`calc(${t} * ${b} + ${Math.max(0,t-1)} * 0.25rem + 1rem)`;return{flex:`1 1 ${n}`,minWidth:n}};return(0,K.jsxs)(`div`,{className:`mt-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] uppercase tracking-wider text-bambu-gray font-medium`,children:P(`printers.filaments`)}),(0,K.jsx)(NAe,{state:G.ams_filament_backup,onClick:()=>_e(!0)}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`}),r&&(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(PAe,{hidden:ve,onClick:be}),(0,K.jsx)(`div`,{className:`w-3 h-[2px] bg-bambu-dark-tertiary`})]})]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[t.map(t=>{let n=on[String(t.id)],r=t.id>=128?t.id-128:t.id,i=n===void 0?r:n,g=i===1,v=i===0;return(0,K.jsxs)(`div`,{style:E(4),className:`min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1`,children:[(0,K.jsxs)(`div`,{className:`flex w-full min-h-7 items-center justify-between gap-2 rounded-lg bg-bambu-dark-secondary px-2 py-1`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-1.5`,children:[(0,K.jsx)(LW,{ams:t,printerId:e.id,label:ep(t.id,t.tray.length),amsLabels:Zt,canEdit:R(`printers:update`),onSaved:Qt,children:(0,K.jsx)(`span`,{className:`block truncate text-[length:var(--pc-t10,10px)] text-white font-medium cursor-default select-none`,children:Zt?.[t.id]||ep(t.id,t.tray.length)})}),_&&(g||v)&&(0,K.jsx)(SW,{side:g?`L`:`R`})]}),(t.humidity!=null||t.temp!=null)&&(0,K.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5`,children:[t.humidity!=null&&(0,K.jsx)(DW,{humidity:t.humidity,goodThreshold:a?.humidityGood,fairThreshold:a?.humidityFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`humidity`}),compact:!0}),t.temp!=null&&(0,K.jsx)(`div`,{className:`mr-1`,children:(0,K.jsx)(OW,{temp:t.temp,goodThreshold:a?.tempGood,fairThreshold:a?.tempFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`temperature`}),compact:!0})}),(G.supports_drying||G.drying_screen_only)&&(t.module_type===`n3f`||t.module_type===`n3s`)&&R(`printers:control`)&&(0,K.jsx)(`button`,{disabled:G.drying_screen_only||!!(t.dry_sf_reason?.length&&t.dry_time===0),onClick:e=>{if(t.dry_time>0)Bn.mutate(t.id);else if(Je===t.id)Ye(null);else{let n=(t.tray.find(e=>e.tray_type)?.tray_type||`PLA`).split(` `)[0].toUpperCase(),r=x[n]||x.PLA,i=t.module_type;et(n),nt(r[i]||r.n3f),it(i===`n3s`?r.n3s_hours:r.n3f_hours),ot(!1),Ze(t.module_type),Ye(t.id),ct(Zp({triggerRect:e.currentTarget.getBoundingClientRect(),popoverWidth:yW,estimatedHeight:bW,horizontalAlign:`center`}))}},className:`ml-1 flex items-center gap-0.5 px-1 py-0.5 rounded text-[length:var(--pc-t9,9px)] transition-colors ${t.dry_time>0?`bg-amber-100 dark:bg-amber-500/20 text-amber-700 dark:text-amber-400`:G.drying_screen_only||t.dry_sf_reason?.length?`bg-bambu-dark text-bambu-gray/50 cursor-not-allowed`:`bg-bambu-dark text-bambu-gray hover:text-white hover:bg-bambu-dark/80`}`,title:G.drying_screen_only?P(`printers.drying.screenOnly`):t.dry_time>0?P(`printers.drying.stop`):t.dry_sf_reason?.length?P(`printers.drying.powerRequired`):P(`printers.drying.start`),children:(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})]})]}),t.dry_time>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 rounded-lg bg-amber-50 dark:bg-amber-500/10 px-2 py-1 text-[length:var(--pc-t9,9px)]`,children:[(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] text-amber-600 dark:text-amber-400 shrink-0`}),(0,K.jsx)(`span`,{className:`text-amber-700 dark:text-amber-400 font-medium`,children:P(`printers.drying.active`)}),t.dry_filament&&t.dry_target_temp!=null&&(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70`,children:P(`printers.drying.targetSummary`,{filament:t.dry_filament,temp:t.dry_target_temp})}),(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70`,children:P(`printers.drying.timeRemaining`,{time:t.dry_time>=60?`${Math.floor(t.dry_time/60)}h ${t.dry_time%60}m`:`${t.dry_time}m`})}),!G.drying_screen_only&&(0,K.jsx)(`button`,{onClick:()=>Bn.mutate(t.id),disabled:Bn.isPending,className:`ml-auto text-amber-700 dark:text-amber-400 hover:text-amber-900 dark:hover:text-amber-300 transition-colors disabled:opacity-50`,title:P(`printers.drying.stop`),children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})]}),(0,K.jsx)(`div`,{className:`grid w-full gap-1`,style:w(4),children:[0,1,2,3].map(r=>{let i=t.tray[r]||t.tray.find(e=>e.id===r),a=i?.tray_type&&i.remain>=0,g=!i?.tray_type,_=kW(i),v=t.id*4+r,y=dn===v,b=fn!==null&&fn===v,x=pn!==null&&pn===v,C=i?.tray_info_idx?Kt?.[i.tray_info_idx]:null,w=qt?.[v],E=(i?.tray_uuid||i?.tag_uid||fp(e.serial_number,t.id,r))?.toUpperCase(),D=E?s?.[E]:void 0,O=lp(D),k=o&&!m?p?.find(n=>n.printer_id===e.id&&n.ams_id===t.id&&n.tray_id===r):void 0,A=k?f?.find(e=>e.id===k.spoolman_spool_id):void 0,j=A&&(A.label_weight??0)>0?Math.round(Math.max(0,(A.label_weight??0)-A.weight_used)/(A.label_weight??1)*100):null,M=u?.(e.id,t.id,r),N=(()=>{let e=M?.spool;return e&&e.label_weight>0&&e.weight_used!=null?Math.round(Math.max(0,e.label_weight-e.weight_used)/e.label_weight*100):null})(),F=N===0&&a&&i.remain>0?null:N,I=O??j??F??(a?i.remain:null),L=O!==null||j!==null?`spoolman`:F===null?a?`ams`:void 0:`inventory`,z=i?.tray_type?{vendor:Sp(i)?`Bambu Lab`:`Generic`,profile:w?.preset_name||(A?[A.brand,A.slicer_filament_name?.split(`@`)[0].trim()||A.material].filter(Boolean).join(` `).trim():null)||M?.spool?.slicer_filament_name||C?.name||i.tray_sub_brands||i.tray_type,colorName:pf(i.tray_color||``),colorHex:i.tray_color||null,kFactor:xW(i.k),fillLevel:I,trayUuid:i.tray_uuid||null,tagUid:i.tag_uid||null,fillSource:L}:null,B=hr?.amsId===t.id&&hr?.slotId===r,V=T.indexOf(v),ee=V>=0?`P${V+1}`:null,te=(0,K.jsxs)(`div`,{className:`relative w-full bg-bambu-dark-secondary rounded-lg p-1 text-center ${g?`opacity-50`:``} ${b?`ring-2 ring-amber-400 ring-offset-1 ring-offset-bambu-dark animate-pulse`:x?`ring-2 ring-red-500/60 ring-offset-1 ring-offset-bambu-dark`:y?`ring-2 ring-bambu-green ring-offset-1 ring-offset-bambu-dark`:``}`,children:[b&&(0,K.jsx)(`span`,{"aria-label":P(`printers.expectedSlot.ariaLabel`,{n:r+1}),title:P(`printers.expectedSlot.title`),className:`absolute top-0.5 left-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-amber-400 rounded pointer-events-none leading-none`,children:`↓`}),ee&&(0,K.jsx)(`span`,{"aria-label":P(`printers.activeJobSlot.ariaLabel`,{n:V+1}),title:P(`printers.activeJobSlot.title`,{n:V+1}),className:`absolute top-0.5 right-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-bambu-green rounded pointer-events-none leading-none`,children:ee}),(0,K.jsx)(vW,{trayColor:i?.tray_color,trayType:i?.tray_type,isEmpty:g,emptyKind:_,slotNumber:r+1}),(0,K.jsx)(`div`,{className:`text-[length:var(--pc-t9,9px)] text-white font-bold truncate`,children:i?.tray_type||P(_===`reset`?`ams.slotUnconfigured`:`ams.slotEmpty`)}),(0,K.jsx)(`div`,{className:`mt-1 h-1.5 bg-black/30 rounded-full overflow-hidden`,children:I!==null&&I>=0&&!g&&i&&(0,K.jsx)(`div`,{className:`h-full rounded-full transition-all`,style:{width:`${I}%`,backgroundColor:cp(I)}})})]});return(0,K.jsxs)(`div`,{className:`relative group w-full`,style:S,children:[B&&(0,K.jsx)(`div`,{className:`absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20`,children:(0,K.jsx)(Fl,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] text-bambu-green animate-spin`})}),z?(0,K.jsx)(uU,{data:z,actions:qr({amsId:t.id,slotId:r,loadTrayId:t.id*4+r,isRefreshing:B}),spoolman:{enabled:o,linkedSpoolId:k?.spoolman_spool_id??(E?s?.[E]?.id:void 0),spoolmanUrl:c,syncMode:l,onLinkSpool:o&&!k&&!M?()=>{let n=(z.trayUuid||z.tagUid||fp(e.serial_number,t.id,r)).toUpperCase();St({tagUid:z.tagUid||n,trayUuid:z.trayUuid||``,printerId:e.id,amsId:t.id,trayId:r})}:void 0,onUnlinkSpool:D?.id?()=>Rn.mutate(D.id):void 0},inventory:(()=>{if(o){if(m)return;let n=k,a=A;return{assignedSpool:a?{id:a.id,material:a.material,brand:a.brand??null,color_name:a.color_name??null,remainingWeightGrams:a.label_weight?Math.max(0,Math.round(a.label_weight-a.weight_used)):void 0}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:r,trayInfo:{type:i?.tray_type||z.profile,material:i?.tray_type??void 0,profile:z.profile,color:z.colorHex||``,location:`${ep(t.id,t.tray.length)} Slot ${r+1}`}}),onUnassignSpool:a&&!Sp(i)?()=>h?.(a.id):void 0,isAssigned:!!n||Sp(i)}}let n=u?.(e.id,t.id,r);return{assignedSpool:n?.spool?{id:n.spool.id,material:n.spool.material,brand:n.spool.brand,color_name:n.spool.color_name,remainingWeightGrams:Math.max(0,Math.round(n.spool.label_weight-n.spool.weight_used))}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:r,trayInfo:{type:i?.tray_type||z.profile,material:i?.tray_type??void 0,profile:z.profile,color:z.colorHex||``,location:`${ep(t.id,t.tray.length)} Slot ${r+1}`}}),onUnassignSpool:n&&!Sp(i)?()=>d?.(e.id,t.id,r):void 0,isAssigned:!!n||Sp(i)}})(),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:r,trayCount:t.tray.length,trayType:i?.tray_type||void 0,trayColor:i?.tray_color||void 0,traySubBrands:i?.tray_sub_brands||void 0,trayInfoIdx:i?.tray_info_idx||void 0,extruderId:n,caliIdx:i?.cali_idx,savedPresetId:w?.preset_id})},children:te}):(0,K.jsx)(dU,{kind:_??void 0,actions:qr({amsId:t.id,slotId:r,loadTrayId:t.id*4+r,isRefreshing:B}),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:r,trayCount:t.tray.length,extruderId:n})},onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:r,trayInfo:{type:``,material:void 0,profile:``,color:``,location:`${ep(t.id,t.tray.length)} Slot ${r+1}`}}),children:te})]},r)})})]},t.id)}),n.map(t=>{let n=on[String(t.id)],r=t.id>=128?t.id-128:t.id,i=n===void 0?r:n,g=i===1,v=i===0,S=t.tray[0],w=S?.tray_type&&S.remain>=0,E=!S?.tray_type,D=kW(S),O=sp(t.id,S?.id??0,!1),k=dn===O,A=fn!==null&&fn===O,j=pn!==null&&pn===O,M=S?.tray_info_idx?Kt?.[S.tray_info_idx]:null,N=qt?.[O],F=S?.id??0,I=(S?.tray_uuid||S?.tag_uid||fp(e.serial_number,t.id,F))?.toUpperCase(),L=I?s?.[I]:void 0,z=lp(L),B=u?.(e.id,t.id,F),V=(()=>{let e=B?.spool;return e&&e.label_weight>0&&e.weight_used!=null?Math.round(Math.max(0,e.label_weight-e.weight_used)/e.label_weight*100):null})(),ee=V===0&&w&&S.remain>0?null:V,te=o&&!m?p?.find(n=>n.printer_id===e.id&&n.ams_id===t.id&&n.tray_id===F):void 0,H=te?f?.find(e=>e.id===te.spoolman_spool_id):void 0,ne=H&&(H.label_weight??0)>0?Math.round(Math.max(0,(H.label_weight??0)-H.weight_used)/(H.label_weight??1)*100):null,re=z??ne??ee??(w?S.remain:null),U=z!==null||ne!==null?`spoolman`:ee===null?w?`ams`:void 0:`inventory`,ie=S?.tray_type?{vendor:Sp(S)?`Bambu Lab`:`Generic`,profile:N?.preset_name||(H?[H.brand,H.slicer_filament_name?.split(`@`)[0].trim()||H.material].filter(Boolean).join(` `).trim():null)||B?.spool?.slicer_filament_name||M?.name||S.tray_sub_brands||S.tray_type,colorName:pf(S.tray_color||``),colorHex:S.tray_color||null,kFactor:xW(S.k),fillLevel:re,trayUuid:S.tray_uuid||null,tagUid:S.tag_uid||null,fillSource:U}:null,ae=hr?.amsId===t.id&&hr?.slotId===F,W=T.indexOf(O),oe=W>=0?`P${W+1}`:null,se=(0,K.jsxs)(`div`,{className:`relative w-full bg-bambu-dark-secondary rounded-lg p-1 text-center ${E?`opacity-50`:``} ${A?`ring-2 ring-amber-400 ring-offset-1 ring-offset-bambu-dark animate-pulse`:j?`ring-2 ring-red-500/60 ring-offset-1 ring-offset-bambu-dark`:k?`ring-2 ring-bambu-green ring-offset-1 ring-offset-bambu-dark`:``}`,children:[A&&(0,K.jsx)(`span`,{"aria-label":P(`printers.expectedSlot.ariaLabel`,{n:1}),title:P(`printers.expectedSlot.title`),className:`absolute top-0.5 left-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-amber-400 rounded pointer-events-none leading-none`,children:`↓`}),oe&&(0,K.jsx)(`span`,{"aria-label":P(`printers.activeJobSlot.ariaLabel`,{n:W+1}),title:P(`printers.activeJobSlot.title`,{n:W+1}),className:`absolute top-0.5 right-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-bambu-green rounded pointer-events-none leading-none`,children:oe}),(0,K.jsx)(vW,{trayColor:S?.tray_color,trayType:S?.tray_type,isEmpty:E,emptyKind:D,slotNumber:1}),(0,K.jsx)(`div`,{className:`text-[length:var(--pc-t9,9px)] text-white font-bold truncate`,children:S?.tray_type||P(D===`reset`?`ams.slotUnconfigured`:`ams.slotEmpty`)}),(0,K.jsx)(`div`,{className:`mt-1 h-1.5 bg-black/30 rounded-full overflow-hidden`,children:re!==null&&re>=0&&!E&&(0,K.jsx)(`div`,{className:`h-full rounded-full transition-all`,style:{width:`${re}%`,backgroundColor:cp(re)}})})]}),ce=y(11);return(0,K.jsxs)(`div`,{style:{flex:`1 1 ${ce}`,minWidth:ce,maxWidth:`calc(4 * ${b} + 3 * 0.25rem + 1rem)`},className:`min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1`,children:[(0,K.jsxs)(`div`,{className:`flex w-full min-h-7 items-center gap-1.5 rounded-lg bg-bambu-dark-secondary px-2 py-1`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-1.5`,children:[(0,K.jsx)(LW,{ams:t,printerId:e.id,label:ep(t.id,t.tray.length),amsLabels:Zt,canEdit:R(`printers:update`),onSaved:Qt,children:(0,K.jsx)(`span`,{className:`block truncate text-[length:var(--pc-t10,10px)] text-white font-medium cursor-default select-none`,children:Zt?.[t.id]||ep(t.id,t.tray.length)})}),_&&(g||v)&&(0,K.jsx)(SW,{side:g?`L`:`R`})]}),(G.supports_drying||G.drying_screen_only)&&(t.module_type===`n3f`||t.module_type===`n3s`)&&R(`printers:control`)&&(0,K.jsx)(`div`,{className:`relative ml-auto`,children:(0,K.jsx)(`button`,{disabled:G.drying_screen_only,onClick:e=>{if(t.dry_time>0)Bn.mutate(t.id);else if(Je===t.id)Ye(null);else{let n=(t.tray.find(e=>e.tray_type)?.tray_type||`PLA`).split(` `)[0].toUpperCase(),r=x[n]||x.PLA,i=t.module_type;et(n),nt(r[i]||r.n3f),it(i===`n3s`?r.n3s_hours:r.n3f_hours),ot(!1),Ze(t.module_type),Ye(t.id),ct(Zp({triggerRect:e.currentTarget.getBoundingClientRect(),popoverWidth:yW,estimatedHeight:bW,horizontalAlign:`center`}))}},className:`flex items-center gap-0.5 px-1 py-0.5 rounded text-[length:var(--pc-t9,9px)] transition-colors ${t.dry_time>0?`bg-amber-100 dark:bg-amber-500/20 text-amber-700 dark:text-amber-400`:G.drying_screen_only?`bg-bambu-dark text-bambu-gray/50 cursor-not-allowed`:`bg-bambu-dark text-bambu-gray hover:text-white hover:bg-bambu-dark/80`}`,title:G.drying_screen_only?P(`printers.drying.screenOnly`):t.dry_time>0?P(`printers.drying.stop`):P(`printers.drying.start`),children:(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})})]}),t.dry_time>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-1.5 overflow-hidden whitespace-nowrap rounded-lg bg-amber-50 dark:bg-amber-500/10 px-2 py-1 text-[length:var(--pc-t9,9px)]`,children:[(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] text-amber-600 dark:text-amber-400 shrink-0`}),t.dry_filament&&t.dry_target_temp!=null&&(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70 text-[length:var(--pc-t8,8px)] truncate`,children:P(`printers.drying.targetSummary`,{filament:t.dry_filament,temp:t.dry_target_temp})}),(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70 text-[length:var(--pc-t8,8px)] truncate`,children:t.dry_time>=60?`${Math.floor(t.dry_time/60)}h ${t.dry_time%60}m`:`${t.dry_time}m`}),!G.drying_screen_only&&(0,K.jsx)(`button`,{onClick:()=>Bn.mutate(t.id),disabled:Bn.isPending,className:`ml-auto text-amber-700 dark:text-amber-400 hover:text-amber-900 dark:hover:text-amber-300 transition-colors disabled:opacity-50 shrink-0`,title:P(`printers.drying.stop`),children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})]}),(0,K.jsxs)(`div`,{className:`flex gap-1.5 max-[550px]:flex-col max-[550px]:items-start`,children:[(0,K.jsxs)(`div`,{className:`relative group flex-1`,style:C,children:[ae&&(0,K.jsx)(`div`,{className:`absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20`,children:(0,K.jsx)(Fl,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] text-bambu-green animate-spin`})}),ie?(0,K.jsx)(uU,{data:ie,actions:qr({amsId:t.id,slotId:F,loadTrayId:t.id*4+F,isRefreshing:ae}),spoolman:{enabled:o,linkedSpoolId:te?.spoolman_spool_id??(I?s?.[I]?.id:void 0),spoolmanUrl:c,syncMode:l,onLinkSpool:o&&!te&&!B?()=>{let n=(ie.trayUuid||ie.tagUid||fp(e.serial_number,t.id,F)).toUpperCase();St({tagUid:ie.tagUid||n,trayUuid:ie.trayUuid||``,printerId:e.id,amsId:t.id,trayId:F})}:void 0,onUnlinkSpool:L?.id?()=>Rn.mutate(L.id):void 0},inventory:(()=>{if(o){if(m)return;let n=te,r=H;return{assignedSpool:r?{id:r.id,material:r.material,brand:r.brand??null,color_name:r.color_name??null,remainingWeightGrams:r.label_weight?Math.max(0,Math.round(r.label_weight-r.weight_used)):void 0}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:F,trayInfo:{type:S?.tray_type||ie.profile,material:S?.tray_type??void 0,profile:ie.profile,color:ie.colorHex||``,location:ep(t.id,t.tray.length)}}),onUnassignSpool:r&&!Sp(S)?()=>h?.(r.id):void 0,isAssigned:!!n||Sp(S)}}let n=u?.(e.id,t.id,F);return{assignedSpool:n?.spool?{id:n.spool.id,material:n.spool.material,brand:n.spool.brand,color_name:n.spool.color_name,remainingWeightGrams:Math.max(0,Math.round(n.spool.label_weight-n.spool.weight_used))}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:F,trayInfo:{type:S?.tray_type||ie.profile,material:S?.tray_type??void 0,profile:ie.profile,color:ie.colorHex||``,location:ep(t.id,t.tray.length)}}),onUnassignSpool:n&&!Sp(S)?()=>d?.(e.id,t.id,F):void 0,isAssigned:!!n||Sp(S)}})(),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:F,trayCount:t.tray.length,trayType:S?.tray_type||void 0,trayColor:S?.tray_color||void 0,traySubBrands:S?.tray_sub_brands||void 0,trayInfoIdx:S?.tray_info_idx||void 0,extruderId:n,caliIdx:S?.cali_idx,savedPresetId:N?.preset_id})},children:se}):(0,K.jsx)(dU,{kind:D??void 0,actions:qr({amsId:t.id,slotId:F,loadTrayId:t.id*4+F,isRefreshing:ae}),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:F,trayCount:t.tray.length,extruderId:n})},onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:F,trayInfo:{type:``,material:void 0,profile:``,color:``,location:ep(t.id,t.tray.length)}}),children:se})]}),(t.humidity!=null||t.temp!=null)&&(0,K.jsxs)(`div`,{className:`flex flex-col justify-center gap-1 shrink-0 max-[550px]:w-full`,children:[t.temp!=null&&(0,K.jsx)(OW,{temp:t.temp,goodThreshold:a?.tempGood,fairThreshold:a?.tempFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`temperature`}),compact:!0}),t.humidity!=null&&(0,K.jsx)(DW,{humidity:t.humidity,goodThreshold:a?.humidityGood,fairThreshold:a?.humidityFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`humidity`}),compact:!0})]})]})]},t.id)}),G.vt_tray.length>0&&g&&(0,K.jsxs)(`div`,{style:E(G.vt_tray.length),className:`min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1`,children:[(0,K.jsx)(`div`,{className:`flex w-full min-h-7 items-center gap-1.5 rounded-lg bg-bambu-dark-secondary px-2 py-1`,children:(0,K.jsx)(`span`,{className:`block min-w-0 flex-1 truncate text-[length:var(--pc-t10,10px)] text-white font-medium`,children:P(`printers.external`)})}),(0,K.jsx)(`div`,{className:`grid w-full gap-1`,style:w(G.vt_tray.length>1?2:1),children:[...G.vt_tray].sort((e,t)=>(e.id??254)-(t.id??254)).map(t=>{let n=t.id??254,r=_&&dn===254?n===254&&G.active_extruder===1||n===255&&G.active_extruder===0:dn===n,i=n-254,a=_?P(n===254?`printers.extL`:`printers.extR`):``,g=t.tray_info_idx?Kt?.[t.tray_info_idx]:null,v=qt?.[1020+i],y=(t.tray_uuid||t.tag_uid||fp(e.serial_number,255,i))?.toUpperCase(),b=y?s?.[y]:void 0,x=lp(b),C=u?.(e.id,255,i),w=(()=>{let e=C?.spool;return e&&e.label_weight>0&&e.weight_used!=null?Math.round(Math.max(0,e.label_weight-e.weight_used)/e.label_weight*100):null})(),T=t.tray_type&&t.remain>=0,E=w===0&&T&&t.remain>0?null:w,D=o&&!m?p?.find(t=>t.printer_id===e.id&&t.ams_id===255&&t.tray_id===i):void 0,O=D?f?.find(e=>e.id===D.spoolman_spool_id):void 0,k=O&&(O.label_weight??0)>0?Math.round(Math.max(0,(O.label_weight??0)-O.weight_used)/(O.label_weight??1)*100):null,A=x??k??E??(T?t.remain:null),j=x!==null||k!==null?`spoolman`:E===null?T?`ams`:void 0:`inventory`,M={vendor:Sp(t)?`Bambu Lab`:`Generic`,profile:v?.preset_name||(O?[O.brand,O.slicer_filament_name?.split(`@`)[0].trim()||O.material].filter(Boolean).join(` `).trim():null)||C?.spool?.slicer_filament_name||g?.name||t.tray_sub_brands||t.tray_type||`Unknown`,colorName:pf(t.tray_color||``),colorHex:t.tray_color||null,kFactor:xW(t.k),fillLevel:A,trayUuid:t.tray_uuid||null,tagUid:t.tag_uid||null,fillSource:j},N=!t.tray_type,F=kW(t),I=(0,K.jsxs)(`div`,{className:`w-full bg-bambu-dark-secondary rounded-lg p-1 text-center ${N?`opacity-50`:``} ${r?`ring-2 ring-bambu-green ring-offset-1 ring-offset-bambu-dark`:``}`,children:[(0,K.jsx)(vW,{trayColor:t.tray_color,trayType:t.tray_type,isEmpty:N,emptyKind:F,slotNumber:_?n===254?`L`:`R`:i+1}),(0,K.jsx)(`div`,{className:`text-[length:var(--pc-t9,9px)] font-bold truncate ${N?`text-white/40`:`text-white`}`,children:t.tray_type||P(`ams.slotEmpty`)}),(0,K.jsx)(`div`,{className:`mt-1 h-1.5 bg-black/30 rounded-full overflow-hidden`,children:A!==null&&A>=0&&!N&&(0,K.jsx)(`div`,{className:`h-full rounded-full transition-all`,style:{width:`${A}%`,backgroundColor:cp(A)}})})]});return(0,K.jsx)(`div`,{className:`relative group w-full`,style:S,children:N?(0,K.jsx)(dU,{kind:F??void 0,actions:qr({amsId:255,slotId:i,loadTrayId:n,includeRfid:!1}),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:255,trayId:i,trayCount:1,extruderId:_?+(n===254):void 0})},onAssignSpool:()=>wt({printerId:e.id,amsId:255,trayId:i,trayInfo:{type:``,material:void 0,profile:``,color:``,location:`External Slot ${i+1}`}}),children:I}):(0,K.jsx)(uU,{data:M,actions:qr({amsId:255,slotId:i,loadTrayId:n,includeRfid:!1}),spoolman:{enabled:o,linkedSpoolId:D?.spoolman_spool_id??(y?s?.[y]?.id:void 0),spoolmanUrl:c,syncMode:l,onLinkSpool:o&&!D&&!C?()=>{let t=(M.trayUuid||M.tagUid||fp(e.serial_number,255,i)).toUpperCase();St({tagUid:M.tagUid||t,trayUuid:M.trayUuid||``,printerId:e.id,amsId:255,trayId:i})}:void 0,onUnlinkSpool:b?.id?()=>Rn.mutate(b.id):void 0},inventory:(()=>{if(o){if(m)return;let n=D,r=O;return{assignedSpool:r?{id:r.id,material:r.material,brand:r.brand??null,color_name:r.color_name??null,remainingWeightGrams:r.label_weight?Math.max(0,Math.round(r.label_weight-r.weight_used)):void 0}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:255,trayId:i,trayInfo:{type:t.tray_type||M.profile,material:t.tray_type??void 0,profile:M.profile,color:M.colorHex||``,location:a||P(`printers.external`)}}),onUnassignSpool:r&&!Sp(t)?()=>h?.(r.id):void 0,isAssigned:!!n||Sp(t)}}let n=u?.(e.id,255,i);return{assignedSpool:n?.spool?{id:n.spool.id,material:n.spool.material,brand:n.spool.brand,color_name:n.spool.color_name,remainingWeightGrams:Math.max(0,Math.round(n.spool.label_weight-n.spool.weight_used))}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:255,trayId:i,trayInfo:{type:t.tray_type||M.profile,material:t.tray_type??void 0,profile:M.profile,color:M.colorHex||``,location:a||P(`printers.external`)}}),onUnassignSpool:n&&!Sp(t)?()=>d?.(e.id,255,i):void 0,isAssigned:!!n||Sp(t)}})(),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:255,trayId:i,trayCount:1,trayType:t.tray_type||void 0,trayColor:t.tray_color||void 0,traySubBrands:t.tray_sub_brands||void 0,trayInfoIdx:t.tray_info_idx||void 0,extruderId:_?+(n===254):void 0,caliIdx:t.cali_idx,savedPresetId:v?.preset_id})},children:I})},n)})})]})]})]})})()]}),r===`expanded`&&(0,K.jsxs)(`div`,{className:`mt-auto`,children:[gn&&(0,K.jsxs)(`div`,{className:`pt-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] uppercase tracking-wider text-bambu-gray font-medium`,children:P(`printers.power`,`Power`)}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2 rounded-[10px] bg-bambu-dark p-2`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0 pl-1`,children:[(0,K.jsx)(Xu,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] text-bambu-gray flex-shrink-0`}),(0,K.jsx)(`span`,{className:`text-sm text-white truncate`,children:gn.name}),(0,K.jsx)(`span`,{className:`px-1.5 py-0.5 rounded-full bg-bambu-dark-tertiary text-bambu-gray text-[length:var(--pc-t10,10px)] font-medium flex-shrink-0`,title:P(`smartPlugs.power`),children:vn?.energy?.power!==null&&vn?.energy?.power!==void 0?`${Math.round(vn.energy.power)}W`:`--`})]}),(0,K.jsx)(`div`,{className:`flex-1`}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`button`,{onClick:()=>Un.mutate(!gn.auto_off),disabled:Un.isPending||gn.auto_off_executed||!R(`smart_plugs:control`),title:R(`smart_plugs:control`)?gn.auto_off_executed?P(`printers.autoOffExecuted`):P(`printers.autoOffAfterPrint`):P(`printers.permission.noSmartPlugControl`),className:`flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-xs font-bold transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${R(`smart_plugs:control`)?gn.auto_off||gn.auto_off_executed?`bg-bambu-green/20 text-bambu-green hover:bg-bambu-green/30`:`bg-bambu-dark-tertiary text-bambu-gray hover:text-white hover:bg-bambu-dark-tertiary/80`:`bg-bambu-dark-tertiary/50 text-bambu-gray/50`}`,children:(0,K.jsx)(Ts,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})}),(0,K.jsx)(`button`,{onClick:()=>{vn?.state===`ON`?le(!0):se(!0)},disabled:Hn.isPending||!R(`smart_plugs:control`),className:`flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-xs transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${R(`smart_plugs:control`)?vn?.state===`ON`?`bg-bambu-green/20 text-bambu-green hover:bg-bambu-green/30`:`bg-bambu-dark-tertiary text-bambu-gray hover:text-white hover:bg-bambu-dark-tertiary/80`:`bg-bambu-dark-tertiary/50 text-bambu-gray/50`}`,title:R(`smart_plugs:control`)?vn?.state===`ON`?`Turn off`:`Turn on`:P(`printers.permission.noSmartPlugControl`),children:(0,K.jsx)(Xu,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})})]})]}),_n&&_n.length>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mt-2`,children:[(0,K.jsx)(Pc,{className:`w-[var(--pc-i35,0.875rem)] h-[var(--pc-i35,0.875rem)] text-blue-600 dark:text-blue-400 flex-shrink-0`}),(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:`HA:`}),(0,K.jsx)(`div`,{className:`h-[2px] w-5 bg-bambu-dark-tertiary/50`}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:_n.map(e=>{let t=e.ha_entity_id?.startsWith(`script.`);return(0,K.jsxs)(`button`,{onClick:()=>{t?Wn.mutate({id:e.id,action:`on`}):de(e)},disabled:Wn.isPending,title:`${t?`Run`:`Toggle`} ${e.ha_entity_id}`,className:`px-2 py-0.5 text-xs bg-blue-100 dark:bg-blue-500/20 text-blue-700 dark:text-blue-400 hover:bg-blue-500/30 rounded transition-colors flex items-center gap-1`,children:[(0,K.jsx)(Dl,{className:`w-[var(--pc-i25,0.625rem)] h-[var(--pc-i25,0.625rem)]`}),e.name]},e.id)})})]})]}),(0,K.jsxs)(`div`,{className:`pt-4`,children:[(0,K.jsx)(`div`,{className:`mb-3 h-[2px] bg-bambu-dark-tertiary`}),(0,K.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[Jr,(0,K.jsxs)(`div`,{className:`flex items-center justify-end gap-2 flex-wrap`,children:[(0,K.jsx)($,{variant:`secondary`,size:`sm`,onClick:()=>{if(_===`embedded`&&v)v(e.id,e.name);else{let t=localStorage.getItem(`cameraWindowState`),n=t?JSON.parse(t):{width:640,height:400},r=[`width=${n.width}`,`height=${n.height}`,n.left===void 0?``:`left=${n.left}`,n.top===void 0?``:`top=${n.top}`,`menubar=no,toolbar=no,location=no,status=no`].filter(Boolean).join(`,`);window.open(`/camera/${e.id}`,`camera-${e.id}`,r)}},disabled:!G?.connected||!R(`camera:view`),title:R(`camera:view`)?P(_===`embedded`?`printers.openCameraOverlay`:`printers.openCameraWindow`):P(`printers.permission.noCamera`),className:Kr,children:(0,K.jsx)(Ru,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})}),(0,K.jsx)($,{variant:`secondary`,size:`sm`,onClick:()=>ie(!0),disabled:!rn||!R(`printers:files`),title:R(`printers:files`)?P(`printers.browseFiles`):P(`printers.permission.noFiles`),className:Kr,children:(0,K.jsx)(Oc,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})}),rn&&G?.state!==`RUNNING`&&G?.state!==`PAUSE`&&(0,K.jsxs)($,{size:`sm`,onClick:()=>Be(!0),disabled:!R(`library:upload`)||!R(`queue:create`),title:R(`library:upload`)?R(`queue:create`)?P(`common.print`):P(`fileManager.noPermissionAddToQueue`):P(`fileManager.noPermissionUpload`),className:`!h-8 !min-h-8 !px-2 !py-0 !bg-bambu-green hover:!bg-bambu-green/80 !text-white`,children:[(0,K.jsx)(Ml,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`}),P(`common.print`)]})]})]})]})]})]}),U&&(0,K.jsx)(Ole,{printerId:e.id,printerName:e.name,onClose:()=>ie(!1)}),ze&&(0,K.jsx)(QU,{folderId:null,onClose:()=>Be(!1),onUploadComplete:()=>{},autoUpload:!0,accept:`.gcode,.3mf`,validateFile:e=>{let t=e.name.toLowerCase();if(!t.endsWith(`.gcode`)&&!t.includes(`.gcode.`))return P(`printers.dropNotPrintable`,`Only .gcode and .gcode.3mf files can be printed`)},onFileUploaded:t=>{let n=t.metadata?.sliced_for_model,r=IW(e.model);if(n&&r&&n.toLowerCase()!==r.toLowerCase())return Q.deleteLibraryFile(t.id).catch(()=>{}),P(`printers.incompatibleFile`,`This file was sliced for {{slicedFor}}, but this printer is a {{printerModel}}`,{slicedFor:n,printerModel:r});qe({id:t.id,filename:t.filename})}}),Ke&&(0,K.jsx)(gW,{mode:`create`,libraryFileId:Ke.id,archiveName:Ke.filename,initialSelectedPrinterIds:[e.id],onClose:()=>qe(null),onSuccess:()=>qe(null),cleanupLibraryAfterDispatch:!0}),ae&&(0,K.jsx)(Hle,{printerId:e.id,printerName:e.name,onClose:()=>W(!1)}),Ue&&(0,K.jsx)(jp,{printerId:e.id,printerName:e.name,onClose:()=>We(!1)}),Ve&&(0,K.jsx)(SAe,{printer:e,status:G,totalPrintHours:n?.total_print_hours,onClose:Ge}),kt&&(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:()=>Ar(),children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-xl shadow-2xl max-w-lg w-full`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[kt.needs_calibration?(0,K.jsx)(Ul,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)] text-blue-500`}):kt.is_empty?(0,K.jsx)(gs,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)] text-green-500`}):(0,K.jsx)(Ss,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)] text-yellow-500`}),(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:`Build Plate Check`}),kt.reference_count!==void 0&&kt.max_references&&(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray bg-bambu-dark-tertiary px-2 py-1 rounded`,children:[kt.reference_count,`/`,kt.max_references,` refs`]})]}),(0,K.jsx)(`button`,{onClick:()=>Ar(),className:`p-1 text-bambu-gray hover:text-white rounded transition-colors`,children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)]`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-4`,children:[kt.needs_calibration?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`p-3 rounded-lg bg-blue-100 dark:bg-blue-500/20 border border-blue-300 dark:border-blue-500/50`,children:[(0,K.jsx)(`p`,{className:`font-medium text-blue-700 dark:text-blue-400`,children:P(`printers.plateDetection.calibrationRequired`)}),(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mt-1`,dangerouslySetInnerHTML:{__html:P(`printers.plateDetection.calibrationInstructions`)}})]}),(0,K.jsxs)(`div`,{className:`text-sm text-bambu-gray space-y-2`,children:[(0,K.jsx)(`p`,{children:P(`printers.plateDetection.calibrationDescription`)}),(0,K.jsx)(`p`,{dangerouslySetInnerHTML:{__html:P(`printers.plateDetection.calibrationTip`)}})]})]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`p-3 rounded-lg ${kt.is_empty?`bg-green-100 dark:bg-green-500/20 border border-green-300 dark:border-green-500/50`:`bg-yellow-100 dark:bg-yellow-500/20 border border-yellow-300 dark:border-yellow-500/50`}`,children:[(0,K.jsx)(`p`,{className:`font-medium ${kt.is_empty?`text-green-700 dark:text-green-400`:`text-yellow-700 dark:text-yellow-400`}`,children:kt.is_empty?P(`printers.plateDetection.plateEmpty`):P(`printers.plateDetection.objectsDetected`)}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray mt-1`,children:[P(`printers.plateDetection.confidence`),`: `,Math.round(kt.confidence*100),`% | `,P(`printers.plateDetection.difference`),`: `,kt.difference_percent.toFixed(1),`%`]})]}),kt.debug_image_url&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mb-2`,children:P(`printers.plateDetection.analysisPreview`)}),(0,K.jsx)(`img`,{src:kt.debug_image_url,alt:P(`printers.plateDetection.analysisPreview`),className:`w-full rounded-lg border border-bambu-dark-tertiary`}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-2`,children:P(`printers.plateDetection.analysisLegend`)})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:kt.message})]}),Cr&&Cr.references.length>0&&(0,K.jsxs)(`div`,{className:`mt-4`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,K.jsx)(`p`,{className:`text-sm font-medium text-white shrink-0`,children:P(`printers.plateDetection.savedReferences`,{count:Cr.references.length,max:Cr.max_references})}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`})]}),(0,K.jsx)(`div`,{className:`grid grid-cols-5 gap-2`,children:Cr.references.map(t=>(0,K.jsxs)(`div`,{className:`relative group`,children:[(0,K.jsx)(`img`,{src:Q.getPlateReferenceThumbnailUrl(e.id,t.index),alt:t.label||`Reference ${t.index+1}`,className:`w-full aspect-video object-cover rounded border border-bambu-dark-tertiary`}),(0,K.jsx)(`button`,{onClick:()=>Nr(t.index),className:`absolute top-1 right-1 p-0.5 bg-red-500/80 rounded opacity-0 group-hover:opacity-100 transition-opacity`,title:P(`printers.plateDetection.deleteReference`),children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] text-white`})}),Tr?.index===t.index?(0,K.jsx)(`input`,{type:`text`,value:Tr.label,onChange:e=>Er({...Tr,label:e.target.value}),onBlur:()=>Mr(t.index,Tr.label),onKeyDown:e=>{e.key===`Enter`&&Mr(t.index,Tr.label),e.key===`Escape`&&Er(null)},className:`w-full mt-1 px-1 py-0.5 text-xs bg-bambu-dark-tertiary border border-bambu-green rounded text-white`,autoFocus:!0,placeholder:P(`printers.plateDetection.labelPlaceholder`)}):(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1 truncate cursor-pointer hover:text-white`,onClick:()=>Er({index:t.index,label:t.label}),title:t.label?P(`printers.plateDetection.clickToEdit`,{label:t.label}):P(`printers.plateDetection.clickToAddLabel`),children:t.label||(0,K.jsx)(`span`,{className:`italic opacity-50`,children:P(`printers.noLabel`)})}),(0,K.jsx)(`p`,{className:`text-[length:var(--pc-t10,10px)] text-bambu-gray/60`,children:t.timestamp?Vf(t.timestamp)?.toLocaleDateString()??``:``})]},t.index))})]}),!kt.needs_calibration&&(0,K.jsxs)(`div`,{className:`mt-4`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-2`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,K.jsx)(`p`,{className:`text-sm font-medium text-white shrink-0`,children:P(`printers.roi.title`)}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`})]}),Ft?(0,K.jsxs)(`div`,{className:`flex gap-1`,children:[(0,K.jsx)($,{variant:`ghost`,size:`sm`,onClick:()=>It(null),disabled:Lt,children:P(`common.cancel`)}),(0,K.jsx)($,{size:`sm`,onClick:Pr,disabled:Lt,children:Lt?(0,K.jsx)(X,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] animate-spin`}):P(`common.save`)})]}):(0,K.jsxs)($,{variant:`ghost`,size:`sm`,onClick:()=>It(kt.roi||{x:.15,y:.35,w:.7,h:.55}),children:[(0,K.jsx)(Tl,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] mr-1`}),P(`common.edit`)]})]}),Ft?(0,K.jsxs)(`div`,{className:`space-y-3 bg-bambu-dark-tertiary/50 p-3 rounded-lg`,children:[(0,K.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.roi.xStart`)}),(0,K.jsx)(`input`,{type:`range`,min:`0`,max:`0.9`,step:`0.01`,value:Ft.x,onChange:e=>It({...Ft,x:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.x*100),`%`]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.roi.yStart`)}),(0,K.jsx)(`input`,{type:`range`,min:`0`,max:`0.9`,step:`0.01`,value:Ft.y,onChange:e=>It({...Ft,y:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.y*100),`%`]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.width`)}),(0,K.jsx)(`input`,{type:`range`,min:`0.1`,max:`1`,step:`0.01`,value:Ft.w,onChange:e=>It({...Ft,w:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.w*100),`%`]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.height`)}),(0,K.jsx)(`input`,{type:`range`,min:`0.1`,max:`1`,step:`0.01`,value:Ft.h,onChange:e=>It({...Ft,h:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.h*100),`%`]})]})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:P(`printers.roi.instruction`)})]}):(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray`,children:[`Current: X=`,Math.round((kt.roi?.x||.15)*100),`%, Y=`,Math.round((kt.roi?.y||.35)*100),`%, W=`,Math.round((kt.roi?.w||.7)*100),`%, H=`,Math.round((kt.roi?.h||.55)*100),`%`]})]})]}),(0,K.jsx)(`div`,{className:`flex justify-end gap-2 p-4`,children:kt.needs_calibration?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)($,{variant:`ghost`,onClick:()=>Ar(),children:P(`common.cancel`)}),(0,K.jsx)($,{onClick:()=>jr(),disabled:Nt,children:Nt?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] mr-2 animate-spin`}),`Calibrating...`]}):`Calibrate Empty Plate`})]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)($,{variant:`ghost`,onClick:()=>jr(),disabled:Nt,children:Nt?`Adding...`:`Add Reference (${Cr?.references.length||0}/${Cr?.max_references||5})`}),(0,K.jsx)($,{onClick:()=>Ar(),children:`Close`})]})})]})}),oe&&gn&&(0,K.jsx)(Kd,{title:P(`printers.confirm.powerOnTitle`),message:P(`printers.confirm.powerOnMessage`,{name:e.name}),confirmText:P(`printers.confirm.powerOnButton`),variant:`default`,onConfirm:()=>{Hn.mutate(`on`),se(!1)},onCancel:()=>se(!1)}),ur&&(0,K.jsx)(Kd,{title:P(`printers.maintenance.confirmMidPrintTitle`),message:P(`printers.maintenance.confirmMidPrintMessage`,{name:e.name}),confirmText:P(`printers.maintenance.menuEnter`),variant:`danger`,onConfirm:()=>{lr.mutate(!1),dr(!1)},onCancel:()=>dr(!1)}),ce&&gn&&(0,K.jsx)(Kd,{title:P(`printers.confirm.powerOffTitle`),message:G?.state===`RUNNING`?P(`printers.confirm.powerOffWarning`,{name:e.name}):P(`printers.confirm.powerOffMessage`,{name:e.name}),confirmText:P(`printers.confirm.powerOffButton`),variant:`danger`,onConfirm:()=>{Hn.mutate(`off`),le(!1)},onCancel:()=>le(!1)}),ue&&(0,K.jsx)(Kd,{title:P(`printers.confirm.haToggleTitle`,{name:ue.name}),message:G?.state===`RUNNING`?P(`printers.confirm.haToggleWarning`,{name:e.name,entity:ue.ha_entity_id||ue.name}):P(`printers.confirm.haToggleMessage`,{entity:ue.ha_entity_id||ue.name}),confirmText:P(`printers.confirm.haToggleButton`),variant:G?.state===`RUNNING`?`danger`:`default`,onConfirm:()=>{Wn.mutate({id:ue.id,action:`toggle`}),de(null)},onCancel:()=>de(null)}),xe&&(0,K.jsx)(Kd,{title:P(`printers.confirm.stopTitle`),message:P(`printers.confirm.stopMessage`,{name:e.name}),confirmText:P(`printers.confirm.stopButton`),variant:`danger`,onConfirm:()=>{Gn.mutate(),Se(!1)},onCancel:()=>Se(!1)}),Ce&&(0,K.jsx)(Kd,{title:P(`printers.confirm.pauseTitle`),message:P(`printers.confirm.pauseMessage`,{name:e.name}),confirmText:P(`printers.confirm.pauseButton`),variant:`default`,onConfirm:()=>{Kn.mutate(),we(!1)},onCancel:()=>we(!1)}),Fe&&(0,K.jsx)(Kd,{title:P(`printers.confirm.resumeTitle`),message:P(`printers.confirm.resumeMessage`,{name:e.name}),confirmText:P(`printers.confirm.resumeButton`),variant:`default`,onConfirm:()=>{qn.mutate(),Ie(!1)},onCancel:()=>Ie(!1)}),(0,K.jsx)(kT,{printerId:e.id,isOpen:Le,onClose:()=>Re(!1)}),fe&&(0,K.jsx)(vee,{printerName:e.name,errors:G?.hms_errors||[],onClose:()=>pe(!1),printerId:e.id,hasPermission:R,runoutGuidance:hn}),me&&(0,K.jsx)(Ule,{printerName:e.name,detection:M,lastError:N,onClose:()=>he(!1)}),ge&&G&&(0,K.jsx)(zke,{isOpen:ge,state:G.ams_filament_backup,amsUnits:G.ams,amsExtruderMap:G.ams_extruder_map,isDualNozzle:e.nozzle_count===2||G?.temperatures?.nozzle_2!==void 0,canToggle:R(`printers:control`),pending:Vn.isPending,onToggle:e=>Vn.mutate(e),onClose:()=>_e(!1)}),_t&&(0,K.jsx)(Fke,{isOpen:!!_t,onClose:()=>vt(null),printerId:e.id,printerName:e.name,amsId:_t.amsId,amsLabel:_t.amsLabel,initialMode:_t.mode,thresholds:a}),yt&&(0,K.jsx)(Vke,{isOpen:!!yt,onClose:()=>bt(null),printerId:e.id,printerName:e.name,initialKind:yt.initialKind,availableKinds:yt.availableKinds}),xt&&(0,K.jsx)(fU,{isOpen:!!xt,onClose:()=>St(null),tagUid:xt.tagUid,trayUuid:xt.trayUuid,printerId:xt.printerId,amsId:xt.amsId,trayId:xt.trayId}),Ct&&(0,K.jsx)(mU,{isOpen:!!Ct,onClose:()=>wt(null),printerId:Ct.printerId,amsId:Ct.amsId,trayId:Ct.trayId,trayInfo:Ct.trayInfo,spoolmanEnabled:!!o}),Tt&&(0,K.jsx)(XU,{isOpen:!!Tt,onClose:()=>Et(null),printerId:e.id,slotInfo:Tt,printerModel:IW(e.model)||void 0,nozzleDiameter:xp(G,Tt.amsId),onSuccess:()=>{F.invalidateQueries({queryKey:[`slotPresets`,e.id]}),F.invalidateQueries({queryKey:[`printerStatus`,e.id]})}}),ne&&(0,K.jsx)(KAe,{printer:e,onClose:()=>re(!1)}),Dt&&Vt&&(0,K.jsx)(GAe,{printer:e,firmwareInfo:Vt,onClose:()=>Ot(!1)}),Je!==null&&st&&(()=>{let e=Xe===`n3s`?85:65,t=e+10;return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`div`,{className:`fixed inset-0 z-[100]`,onClick:()=>Ye(null)}),(0,K.jsxs)(`div`,{className:`fixed z-[101] flex flex-col w-[240px] bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-xl shadow-2xl overflow-hidden`,style:{top:st.top,left:st.left,maxHeight:`calc(100dvh - ${st.top}px - 8px)`},onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`shrink-0 flex items-center justify-center gap-2 px-3 py-2.5`,children:[(0,K.jsx)(lc,{className:`w-[var(--pc-i35,0.875rem)] h-[var(--pc-i35,0.875rem)] text-bambu-green`}),(0,K.jsx)(`span`,{className:`text-sm text-white font-medium text-center`,children:P(`printers.drying.start`)})]}),(0,K.jsx)(`div`,{className:`shrink-0 h-px bg-bambu-dark-tertiary`}),(0,K.jsxs)(`div`,{className:`px-3 py-2.5 space-y-2.5 overflow-y-auto min-h-0`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-[length:var(--pc-t10,10px)] text-white/70 font-medium mb-1 block`,children:P(`printers.filaments`)}),(0,K.jsx)(AW,{value:Qe,options:Object.keys(x).map(e=>({value:e,label:e})),onChange:e=>{et(e);let t=x[e];t&&(nt(t[Xe===`n3s`?`n3s`:`n3f`]),it(Xe===`n3s`?t.n3s_hours:t.n3f_hours))},fullWidth:!0})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-1`,children:[(0,K.jsx)(`label`,{className:`text-[length:var(--pc-t10,10px)] text-white/70 font-medium`,children:P(`printers.drying.temperature`)}),(0,K.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,K.jsx)(`input`,{type:`number`,min:45,max:e,value:tt,onChange:t=>nt(Math.min(e,Math.max(45,Number(t.target.value)||45))),className:`w-12 px-1 py-0.5 bg-bambu-dark border border-bambu-dark-tertiary rounded text-white text-[length:var(--pc-t11,11px)] text-center focus:outline-none focus:border-bambu-green [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`}),(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] text-bambu-gray`,children:`°C`})]})]}),(0,K.jsx)(`input`,{type:`range`,min:35,max:t,value:tt,onChange:t=>nt(Math.min(e,Math.max(45,Number(t.target.value)))),className:`w-full h-1 accent-bambu-green cursor-pointer`}),(0,K.jsxs)(`div`,{className:`flex justify-between text-[length:var(--pc-t9,9px)] text-bambu-gray/50 mt-0.5`,children:[(0,K.jsx)(`span`,{children:`45°C`}),(0,K.jsxs)(`span`,{children:[e,`°C`]})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-1`,children:[(0,K.jsx)(`label`,{className:`text-[length:var(--pc-t10,10px)] text-white/70 font-medium`,children:P(`printers.drying.duration`)}),(0,K.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,K.jsx)(`input`,{type:`number`,min:1,max:24,value:rt,onChange:e=>it(Math.min(24,Math.max(1,Number(e.target.value)||1))),className:`w-10 px-1 py-0.5 bg-bambu-dark border border-bambu-dark-tertiary rounded text-white text-[length:var(--pc-t11,11px)] text-center focus:outline-none focus:border-bambu-green [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`}),(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] text-bambu-gray`,children:P(`printers.drying.hours`)})]})]}),(0,K.jsx)(`input`,{type:`range`,min:1,max:24,value:rt,onChange:e=>it(Number(e.target.value)),className:`w-full h-1 accent-bambu-green cursor-pointer`}),(0,K.jsxs)(`div`,{className:`flex justify-between text-[length:var(--pc-t9,9px)] text-bambu-gray/50 mt-0.5`,children:[(0,K.jsx)(`span`,{children:`1h`}),(0,K.jsx)(`span`,{children:`24h`})]})]}),(()=>{let e=((Je===null?void 0:cn.find(e=>e.id===Je))?.tray??[]).some(e=>e.state===11),t=at&&!e;return(0,K.jsx)(`button`,{type:`button`,onClick:()=>ot(e=>!e),"aria-pressed":t,disabled:e,title:e?P(`printers.drying.rotateUnavailableReason`):void 0,className:`h-8 w-full rounded-lg border px-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${t?`bg-bambu-green border-bambu-green text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary disabled:hover:bg-bambu-dark`}`,children:P(`printers.drying.rotateTray`)})})()]}),(0,K.jsx)(`div`,{className:`shrink-0 h-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`shrink-0 px-3 pt-2.5 pb-3`,children:(0,K.jsx)(`button`,{onClick:()=>{if(Je!==null){let e=(cn.find(e=>e.id===Je)?.tray??[]).some(e=>e.state===11);zn.mutate({amsId:Je,temp:tt,duration:rt,filament:Qe,rotateTray:at&&!e})}},disabled:zn.isPending,"data-testid":`drying-start-confirm`,className:`w-full py-1.5 bg-bambu-green hover:bg-bambu-green/80 text-white text-xs font-medium rounded-lg transition-colors disabled:opacity-50`,children:zn.isPending?P(`printers.drying.startingDrying`):P(`printers.drying.start`)})})]})]})})()]})}function WAe({onClose:e,onAdd:t,existingSerials:n}){let{t:r}=$e(),[i,a]=(0,y.useState)({name:``,serial_number:``,ip_address:``,access_code:``,model:``,location:``,auto_archive:!0}),[o,s]=(0,y.useState)(!1),[c,l]=(0,y.useState)([]),[u,d]=(0,y.useState)(``),[f,p]=(0,y.useState)(!1),[m,h]=(0,y.useState)(!1),[g,_]=(0,y.useState)([]),[v,b]=(0,y.useState)(``),[x,S]=(0,y.useState)(``),[C,w]=(0,y.useState)(!1),[T,E]=(0,y.useState)({scanned:0,total:0}),[D,O]=(0,y.useState)(!1),[k,A]=(0,y.useState)(!1),[j,M]=(0,y.useState)(null);(0,y.useEffect)(()=>{ud.getInfo().then(e=>{h(e.is_docker),e.subnets.length>0&&(_(e.subnets),b(e.subnets[0]))}).catch(()=>{});try{let e=localStorage.getItem(`bambuddy.discovery.customSubnet`);e&&S(e)}catch{}},[]);let N=c.filter(e=>!n.includes(e.serial)),P=async e=>{e.preventDefault(),A(!0);try{let e=await Q.diagnoseConnection({ip_address:i.ip_address.trim(),serial_number:i.serial_number.trim()||void 0,access_code:i.access_code||void 0});if(e.checks.some(e=>e.status===`fail`)){M(e);return}}catch{}finally{A(!1)}t(i)},F=async()=>{d(``),l([]),s(!0),p(!1),E({scanned:0,total:0});let e=C?x.trim():v,t=m||C;if(t&&C)try{localStorage.setItem(`bambuddy.discovery.customSubnet`,e)}catch{}try{if(t){await ud.startSubnetScan(e);let t=setInterval(async()=>{try{let e=await ud.getScanStatus();E({scanned:e.scanned,total:e.total}),l(await ud.getDiscoveredPrinters()),e.running||(clearInterval(t),s(!1),p(!0))}catch(e){console.error(`Failed to get scan status:`,e)}},500)}else{await ud.startDiscovery(10);let e=setInterval(async()=>{try{l(await ud.getDiscoveredPrinters())}catch(e){console.error(`Failed to get discovered printers:`,e)}},1e3);setTimeout(async()=>{clearInterval(e);try{await ud.stopDiscovery()}catch{}s(!1),p(!0);try{l(await ud.getDiscoveredPrinters())}catch(e){console.error(`Failed to get final discovered printers:`,e)}},1e4)}}catch(e){console.error(`Failed to start discovery:`,e),d(e instanceof Error?e.message:r(`printers.discovery.failedToStart`)),s(!1),p(!0)}},I=e=>{let t=e.serial.startsWith(`unknown-`)?``:e.serial;a({...i,name:e.name||``,serial_number:t,ip_address:e.ip_address,model:IW(e.model)}),l([])};return(0,y.useEffect)(()=>()=>{ud.stopDiscovery().catch(()=>{}),ud.stopSubnetScan().catch(()=>{})},[]),(0,y.useEffect)(()=>{let t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]),(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-start sm:items-center justify-center z-50 p-4 overflow-y-auto`,onClick:e,children:(0,K.jsx)(Dd,{className:`w-full max-w-md my-auto max-h-[calc(100vh-2rem)] overflow-y-auto`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{children:[(0,K.jsx)(`h2`,{className:`text-xl font-semibold mb-4`,children:r(`printers.addPrinter`)}),(0,K.jsxs)(`div`,{className:`mb-4 pb-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`mb-3`,children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.discovery.subnetToScan`)}),g.length>0?(0,K.jsxs)(`select`,{className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm`,value:C?`__custom__`:v,onChange:e=>{e.target.value===`__custom__`?w(!0):(w(!1),b(e.target.value))},disabled:o,children:[g.map(e=>(0,K.jsx)(`option`,{value:e,children:e},e)),(0,K.jsx)(`option`,{value:`__custom__`,children:r(`printers.discovery.customSubnetOption`)})]}):(0,K.jsx)(`input`,{type:`text`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm`,value:v,onChange:e=>b(e.target.value),placeholder:`192.168.1.0/24`,disabled:o}),C&&(0,K.jsx)(`input`,{type:`text`,"aria-label":r(`printers.discovery.customSubnetLabel`),className:`mt-2 w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm`,value:x,onChange:e=>S(e.target.value),placeholder:`10.1.1.0/24`,disabled:o}),(0,K.jsx)(`p`,{className:`mt-1 text-xs text-bambu-gray`,children:r(m?`printers.discovery.dockerNote`:`printers.discovery.customSubnetNote`)})]}),(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:F,disabled:o,className:`w-full`,children:o?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),(m||C)&&T.total>0?r(`printers.discovery.scanProgress`,{scanned:T.scanned,total:T.total}):r(`printers.discovery.scanning`)]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(Gl,{className:`w-4 h-4`}),r(m||C?`printers.discovery.scanSubnet`:`printers.discovery.discoverNetwork`)]})}),u&&(0,K.jsx)(`div`,{className:`mt-2 text-sm text-red-700 dark:text-red-400`,children:u}),N.length>0&&(0,K.jsx)(`div`,{className:`mt-3 space-y-2 max-h-40 overflow-y-auto`,children:N.map(e=>(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-2 bg-bambu-dark rounded-lg hover:bg-bambu-dark-secondary cursor-pointer transition-colors`,onClick:()=>I(e),children:[(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`font-medium text-white text-sm truncate`,children:e.name||e.serial}),(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray truncate`,children:[IW(e.model)||r(`printers.discovery.unknown`),` • `,e.ip_address,e.serial.startsWith(`unknown-`)&&(0,K.jsxs)(`span`,{className:`text-yellow-500`,children:[` • `,r(`printers.discovery.serialRequired`)]})]})]}),(0,K.jsx)(cs,{className:`w-4 h-4 text-bambu-gray -rotate-90 flex-shrink-0 ml-2`})]},e.serial))}),o&&(0,K.jsx)(`p`,{className:`mt-2 text-sm text-bambu-gray text-center`,children:r(m||C?`printers.discovery.scanningSubnet`:`printers.discovery.scanningNetwork`)}),f&&!o&&c.length===0&&(0,K.jsx)(`p`,{className:`mt-2 text-sm text-bambu-gray text-center`,children:r(m||C?`printers.discovery.noPrintersFoundSubnet`:`printers.discovery.noPrintersFoundNetwork`)}),f&&!o&&c.length>0&&N.length===0&&(0,K.jsx)(`p`,{className:`mt-2 text-sm text-bambu-gray text-center`,children:r(`printers.discovery.allConfigured`)})]}),(0,K.jsxs)(`form`,{onSubmit:P,className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.name`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.name,onChange:e=>a({...i,name:e.target.value}),placeholder:r(`printers.modal.myPrinter`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.ipAddress`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,pattern:`(\\d{1,3}(\\.\\d{1,3}){3}|[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*)`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.ip_address,onChange:e=>a({...i,ip_address:e.target.value}),placeholder:`192.168.1.100 or printer.local`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.serialNumber`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.serial_number,onChange:e=>a({...i,serial_number:e.target.value}),placeholder:`01P00A000000000`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.accessCode`)}),(0,K.jsx)(`input`,{type:`password`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.access_code,onChange:e=>a({...i,access_code:e.target.value}),placeholder:r(`printers.modal.fromPrinterSettings`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.modal.modelOptional`)}),(0,K.jsxs)(`select`,{className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.model||``,onChange:e=>a({...i,model:e.target.value}),children:[(0,K.jsx)(`option`,{value:``,children:r(`printers.modal.selectModel`)}),(0,K.jsxs)(`optgroup`,{label:`A1 Series`,children:[(0,K.jsx)(`option`,{value:`A1`,children:`A1`}),(0,K.jsx)(`option`,{value:`A1 Mini`,children:`A1 Mini`})]}),(0,K.jsx)(`optgroup`,{label:`A2 Series`,children:(0,K.jsx)(`option`,{value:`A2L`,children:`A2L`})}),(0,K.jsxs)(`optgroup`,{label:`H2 Series`,children:[(0,K.jsx)(`option`,{value:`H2C`,children:`H2C`}),(0,K.jsx)(`option`,{value:`H2D`,children:`H2D`}),(0,K.jsx)(`option`,{value:`H2D Pro`,children:`H2D Pro`}),(0,K.jsx)(`option`,{value:`H2S`,children:`H2S`})]}),(0,K.jsxs)(`optgroup`,{label:`P Series`,children:[(0,K.jsx)(`option`,{value:`P1P`,children:`P1P`}),(0,K.jsx)(`option`,{value:`P1S`,children:`P1S`}),(0,K.jsx)(`option`,{value:`P2S`,children:`P2S`})]}),(0,K.jsxs)(`optgroup`,{label:`X1 Series`,children:[(0,K.jsx)(`option`,{value:`X1`,children:`X1`}),(0,K.jsx)(`option`,{value:`X1C`,children:`X1 Carbon`}),(0,K.jsx)(`option`,{value:`X1E`,children:`X1E`})]}),(0,K.jsx)(`optgroup`,{label:`X2 Series`,children:(0,K.jsx)(`option`,{value:`X2D`,children:`X2D`})})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.modal.locationGroup`)}),(0,K.jsx)(`input`,{type:`text`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.location||``,onChange:e=>a({...i,location:e.target.value}),placeholder:r(`printers.modal.locationPlaceholder`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`printers.locationHelp`)})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`input`,{type:`checkbox`,id:`auto_archive`,checked:i.auto_archive,onChange:e=>a({...i,auto_archive:e.target.checked}),className:`rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green`}),(0,K.jsx)(`label`,{htmlFor:`auto_archive`,className:`text-sm text-bambu-gray`,children:r(`printers.modal.autoArchiveLabel`)})]}),(0,K.jsxs)(`button`,{type:`button`,onClick:()=>O(!0),disabled:!i.ip_address.trim(),className:`w-full flex items-center justify-center gap-2 px-3 py-2 text-sm text-bambu-gray hover:text-white disabled:opacity-40 disabled:cursor-not-allowed border border-bambu-dark-tertiary rounded-lg transition-colors`,children:[(0,K.jsx)(hu,{className:`w-4 h-4`}),r(`diagnostic.runButton`)]}),j?(0,K.jsxs)(`div`,{className:`rounded-lg bg-amber-50 dark:bg-amber-500/10 border border-amber-300 dark:border-amber-500/30 p-3 space-y-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,K.jsx)(Au,{className:`w-4 h-4 mt-0.5 flex-shrink-0 text-amber-600 dark:text-amber-400`}),(0,K.jsx)(`p`,{className:`text-sm text-amber-700 dark:text-amber-300`,children:r(`printers.addPreflight.warning`)})]}),(0,K.jsx)(kp,{result:j}),(0,K.jsxs)(`div`,{className:`flex gap-3`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:()=>M(null),className:`flex-1`,children:r(`printers.addPreflight.back`)}),(0,K.jsx)($,{type:`button`,onClick:()=>t(i),className:`flex-1`,children:r(`printers.addPreflight.saveAnyway`)})]})]}):(0,K.jsxs)(`div`,{className:`flex gap-3 pt-2`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:e,className:`flex-1`,children:r(`common.cancel`)}),(0,K.jsx)($,{type:`submit`,disabled:k,className:`flex-1`,children:r(k?`printers.addPreflight.checking`:`printers.addPrinter`)})]})]})]})})}),D&&(0,K.jsx)(jp,{connection:{ip_address:i.ip_address.trim(),serial_number:i.serial_number.trim()||void 0,access_code:i.access_code||void 0},printerName:i.name||null,onClose:()=>O(!1)})]})}function GAe({printer:e,firmwareInfo:t,onClose:n}){let{t:r}=$e(),i=ao(),{showToast:a}=Pd(),{hasPermission:o}=xd(),s=o(`firmware:update`),[c,l]=(0,y.useState)(null),[u,d]=(0,y.useState)(!1),[f,p]=(0,y.useState)(null),[m,h]=(0,y.useState)(t.update_available?t.latest_version:null),{data:g,isLoading:_}=q({queryKey:[`firmwarePrepare`,e.id,m],queryFn:()=>md.prepareUpload(e.id,m??void 0),staleTime:3e4,enabled:!!m&&s&&!u}),v=J({mutationFn:()=>md.startUpload(e.id,m??void 0),onSuccess:()=>{d(!0);let t=setInterval(async()=>{try{let n=await md.getUploadStatus(e.id);l(n),(n.status===`complete`||n.status===`error`)&&(clearInterval(t),p(null),d(!1),n.status===`complete`&&(a(r(`printers.firmwareModal.uploadedToast`),`success`),i.invalidateQueries({queryKey:[`firmwareUpdate`,e.id]})))}catch{}},2e3);p(t)},onError:e=>{a(r(`printers.firmwareModal.uploadFailed`,{error:e.message}),`error`),d(!1)}});return(0,y.useEffect)(()=>()=>{f&&clearInterval(f)},[f]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50`,children:(0,K.jsx)(Dd,{className:`w-full max-w-md mx-4`,children:(0,K.jsxs)(kd,{children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-3 mb-4`,children:[(0,K.jsx)(`div`,{className:`p-2 rounded-full ${t.update_available?`bg-orange-100 dark:bg-orange-500/20`:`bg-status-ok/20`}`,children:t.update_available?(0,K.jsx)(Gs,{className:`w-5 h-5 text-orange-600 dark:text-orange-400`}):(0,K.jsx)(gs,{className:`w-5 h-5 text-status-ok`})}),(0,K.jsxs)(`div`,{className:`flex-1`,children:[(0,K.jsx)(`h3`,{className:`text-lg font-semibold text-white`,children:t.update_available?r(`printers.firmwareModal.title`):r(`printers.firmwareModal.titleUpToDate`)}),(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mt-1`,children:e.name})]})]}),(()=>{let e=m?t.available_versions?.find(e=>e.version===m):null,n=m??t.latest_version,i=e?.release_notes??t.release_notes,a=!!n&&n!==t.current_version;return(0,K.jsxs)(`div`,{className:`bg-bambu-dark rounded-lg p-3 mb-4`,children:[(0,K.jsxs)(`div`,{className:`flex justify-between items-center text-sm`,children:[(0,K.jsx)(`span`,{className:`text-bambu-gray`,children:r(`printers.firmwareModal.currentVersion`)}),(0,K.jsx)(`span`,{className:`font-mono ${a?`text-white`:`text-status-ok`}`,children:t.current_version||r(`common.unknown`)})]}),a&&(0,K.jsxs)(`div`,{className:`flex justify-between items-center text-sm mt-1`,children:[(0,K.jsx)(`span`,{className:`text-bambu-gray`,children:r(`printers.firmwareModal.latestVersion`)}),(0,K.jsx)(`span`,{className:`text-orange-700 dark:text-orange-400 font-mono`,children:n})]}),i&&(0,K.jsxs)(`details`,{className:`mt-3 text-sm`,open:!a,children:[(0,K.jsx)(`summary`,{className:`cursor-pointer hover:underline ${a?`text-orange-700 dark:text-orange-400`:`text-status-ok`}`,children:r(`printers.firmwareModal.releaseNotes`)}),(0,K.jsx)(`div`,{className:`mt-2 text-bambu-gray text-xs max-h-40 overflow-y-auto whitespace-pre-wrap`,children:i})]},n??`none`)]})})(),t.available_versions&&t.available_versions.length>0&&!u&&c?.status!==`complete`&&(0,K.jsxs)(`div`,{className:`mb-4`,children:[(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray mb-2`,children:r(`printers.firmwareModal.availableVersions`)}),(0,K.jsx)(`div`,{className:`max-h-56 overflow-y-auto border border-bambu-dark-tertiary rounded-lg divide-y divide-bambu-dark-tertiary`,children:t.available_versions.map(e=>{let n=t.current_version===e.version,i=m===e.version,a=t.current_version?lee(e.version,t.current_version):0,o=r(n?`printers.firmwareModal.currentBadge`:a>0?`printers.firmwareModal.newerBadge`:`printers.firmwareModal.olderBadge`),c=n?`text-bambu-gray`:a>0?`text-orange-700 dark:text-orange-400`:`text-blue-700 dark:text-blue-400`;return(0,K.jsxs)(`button`,{type:`button`,disabled:!e.file_available||!s||n,onClick:()=>h(e.version),className:`w-full text-left px-3 py-2 text-sm flex items-center justify-between gap-2 transition-colors ${i?`bg-orange-50 dark:bg-orange-500/10`:`hover:bg-bambu-dark`} ${!e.file_available||!s||n?`opacity-60 cursor-not-allowed`:`cursor-pointer`}`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,K.jsx)(`span`,{className:`font-mono text-white`,children:e.version}),(0,K.jsx)(`span`,{className:`text-xs ${c}`,children:o})]}),(0,K.jsx)(`span`,{className:`text-xs px-2 py-0.5 rounded-full ${n?`bg-blue-50 dark:bg-blue-500/15 text-blue-700 dark:text-blue-400 border border-blue-300 dark:border-blue-500/30`:e.file_available?`bg-bambu-green/15 text-bambu-green border border-bambu-green/30`:`bg-bambu-gray/10 text-bambu-gray border border-bambu-gray/30`}`,children:n?r(`printers.firmwareModal.installed`):e.file_available?r(`printers.firmwareModal.usable`):r(`printers.firmwareModal.unavailable`)})]},e.version)})})]}),m?_?(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-bambu-gray text-sm mb-4`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),r(`printers.firmwareModal.checkingPrereqs`)]}):g&&!u&&!c?(0,K.jsx)(`div`,{className:`mb-4`,children:g.can_proceed?(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-bambu-green text-sm`,children:[(0,K.jsx)(qo,{className:`w-4 h-4`}),r(`printers.firmwareModal.sdCardReady`)]}):(0,K.jsx)(`div`,{className:`space-y-1`,children:g.errors.map((e,t)=>(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-red-700 dark:text-red-400 text-sm`,children:[(0,K.jsx)(ms,{className:`w-4 h-4 flex-shrink-0`}),e]},t))})}):null:null,(u||c)&&c&&(0,K.jsxs)(`div`,{className:`mb-4`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between text-sm mb-1`,children:[(0,K.jsx)(`span`,{className:`text-bambu-gray capitalize`,children:c.status}),(0,K.jsxs)(`span`,{className:`text-white`,children:[c.progress,`%`]})]}),(0,K.jsx)(`div`,{className:`w-full bg-bambu-dark-tertiary rounded-full h-2`,children:(0,K.jsx)(`div`,{className:`h-2 rounded-full transition-all ${c.status===`error`?`bg-status-error`:c.status===`complete`?`bg-status-ok`:`bg-orange-500`} ${c.status===`uploading`?`animate-pulse`:``}`,style:{width:`${c.progress}%`}})}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:c.message}),c.error&&(0,K.jsx)(`p`,{className:`text-xs text-red-700 dark:text-red-400 mt-1`,children:c.error})]}),c?.status===`complete`&&(0,K.jsxs)(`div`,{className:`bg-bambu-green/10 border border-bambu-green/30 rounded-lg p-3 mb-4`,children:[(0,K.jsx)(`p`,{className:`text-sm text-bambu-green font-medium mb-2`,children:r(`printers.firmwareModal.uploadedSuccess`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:r(`printers.firmwareModal.applyInstructions`)}),(0,K.jsxs)(`ol`,{className:`text-xs text-bambu-gray mt-1 list-decimal list-inside space-y-1`,children:[(0,K.jsx)(`li`,{dangerouslySetInnerHTML:{__html:r(`printers.firmwareModal.step1`)}}),(0,K.jsx)(`li`,{dangerouslySetInnerHTML:{__html:r(`printers.firmwareModal.step2`)}}),(0,K.jsx)(`li`,{dangerouslySetInnerHTML:{__html:r(`printers.firmwareModal.step3`)}}),(0,K.jsx)(`li`,{children:r(`printers.firmwareModal.step4`)})]})]}),(0,K.jsxs)(`div`,{className:`flex gap-2 justify-end`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:n,children:c?.status===`complete`?r(`printers.firmwareModal.done`):r(`common.cancel`)}),g?.can_proceed&&!u&&c?.status!==`complete`&&s&&(0,K.jsx)($,{onClick:()=>{l(null),v.mutate()},disabled:v.isPending,children:v.isPending?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin mr-2`}),r(`printers.firmwareModal.starting`)]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(Gs,{className:`w-4 h-4 mr-2`}),r(`printers.firmwareModal.uploadFirmware`)]})})]})]})})})}function KAe({printer:e,onClose:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)({name:e.name,ip_address:e.ip_address,access_code:``,model:e.model||``,location:e.location||``,auto_archive:e.auto_archive,is_active:e.is_active}),[s,c]=(0,y.useState)(!1),[l,u]=(0,y.useState)(null),d=J({mutationFn:t=>Q.updatePrinter(e.id,t),onSuccess:()=>{r.invalidateQueries({queryKey:[`printers`]}),r.invalidateQueries({queryKey:[`printerStatus`,e.id]}),t()},onError:e=>i(e.message||n(`printers.toast.failedToUpdate`),`error`)});(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let f=()=>{let e={name:a.name,ip_address:a.ip_address,model:a.model||void 0,location:a.location||void 0,auto_archive:a.auto_archive,is_active:a.is_active};a.access_code&&(e.access_code=a.access_code),d.mutate(e)};return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-start sm:items-center justify-center z-50 p-4 overflow-y-auto`,onClick:t,children:(0,K.jsx)(Dd,{className:`w-full max-w-md my-auto max-h-[calc(100vh-2rem)] overflow-y-auto`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{children:[(0,K.jsx)(`h2`,{className:`text-xl font-semibold mb-4`,children:n(`printers.editPrinter`)}),(0,K.jsxs)(`form`,{onSubmit:async t=>{t.preventDefault(),c(!0);try{let t=await Q.diagnoseConnection({ip_address:a.ip_address.trim(),serial_number:e.serial_number,access_code:a.access_code||void 0});if(t.checks.some(e=>e.status===`fail`)){u(t);return}}catch{}finally{c(!1)}f()},className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.name`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.name,onChange:e=>o({...a,name:e.target.value}),placeholder:n(`printers.modal.myPrinter`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.ipAddress`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,pattern:`(\\d{1,3}(\\.\\d{1,3}){3}|[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*)`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.ip_address,onChange:e=>o({...a,ip_address:e.target.value}),placeholder:`192.168.1.100 or printer.local`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.serialNumber`)}),(0,K.jsx)(`input`,{type:`text`,disabled:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-bambu-gray cursor-not-allowed`,value:e.serial_number}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:n(`printers.serialCannotBeChanged`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.accessCode`)}),(0,K.jsx)(`input`,{type:`password`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.access_code,onChange:e=>o({...a,access_code:e.target.value}),placeholder:n(`printers.accessCodePlaceholder`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.model`)}),(0,K.jsxs)(`select`,{className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.model,onChange:e=>o({...a,model:e.target.value}),children:[(0,K.jsx)(`option`,{value:``,children:n(`printers.modal.selectModel`)}),(0,K.jsxs)(`optgroup`,{label:`A1 Series`,children:[(0,K.jsx)(`option`,{value:`A1`,children:`A1`}),(0,K.jsx)(`option`,{value:`A1 Mini`,children:`A1 Mini`})]}),(0,K.jsx)(`optgroup`,{label:`A2 Series`,children:(0,K.jsx)(`option`,{value:`A2L`,children:`A2L`})}),(0,K.jsxs)(`optgroup`,{label:`H2 Series`,children:[(0,K.jsx)(`option`,{value:`H2C`,children:`H2C`}),(0,K.jsx)(`option`,{value:`H2D`,children:`H2D`}),(0,K.jsx)(`option`,{value:`H2D Pro`,children:`H2D Pro`}),(0,K.jsx)(`option`,{value:`H2S`,children:`H2S`})]}),(0,K.jsxs)(`optgroup`,{label:`P Series`,children:[(0,K.jsx)(`option`,{value:`P1P`,children:`P1P`}),(0,K.jsx)(`option`,{value:`P1S`,children:`P1S`}),(0,K.jsx)(`option`,{value:`P2S`,children:`P2S`})]}),(0,K.jsxs)(`optgroup`,{label:`X1 Series`,children:[(0,K.jsx)(`option`,{value:`X1`,children:`X1`}),(0,K.jsx)(`option`,{value:`X1C`,children:`X1 Carbon`}),(0,K.jsx)(`option`,{value:`X1E`,children:`X1E`})]}),(0,K.jsx)(`optgroup`,{label:`X2 Series`,children:(0,K.jsx)(`option`,{value:`X2D`,children:`X2D`})})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:`Location / Group`}),(0,K.jsx)(`input`,{type:`text`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.location,onChange:e=>o({...a,location:e.target.value}),placeholder:n(`printers.modal.locationPlaceholder`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:n(`printers.locationHelp`)})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`input`,{type:`checkbox`,id:`edit_auto_archive`,checked:a.auto_archive,onChange:e=>o({...a,auto_archive:e.target.checked}),className:`rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green`}),(0,K.jsx)(`label`,{htmlFor:`edit_auto_archive`,className:`text-sm text-bambu-gray`,children:n(`printers.modal.autoArchiveLabel`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`input`,{type:`checkbox`,id:`edit_maintenance_mode`,checked:!a.is_active,onChange:e=>o({...a,is_active:!e.target.checked}),className:`rounded border-bambu-dark-tertiary bg-bambu-dark text-amber-400 focus:ring-amber-400`}),(0,K.jsxs)(`label`,{htmlFor:`edit_maintenance_mode`,className:`text-sm text-bambu-gray flex items-center gap-1.5`,children:[(0,K.jsx)(qu,{className:`w-3.5 h-3.5 text-amber-600 dark:text-amber-400`}),n(`printers.maintenance.editFieldLabel`)]})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray/70 mt-1 ml-6`,children:n(`printers.maintenance.editFieldHelp`)})]}),l?(0,K.jsxs)(`div`,{className:`rounded-lg bg-amber-50 dark:bg-amber-500/10 border border-amber-300 dark:border-amber-500/30 p-3 space-y-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,K.jsx)(Au,{className:`w-4 h-4 mt-0.5 flex-shrink-0 text-amber-600 dark:text-amber-400`}),(0,K.jsx)(`p`,{className:`text-sm text-amber-700 dark:text-amber-300`,children:n(`printers.addPreflight.warning`)})]}),(0,K.jsx)(kp,{result:l}),(0,K.jsxs)(`div`,{className:`flex gap-3`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:()=>u(null),className:`flex-1`,children:n(`printers.addPreflight.back`)}),(0,K.jsx)($,{type:`button`,onClick:f,className:`flex-1`,disabled:d.isPending,children:n(`printers.addPreflight.saveAnyway`)})]})]}):(0,K.jsxs)(`div`,{className:`flex gap-3 pt-4`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:t,className:`flex-1`,children:n(`common.cancel`)}),(0,K.jsx)($,{type:`submit`,className:`flex-1`,disabled:d.isPending||s,children:s?n(`printers.addPreflight.checking`):d.isPending?n(`common.saving`):n(`printers.modal.saveChanges`)})]})]})]})})})}function qAe(e){let{data:t}=q({queryKey:[`printerStatus`,e],queryFn:()=>Q.getPrinterStatus(e),refetchInterval:3e4});return!t?.connected}function JAe({printer:e,plug:t,onPowerOn:n,isPowering:r}){let i=qAe(e.id),{data:a}=q({queryKey:[`smartPlugStatus`,t.id],queryFn:()=>Q.getSmartPlugStatus(t.id),refetchInterval:1e4});return i?(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 hover:bg-gray-100 dark:hover:bg-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,K.jsx)(`span`,{className:`text-sm text-white truncate`,children:e.name}),a&&(0,K.jsx)(`span`,{className:`text-xs px-1.5 py-0.5 rounded ${a.state===`ON`?`bg-bambu-green/20 text-bambu-green`:`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400`}`,children:a.state||`?`})]}),(0,K.jsxs)(`button`,{onClick:()=>n(t.id),disabled:r||a?.state===`ON`,className:`px-2 py-1 text-xs rounded transition-colors flex items-center gap-1 ${a?.state===`ON`?`bg-bambu-green/20 text-bambu-green cursor-default`:`bg-bambu-green/20 text-bambu-green hover:bg-bambu-green hover:text-white`}`,children:[(0,K.jsx)(jl,{className:`w-3 h-3`}),r?`...`:`On`]})]}):null}function YAe(){let{t:e}=$e(),{resolvedMode:t,darkAccent:n,lightAccent:r}=wd(),i={green:`bg-green-500 text-white hover:bg-green-400 border-green-400/60`,teal:`bg-teal-500 text-white hover:bg-teal-400 border-teal-400/60`,blue:`bg-blue-500 text-white hover:bg-blue-400 border-blue-400/60`,orange:`bg-orange-500 text-white hover:bg-orange-400 border-orange-400/60`,purple:`bg-purple-500 text-white hover:bg-purple-400 border-purple-400/60`,red:`bg-red-500 text-white hover:bg-red-400 border-red-400/60`}[t===`dark`?n:r],[a,o]=(0,y.useState)(!1),[s,c]=(0,y.useState)(()=>localStorage.getItem(`hideDisconnectedPrinters`)===`true`),[l,u]=(0,y.useState)(!1),[d,f]=(0,y.useState)(null),[p,m]=(0,y.useState)(()=>localStorage.getItem(`printerSortBy`)||`name`),[h,g]=(0,y.useState)(()=>localStorage.getItem(`printerSortAsc`)!==`false`),[_,v]=(0,y.useState)(()=>{let e=localStorage.getItem(`printerCardSize`);return e?parseInt(e,10):2}),[b,x]=(0,y.useState)(()=>localStorage.getItem(`printerPageView`)===`camwall`?`camwall`:`cards`),[S,C]=(0,y.useState)(()=>{let e=parseInt(localStorage.getItem(`camWallMaxLive`)||``,10);return Number.isFinite(e)&&e>0?e:4}),[w,T]=(0,y.useState)(()=>{let e=parseInt(localStorage.getItem(`camWallSnapshotSec`)||``,10);return Number.isFinite(e)&&e>0?e:8}),[E,D]=(0,y.useState)(()=>{let e=localStorage.getItem(`camWallStatusMode`);return e===`off`||e===`compact`||e===`full`?e:`full`}),O=_===1?`compact`:`expanded`,[k,A]=(0,y.useState)(null),j=(0,y.useCallback)(e=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{let t=document.getElementById(`printer-card-${e}`);if(!t)return;let n=document.querySelector(`header`)?.getBoundingClientRect().height??56,r=t.getBoundingClientRect().top+window.scrollY-n-16;window.scrollTo({top:Math.max(0,r),behavior:`smooth`})})})},[]),M=(0,y.useCallback)(e=>{A(e),v(2),localStorage.setItem(`printerCardSize`,`2`),j(e)},[j]),N=(0,y.useCallback)(()=>{let e=k;A(null),v(1),localStorage.setItem(`printerCardSize`,`1`),e!=null&&j(e)},[k,j]),[P,F]=(0,y.useState)(``),[I,L]=(0,y.useState)(`all`),[R,z]=(0,y.useState)(`all`),[B,V]=(0,y.useState)(0),[ee,te]=(0,y.useState)(()=>{try{let e=localStorage.getItem(`printerCollapsedSections`);return e?JSON.parse(e):{}}catch{return{}}}),H=ao(),{showToast:ne}=Pd(),{hasPermission:re}=xd(),[U,ie]=(0,y.useState)(()=>{let e=localStorage.getItem(`openEmbeddedCameras`);if(e)try{let t=JSON.parse(e);return new Map(t.map(e=>[e.id,e]))}catch{return new Map}return new Map});(0,y.useEffect)(()=>{let e=Array.from(U.values());e.length>0?localStorage.setItem(`openEmbeddedCameras`,JSON.stringify(e)):localStorage.removeItem(`openEmbeddedCameras`)},[U]);let{data:ae,isLoading:W}=q({queryKey:[`printers`],queryFn:Q.getPrinters}),{data:oe}=q({queryKey:[`ui-preferences`],queryFn:Q.getUiPreferences}),se=(0,y.useMemo)(()=>cm(oe?.nozzle_temp_presets,im,0,320),[oe?.nozzle_temp_presets]),ce=(0,y.useMemo)(()=>cm(oe?.bed_temp_presets,am,0,140),[oe?.bed_temp_presets]),le=(0,y.useMemo)(()=>cm(oe?.chamber_temp_presets,om,0,65),[oe?.chamber_temp_presets]),ue=(0,y.useMemo)(()=>cm(oe?.fan_speed_presets,sm,0,100),[oe?.fan_speed_presets]),de=(0,y.useMemo)(()=>{if(oe?.drying_presets)try{let e=JSON.parse(oe.drying_presets);if(typeof e==`object`&&e&&Object.keys(e).length>0)return{...RW,...e}}catch{}return RW},[oe?.drying_presets]);(0,y.useEffect)(()=>{oe?.camera_view_mode===`window`&&U.size>0&&ie(new Map)},[oe?.camera_view_mode,U.size]);let{data:fe}=q({queryKey:[`smart-plugs`],queryFn:Q.getSmartPlugs}),{data:pe}=q({queryKey:[`maintenanceOverview`],queryFn:Q.getMaintenanceOverview,staleTime:60*1e3}),{data:me}=q({queryKey:[`obico-printer-status`],queryFn:Q.getObicoPrinterStatus,refetchInterval:1e4}),he=(0,y.useCallback)(e=>me?.enabled===!0&&(me.monitored_printers===null||me.monitored_printers.includes(e)),[me]),{data:ge}=q({queryKey:[`spoolman-status`],queryFn:Q.getSpoolmanStatus,staleTime:60*1e3}),_e=ge?.enabled&&ge?.connected,{data:ve}=q({queryKey:[`spoolman-settings`],queryFn:Q.getSpoolmanSettings,enabled:!!_e,staleTime:60*1e3}),ye=ve?.spoolman_sync_mode,{data:be}=q({queryKey:[`unlinked-spools`],queryFn:Q.getUnlinkedSpools,enabled:!!_e,staleTime:30*1e3}),xe=be&&be.length>0,{data:Se}=q({queryKey:[`linked-spools`],queryFn:Q.getLinkedSpools,enabled:!!_e,staleTime:30*1e3}),Ce=Se?.linked,{data:we}=q({queryKey:[`spool-assignments`],queryFn:()=>Q.getAssignments(),enabled:re(`inventory:view_assignments`),staleTime:30*1e3}),Te=J({mutationFn:({printerId:e,amsId:t,trayId:n})=>Q.unassignSpool(e,t,n),onSuccess:()=>{H.invalidateQueries({queryKey:[`spool-assignments`]})}}),{data:Ee,isLoading:De}=q({queryKey:[`spoolman-inventory-spools`],queryFn:()=>Q.getSpoolmanInventorySpools(!1),enabled:!!_e,staleTime:30*1e3}),{data:Oe,isLoading:ke}=q({queryKey:[`spoolman-slot-assignments`],queryFn:()=>Q.getSpoolmanSlotAssignments(),enabled:!!_e,staleTime:30*1e3}),Ae=J({mutationFn:e=>Q.unassignSpoolmanSlot(e),onSuccess:()=>{H.invalidateQueries({queryKey:[`spoolman-inventory-spools`]}),H.invalidateQueries({queryKey:[`spoolman-slot-assignments`]})}}),je=(e,t,n)=>we?.find(r=>r.printer_id===e&&r.ams_id===Number(t)&&r.tray_id===Number(n)),Me=pe?.reduce((e,t)=>(e[t.printer_id]={due_count:t.due_count,warning_count:t.warning_count,total_print_hours:t.total_print_hours},e),{})||{},Ne=fe?.reduce((e,t)=>(t.printer_id&&(e[t.printer_id]=t),e),{})||{},Pe=J({mutationFn:Q.createPrinter,onSuccess:()=>{H.invalidateQueries({queryKey:[`printers`]}),H.invalidateQueries({queryKey:[`maintenanceOverview`]}),o(!1)},onError:t=>{if(t instanceof $u&&t.code===`printer_connection_failed`){ne(e(`printers.toast.connectionFailedNotAdded`),`error`);return}ne(t.message||e(`printers.toast.failedToAdd`),`error`)}}),Fe=J({mutationFn:e=>Q.controlSmartPlug(e,`on`),onSuccess:()=>{H.invalidateQueries({queryKey:[`smart-plugs`]}),f(null)},onError:()=>{f(null)}}),[Ie,Le]=(0,y.useState)(new Set),[Re,ze]=(0,y.useState)(!1),[Be,Ve]=(0,y.useState)(null),[He,Ue]=(0,y.useState)(!1),We=Re||Ie.size>0,Ge=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),Ke=(0,y.useCallback)(()=>{Le(new Set),ze(!1)},[]);(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&We&&Ke()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[We,Ke]);let qe=(0,y.useCallback)(async t=>{Ue(!0);let n=Array.from(Ie).filter(e=>{let n=H.getQueryData([`printerStatus`,e]);if(!n?.connected)return!1;switch(t){case`stop`:return n.state===`RUNNING`||n.state===`PAUSE`;case`pause`:return n.state===`RUNNING`;case`resume`:return n.state===`PAUSE`;case`clearPlate`:return!!n.awaiting_plate_clear;case`clearHMS`:return n.hms_errors&&pm(n.hms_errors).length>0;default:return!1}});if(n.length===0){ne(e(`printers.bulk.noneApplicable`),`error`),Ue(!1),Ve(null);return}let r={stop:Q.stopPrint,pause:Q.pausePrint,resume:Q.resumePrint,clearPlate:Q.clearPlate,clearHMS:Q.clearHMSErrors}[t],i=await Promise.allSettled(n.map(e=>r(e))),a=i.filter(e=>e.status===`fulfilled`).length,o=i.filter(e=>e.status===`rejected`).length;o===0?ne(e(`printers.bulk.success`,{action:e(`printers.bulk.actions.${t}`),count:a})):ne(e(`printers.bulk.partial`,{succeeded:a,failed:o}),`error`),n.forEach(e=>{H.invalidateQueries({queryKey:[`printerStatus`,e]})}),Ue(!1),Ve(null)},[Ie,H,ne,e]),Je=(0,y.useCallback)(e=>{e===`stop`||e===`pause`||e===`clearPlate`?Ve(e):qe(e)},[qe]),Ye=()=>{let e=!s;c(e),localStorage.setItem(`hideDisconnectedPrinters`,String(e))},Xe=e=>{m(e),localStorage.setItem(`printerSortBy`,e)},Ze=()=>{let e=!h;g(e),localStorage.setItem(`printerSortAsc`,String(e))},Qe=()=>{switch(_){case 1:return`grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5`;case 2:return`grid-cols-1 md:grid-cols-2 xl:grid-cols-3`;case 3:return`grid-cols-1 lg:grid-cols-2`;case 4:return`grid-cols-1`;default:return`grid-cols-1 md:grid-cols-2 xl:grid-cols-3`}},et=[`S`,`M`,`L`,`XL`];(0,y.useEffect)(()=>H.getQueryCache().subscribe(e=>{e.type===`updated`&&Array.isArray(e.query.queryKey)&&e.query.queryKey[0]===`printerStatus`&&V(e=>e+1)}),[H]);let tt=(0,y.useMemo)(()=>{if(!ae)return[];let e=ae;if(P.trim()){let t=P.trim().toLowerCase();e=e.filter(e=>e.name.toLowerCase().includes(t)||(e.model||``).toLowerCase().includes(t)||(e.location||``).toLowerCase().includes(t)||(e.serial_number||``).toLowerCase().includes(t))}return R!==`all`&&(e=e.filter(e=>(e.location||``)===R)),I!==`all`&&(e=e.filter(e=>{let t=H.getQueryData([`printerStatus`,e.id]);if(!t?.connected)return I===`offline`;let n=t.hms_errors?pm(t.hms_errors):[];switch(I){case`printing`:return t.state===`RUNNING`;case`paused`:return t.state===`PAUSE`;case`finished`:return t.state===`FINISH`;case`error`:return t.state===`FAILED`||n.length>0;case`idle`:return t.state!==`RUNNING`&&t.state!==`PAUSE`&&t.state!==`FINISH`&&t.state!==`FAILED`&&n.length===0;case`offline`:return!1;default:return!0}})),e},[ae,P,I,R,H,B]),nt=(0,y.useMemo)(()=>ae?[...new Set(ae.map(e=>e.location||``).filter(Boolean))].sort():[],[ae]),rt=(0,y.useMemo)(()=>{let e=[...tt];switch(p){case`name`:e.sort((e,t)=>e.name.localeCompare(t.name));break;case`model`:e.sort((e,t)=>(e.model||``).localeCompare(t.model||``));break;case`location`:e.sort((e,t)=>{let n=e.location||``,r=t.location||``;return!n&&r?1:n&&!r?-1:n.localeCompare(r)||e.name.localeCompare(t.name)});break;case`status`:e.sort((e,t)=>{let n=H.getQueryData([`printerStatus`,e.id]),r=H.getQueryData([`printerStatus`,t.id]),i=e=>e?.connected?(e.hms_errors?pm(e.hms_errors):[]).length>0?0:e.state===`RUNNING`?1:2:3;return i(n)-i(r)});break;case`eta`:e.sort((e,t)=>{let n=H.getQueryData([`printerStatus`,e.id]),r=H.getQueryData([`printerStatus`,t.id]),i=e=>e?.connected?e.state===`RUNNING`&&e.remaining_time!=null&&e.remaining_time>0?0:e.state===`RUNNING`?1:2:3,a=i(n),o=i(r);if(a!==o)return a-o;if(a===0){let e=(n.remaining_time??0)-(r.remaining_time??0);if(e!==0)return e}return e.name.localeCompare(t.name)});break}return h||e.reverse(),e},[tt,p,h,H]),it=(0,y.useCallback)(()=>{Le(new Set(rt.map(e=>e.id))),ze(!0)},[rt]),at=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return rt.forEach(t=>{FW(H.getQueryData([`printerStatus`,t.id]))===e&&n.add(t.id)}),n}),ze(!0)},[rt,H]),ot=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return rt.filter(t=>(t.location||``)===e).forEach(e=>n.add(e.id)),n}),ze(!0)},[rt]),st=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return rt.filter(t=>(t.model||`Unknown`)===e).forEach(e=>n.add(e.id)),n}),ze(!0)},[rt]),ct=(0,y.useCallback)(e=>{te(t=>{let n={...t,[e]:!t[e]};try{localStorage.setItem(`printerCollapsedSections`,JSON.stringify(n))}catch{}return n})},[]),lt=(0,y.useMemo)(()=>{if(p===`name`||p===`eta`)return null;let e={};return p===`location`?rt.forEach(t=>{let n=t.location||`Ungrouped`;e[n]||(e[n]=[]),e[n].push(t)}):p===`model`?rt.forEach(t=>{let n=t.model||`Unknown`;e[n]||(e[n]=[]),e[n].push(t)}):p===`status`&&rt.forEach(t=>{let n=FW(H.getQueryData([`printerStatus`,t.id]));e[n]||(e[n]=[]),e[n].push(t)}),e},[p,rt,H,B]),ut=(0,y.useRef)(null),dt=(0,y.useRef)(null),ft=(0,y.useRef)(0),[pt,mt]=(0,y.useState)(!1),ht=(0,y.useCallback)(()=>{let e=ut.current;if(!e)return;let t=dt.current?.offsetWidth;t&&(ft.current=t);let n=ft.current>0&&e.clientWidthe===n?e:n)},[]),gt=Object.keys(Ne).length;(0,y.useLayoutEffect)(()=>{ht();let e=ut.current;if(!e)return;if(typeof ResizeObserver>`u`)return window.addEventListener(`resize`,ht),()=>window.removeEventListener(`resize`,ht);let t=new ResizeObserver(()=>ht());return t.observe(e),window.addEventListener(`resize`,ht),()=>{t.disconnect(),window.removeEventListener(`resize`,ht)}},[ht,ae?.length,nt.length,s,gt]);let _t=(t=!1)=>(0,K.jsxs)(K.Fragment,{children:[ae&&ae.length>0&&(0,K.jsx)(AW,{value:I,onChange:L,fullWidth:t,options:[{value:`all`,label:e(`printers.filter.allStatuses`)},{value:`printing`,label:e(`printers.status.printing`)},{value:`paused`,label:e(`printers.status.paused`)},{value:`idle`,label:e(`printers.status.idle`)},{value:`finished`,label:e(`printers.status.finished`)},{value:`error`,label:e(`printers.status.error`)},{value:`offline`,label:e(`printers.status.offline`)}]}),ae&&ae.length>0&&nt.length>0&&(0,K.jsx)(AW,{value:R,onChange:z,fullWidth:t,options:[{value:`all`,label:e(`printers.filter.allLocations`)},...nt.map(e=>({value:e,label:e}))]}),(0,K.jsx)(`button`,{type:`button`,onClick:Ye,"aria-pressed":s,className:`h-8 px-2 rounded-lg border text-sm font-medium transition-colors ${t?`w-full`:``} ${s?`bg-bambu-green border-bambu-green text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary`}`,children:e(`printers.hideOffline`)})]}),vt=(t=!1)=>(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-1 ${t?`w-full`:``}`,children:[(0,K.jsx)(AW,{value:p,onChange:Xe,fullWidth:t,options:[{value:`name`,label:e(`printers.sort.name`)},{value:`status`,label:e(`printers.sort.status`)},{value:`model`,label:e(`printers.sort.model`)},{value:`location`,label:e(`printers.sort.location`)},{value:`eta`,label:e(`printers.sort.eta`)}]}),(0,K.jsx)(`button`,{onClick:Ze,className:`h-8 shrink-0 px-2 rounded-lg border bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary transition-colors flex items-center justify-center`,title:e(h?`printers.sort.descending`:`printers.sort.ascending`),children:h?(0,K.jsx)(zo,{className:`w-4 h-4 text-white`}):(0,K.jsx)(No,{className:`w-4 h-4 text-white`})})]}),(0,K.jsxs)(`div`,{className:`flex h-8 items-center bg-bambu-dark rounded-lg border border-bambu-dark-tertiary ${t?`w-full`:``}`,children:[(0,K.jsxs)(`button`,{type:`button`,onClick:()=>{x(`cards`),localStorage.setItem(`printerPageView`,`cards`)},className:`flex h-full items-center gap-1 rounded-l-lg px-2 text-xs font-medium transition-colors ${t?`flex-1 justify-center`:``} ${b===`cards`?`bg-bambu-green text-white`:`text-white hover:bg-bambu-dark-tertiary`}`,title:e(`printers.pageView.cards`),"aria-pressed":b===`cards`,children:[(0,K.jsx)(Uc,{className:`w-3.5 h-3.5`}),t&&(0,K.jsx)(`span`,{children:e(`printers.pageView.cards`)})]}),(0,K.jsxs)(`button`,{type:`button`,onClick:()=>{x(`camwall`),localStorage.setItem(`printerPageView`,`camwall`)},className:`flex h-full items-center gap-1 rounded-r-lg px-2 text-xs font-medium transition-colors ${t?`flex-1 justify-center`:``} ${b===`camwall`?`bg-bambu-green text-white`:`text-white hover:bg-bambu-dark-tertiary`}`,title:e(`printers.pageView.camWall`),"aria-pressed":b===`camwall`,disabled:!re(`camera:view`),children:[(0,K.jsx)(ul,{className:`w-3.5 h-3.5`}),t&&(0,K.jsx)(`span`,{children:e(`printers.pageView.camWall`)})]})]}),b===`camwall`&&re(`camera:view`)&&(0,K.jsxs)(Di,{to:`/camwall`,className:`flex h-8 items-center gap-1 rounded-lg border border-bambu-dark-tertiary bg-bambu-dark px-2 text-xs font-medium text-white transition-colors hover:bg-bambu-dark-tertiary ${t?`w-full justify-center`:``}`,title:e(`printers.pageView.openCamWallPage`),children:[(0,K.jsx)(Qs,{className:`w-3.5 h-3.5`}),t&&(0,K.jsx)(`span`,{children:e(`printers.pageView.openCamWallPage`)})]}),(0,K.jsx)(`div`,{className:`flex h-8 items-center bg-bambu-dark rounded-lg border border-bambu-dark-tertiary ${b===`camwall`?`opacity-40 pointer-events-none`:``} ${t?`w-full`:``}`,children:et.map((n,r)=>{let i=r+1,a=_===i;return(0,K.jsx)(`button`,{onClick:()=>{A(null),v(i),localStorage.setItem(`printerCardSize`,String(i))},className:`h-full px-2 text-xs font-medium transition-colors ${t?`flex-1`:``} ${r===0?`rounded-l-lg`:``} ${r===et.length-1?`rounded-r-lg`:``} ${a?`bg-bambu-green text-white`:`text-white hover:bg-bambu-dark-tertiary`}`,title:e(n===`S`?`printers.cardSize.small`:n===`M`?`printers.cardSize.medium`:n===`L`?`printers.cardSize.large`:`printers.cardSize.extraLarge`),children:n},n)})})]}),yt=(t=!1)=>(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`button`,{onClick:()=>{We?Ke():ze(!0)},className:`h-8 px-2 rounded-lg border transition-colors ${t?`w-full justify-center gap-1.5 text-sm font-medium flex items-center`:``} ${We?`bg-bambu-green border-bambu-green text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary`}`,title:e(`printers.bulk.select`),disabled:!re(`printers:control`),children:[(0,K.jsx)(du,{className:`w-4 h-4`}),t&&(0,K.jsx)(`span`,{children:e(`printers.bulk.select`)})]}),s&&Object.keys(Ne).length>0&&(0,K.jsxs)(`div`,{className:`relative ${t?`w-full`:``}`,children:[(0,K.jsxs)(`button`,{onClick:()=>u(!l),className:`h-8 flex items-center gap-1.5 px-2 text-sm rounded-lg border transition-colors ${t?`w-full justify-between bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary hover:text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary`}`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-1.5`,children:[(0,K.jsx)(jl,{className:`w-4 h-4`}),e(`printers.powerOn`)]}),(0,K.jsx)(cs,{className:`w-3 h-3 transition-transform ${l?`rotate-180`:``}`})]}),l&&(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`div`,{className:`fixed inset-0 z-10`,onClick:()=>u(!1)}),(0,K.jsxs)(`div`,{className:`absolute right-0 mt-2 w-56 bg-white dark:bg-bambu-dark-secondary border border-gray-200 dark:border-bambu-dark-tertiary rounded-lg shadow-lg z-20 py-1`,children:[(0,K.jsx)(`div`,{className:`px-3 py-2 text-xs text-gray-500 dark:text-bambu-gray border-b border-gray-200 dark:border-bambu-dark-tertiary`,children:e(`printers.offlinePrintersWithPlugs`)}),ae?.filter(e=>Ne[e.id]).map(e=>(0,K.jsx)(JAe,{printer:e,plug:Ne[e.id],onPowerOn:e=>{f(e),Fe.mutate(e)},isPowering:d===Ne[e.id]?.id},e.id)),ae?.filter(e=>Ne[e.id]).length===0&&(0,K.jsx)(`div`,{className:`px-3 py-2 text-sm text-bambu-gray`,children:`No printers with smart plugs`})]})]})]}),(0,K.jsxs)($,{onClick:()=>o(!0),disabled:!re(`printers:create`),title:re(`printers:create`)?void 0:e(`printers.permission.noAdd`),className:`!h-8 !min-h-8 px-2 py-0 ${t?`w-full`:``}`,children:[(0,K.jsx)(kl,{className:`w-4 h-4`}),e(`printers.addPrinter`)]})]});return(0,K.jsxs)(`div`,{className:`p-4 md:p-8`,children:[(0,K.jsxs)(`div`,{className:`space-y-3 mb-6`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`h1`,{className:`text-2xl font-bold text-white flex items-center gap-3`,children:[(0,K.jsx)(Ml,{className:`w-7 h-7 text-bambu-green`}),e(`printers.title`)]}),(0,K.jsx)(LAe,{printers:ae})]}),(0,K.jsxs)(`div`,{ref:ut,className:`relative flex items-center gap-2`,children:[ae&&ae.length>0&&(0,K.jsxs)(`div`,{className:`relative min-w-0 flex-1`,children:[(0,K.jsx)(Gl,{className:`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray/50`}),(0,K.jsx)(`input`,{type:`search`,name:`printer-search`,autoComplete:`off`,"data-1p-ignore":!0,"data-lpignore":`true`,value:P,onChange:e=>F(e.target.value),placeholder:e(`printers.search`),"aria-label":e(`printers.search`),className:`w-full h-8 pl-9 pr-8 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm placeholder:text-bambu-gray/50 focus:outline-none focus:border-bambu-green`}),P&&(0,K.jsx)(`button`,{type:`button`,"aria-label":e(`common.clear`),onClick:()=>F(``),className:`absolute right-3 top-1/2 -translate-y-1/2 text-bambu-gray hover:text-white`,children:(0,K.jsx)(Ju,{className:`w-4 h-4`})})]}),(0,K.jsxs)(`div`,{ref:dt,"aria-hidden":pt,inert:pt,className:`${pt?`absolute -left-[9999px] top-0 flex w-max pointer-events-none opacity-0`:`flex`} ml-auto items-center justify-end gap-2 flex-nowrap [&>*]:shrink-0`,children:[(0,K.jsx)(`div`,{className:`h-6 w-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`flex items-center gap-2`,children:_t()}),(0,K.jsx)(`div`,{className:`h-6 w-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`flex items-center gap-2`,children:vt()}),(0,K.jsx)(`div`,{className:`h-6 w-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`flex items-center gap-2`,children:yt()})]}),pt&&(0,K.jsxs)(`div`,{className:`ml-auto flex items-center justify-end gap-1`,children:[(0,K.jsx)(jW,{label:e(`printers.toolbar.filters`,`Filters`),icon:(0,K.jsx)(vc,{className:`w-4 h-4`}),children:(0,K.jsx)(`div`,{className:`flex w-48 flex-col gap-2`,children:_t(!0)})}),(0,K.jsx)(jW,{label:e(`printers.toolbar.view`,`View`),icon:(0,K.jsx)(au,{className:`w-4 h-4`}),children:(0,K.jsx)(`div`,{className:`flex w-48 flex-col gap-2`,children:vt(!0)})}),(0,K.jsx)(jW,{label:e(`printers.toolbar.actions`,`Actions`),icon:(0,K.jsx)(Ys,{className:`w-4 h-4`}),children:(0,K.jsx)(`div`,{className:`flex w-48 flex-col gap-2`,children:yt(!0)})})]})]})]}),W?(0,K.jsx)(`div`,{className:`text-center py-12 text-bambu-gray`,children:e(`common.loading`)}):ae?.length===0?(0,K.jsx)(Dd,{children:(0,K.jsxs)(kd,{className:`text-center py-12`,children:[(0,K.jsx)(`p`,{className:`text-bambu-gray mb-4`,children:e(`printers.noPrintersConfigured`)}),(0,K.jsxs)($,{onClick:()=>o(!0),disabled:!re(`printers:create`),title:re(`printers:create`)?void 0:e(`printers.permission.noAdd`),children:[(0,K.jsx)(kl,{className:`w-4 h-4`}),e(`printers.addPrinter`)]})]})}):rt.length===0&&(P.trim()||I!==`all`||R!==`all`)?(0,K.jsx)(Dd,{children:(0,K.jsx)(kd,{className:`text-center py-12`,children:(0,K.jsx)(`p`,{className:`text-bambu-gray`,children:e(`printers.noSearchResults`)})})}):b===`camwall`?(0,K.jsx)(LT,{printers:rt,maxLive:S,snapshotIntervalSec:w,onTileClick:(e,t)=>{if((oe?.camera_view_mode||`window`)===`embedded`)ie(n=>new Map(n).set(e,{id:e,name:t}));else{let t=localStorage.getItem(`cameraWindowState`),n=t?JSON.parse(t):{width:640,height:400},r=[`width=${n.width}`,`height=${n.height}`,n.left===void 0?``:`left=${n.left}`,n.top===void 0?``:`top=${n.top}`,`menubar=no,toolbar=no,location=no,status=no`].filter(Boolean).join(`,`);window.open(`/camera/${e}`,`camera-${e}`,r)}},statusMode:E,onChangeMaxLive:e=>{C(e),localStorage.setItem(`camWallMaxLive`,String(e))},onChangeSnapshotIntervalSec:e=>{T(e),localStorage.setItem(`camWallSnapshotSec`,String(e))},onChangeStatusMode:e=>{D(e),localStorage.setItem(`camWallStatusMode`,e)}}):lt?(0,K.jsx)(`div`,{className:`space-y-6`,children:(()=>{let e=p===`status`?zAe.filter(e=>lt[e]?.length>0):Object.keys(lt);return h?e:[...e].reverse()})().map(t=>{let n=lt[t],r=`${p}:${t}`,i=!ee[r],a=p===`status`&&PW[t]?.dot||`bg-bambu-green`,o=p===`status`?e(PW[t]?.labelKey||t):t;return(0,K.jsx)(Ip,{open:i,onToggle:()=>ct(r),summaryClassName:`py-1`,summary:(0,K.jsxs)(`h2`,{className:`text-lg font-semibold text-white flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`w-2 h-2 rounded-full ${a}`}),o,(0,K.jsxs)(`span`,{className:`text-sm font-normal text-bambu-gray`,children:[`(`,n.length,`)`]}),We&&(0,K.jsx)(`button`,{onClick:e=>{e.stopPropagation(),p===`location`?ot(t===`Ungrouped`?``:t):p===`status`?at(t):p===`model`&&st(t)},className:`text-xs text-bambu-green hover:text-bambu-green-light transition-colors ml-1`,children:e(`printers.bulk.selectAll`)})]}),children:(0,K.jsx)(`div`,{className:`grid gap-4 ${_>=3?`gap-6`:``} ${Qe()}`,children:n.map(e=>(0,K.jsx)(BW,{printer:e,hideIfDisconnected:s,maintenanceInfo:Me[e.id],viewMode:O,cardSize:_,amsThresholds:oe?{humidityGood:Number(oe.ams_humidity_good)||40,humidityFair:Number(oe.ams_humidity_fair)||60,tempGood:Number(oe.ams_temp_good)||28,tempFair:Number(oe.ams_temp_fair)||35}:void 0,spoolmanEnabled:_e,hasUnlinkedSpools:xe,linkedSpools:Ce,spoolmanUrl:ge?.url,spoolmanSyncMode:ye,onGetAssignment:je,onUnassignSpool:(e,t,n)=>Te.mutate({printerId:e,amsId:t,trayId:n}),spoolmanSpools:Ee,spoolmanSlotAssignments:Oe,spoolmanLoading:De||ke,onUnassignSpoolmanSpool:e=>Ae.mutate(e),timeFormat:oe?.time_format||`system`,cameraViewMode:oe?.camera_view_mode||`window`,onOpenEmbeddedCamera:(e,t)=>ie(n=>new Map(n).set(e,{id:e,name:t})),checkPrinterFirmware:oe?.check_printer_firmware!==!1,dryingPresets:de,nozzleTempPresets:se,bedTempPresets:ce,chamberTempPresets:le,fanSpeedPresets:ue,requirePlateClear:oe?.require_plate_clear===!0,selectionMode:We,isSelected:Ie.has(e.id),onToggleSelect:Ge,onOpenCompactCard:M,aiDetectionEnabled:he(e.id),aiDetection:me?.enabled?me.per_printer[String(e.id)]:void 0,aiLastError:me?.last_error??null},e.id))})},t)})}):(0,K.jsx)(`div`,{className:`grid gap-4 ${_>=3?`gap-6`:``} ${Qe()}`,children:rt.map(e=>(0,K.jsx)(BW,{printer:e,hideIfDisconnected:s,maintenanceInfo:Me[e.id],viewMode:O,cardSize:_,spoolmanEnabled:_e,hasUnlinkedSpools:xe,linkedSpools:Ce,spoolmanUrl:ge?.url,spoolmanSyncMode:ye,onGetAssignment:je,onUnassignSpool:(e,t,n)=>Te.mutate({printerId:e,amsId:t,trayId:n}),spoolmanSpools:Ee,spoolmanSlotAssignments:Oe,spoolmanLoading:De||ke,onUnassignSpoolmanSpool:e=>Ae.mutate(e),amsThresholds:oe?{humidityGood:Number(oe.ams_humidity_good)||40,humidityFair:Number(oe.ams_humidity_fair)||60,tempGood:Number(oe.ams_temp_good)||28,tempFair:Number(oe.ams_temp_fair)||35}:void 0,timeFormat:oe?.time_format||`system`,cameraViewMode:oe?.camera_view_mode||`window`,onOpenEmbeddedCamera:(e,t)=>ie(n=>new Map(n).set(e,{id:e,name:t})),checkPrinterFirmware:oe?.check_printer_firmware!==!1,dryingPresets:de,nozzleTempPresets:se,bedTempPresets:ce,chamberTempPresets:le,fanSpeedPresets:ue,requirePlateClear:oe?.require_plate_clear===!0,selectionMode:We,isSelected:Ie.has(e.id),onToggleSelect:Ge,onOpenCompactCard:M,aiDetectionEnabled:he(e.id),aiDetection:me?.enabled?me.per_printer[String(e.id)]:void 0,aiLastError:me?.last_error??null},e.id))}),_===2&&k!=null&&(0,K.jsxs)(`button`,{type:`button`,onClick:N,className:`fixed bottom-5 left-1/2 z-40 inline-flex -translate-x-1/2 items-center gap-2 rounded-full border px-4 py-2 text-sm font-medium shadow-xl transition-colors ${i}`,title:e(`common.back`,`Back`),children:[(0,K.jsx)(Po,{className:`w-4 h-4`}),e(`common.back`,`Back`)]}),a&&(0,K.jsx)(WAe,{onClose:()=>o(!1),onAdd:e=>Pe.mutate(e),existingSerials:ae?.map(e=>e.serial_number)||[]}),We&&ae&&(0,K.jsx)(bee,{selectedIds:Ie,printers:ae,onClose:Ke,onSelectAll:it,onSelectByLocation:ot,onSelectByState:at,onAction:Je,actionPending:He}),Be===`stop`&&(0,K.jsx)(Kd,{title:e(`printers.bulk.confirm.stopTitle`,{count:Ie.size}),message:e(`printers.bulk.confirm.stopMessage`,{count:Ie.size}),confirmText:e(`printers.bulk.confirm.stopButton`),variant:`danger`,isLoading:He,onConfirm:()=>qe(`stop`),onCancel:()=>Ve(null)}),Be===`pause`&&(0,K.jsx)(Kd,{title:e(`printers.bulk.confirm.pauseTitle`,{count:Ie.size}),message:e(`printers.bulk.confirm.pauseMessage`,{count:Ie.size}),confirmText:e(`printers.bulk.confirm.pauseButton`),isLoading:He,onConfirm:()=>qe(`pause`),onCancel:()=>Ve(null)}),Be===`clearPlate`&&(0,K.jsx)(Kd,{title:e(`printers.bulk.confirm.clearPlateTitle`,{count:Ie.size}),message:e(`printers.bulk.confirm.clearPlateMessage`,{count:Ie.size}),confirmText:e(`printers.bulk.confirm.clearPlateButton`),isLoading:He,onConfirm:()=>qe(`clearPlate`),onCancel:()=>Ve(null)}),Array.from(U.values()).map((e,t)=>(0,K.jsx)(Ile,{printerId:e.id,printerName:e.name,viewerIndex:t,onClose:()=>ie(t=>{let n=new Map(t);return n.delete(e.id),n})},e.id))]})}function XAe({title:e,message:t,subtitle:n,closeText:r,variant:i=`error`,onClose:a}){let{t:o}=$e(),s=r??o(`common.close`);return(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&a()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[a]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-[120]`,onClick:a,children:(0,K.jsx)(Dd,{className:`w-full max-w-md`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{className:`p-6`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-4`,children:[(0,K.jsx)(`div`,{className:`p-2 rounded-full bg-bambu-dark ${i===`warning`?`text-yellow-600 dark:text-yellow-400`:`text-red-600 dark:text-red-400`}`,children:(0,K.jsx)(Au,{className:`w-6 h-6`})}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsx)(`h3`,{className:`text-lg font-semibold text-white mb-1`,children:e}),n&&(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mb-2 truncate`,children:n}),(0,K.jsx)(`p`,{className:`text-bambu-gray text-sm whitespace-pre-line break-words`,children:t})]})]}),(0,K.jsx)(`div`,{className:`flex mt-6`,children:(0,K.jsx)($,{onClick:a,className:`flex-1`,children:s})})]})})})}var VW=(0,y.createContext)(null),ZAe=1500,QAe=1e3,HW=e=>`slice-job-${e}`;function UW(e){try{return decodeURIComponent(e)}catch{return e}}function $Ae(e){let t=Math.max(0,Math.floor(e));if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return n<60?`${n}m ${r}s`:`${Math.floor(n/60)}h ${n%60}m`}function eje({children:e}){let{t}=$e(),{showToast:n,showPersistentToast:r,dismissToast:i}=Pd(),a=ao(),[o,s]=(0,y.useState)([]),[c,l]=(0,y.useState)(null),u=(0,y.useRef)([]);u.current=o;let d=(0,y.useRef)(new Map),f=(0,y.useRef)(new Map),p=(0,y.useRef)(new Map),m=(0,y.useRef)(new Set),h=(0,y.useCallback)(e=>{let n=d.current.get(e.id);if(n==null)return;let i=(Date.now()-n)/1e3,a=f.current.get(e.id)??`pending`,o=$Ae(i),s=p.current.get(e.id)??null,c=s&&s.stage&&s.total_percent>0;if(a===`running`&&c){let n=UW(e.sourceName),i=s.stage,a=Math.min(100,Math.max(0,Math.round(s.total_percent))),c=typeof s.multi_plate_index==`number`&&typeof s.multi_plate_count==`number`&&s.multi_plate_count>1?t(`slice.runningWithProgressMultiPlate`,`Plate {{plateIndex}} of {{plateCount}} • {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,{plateIndex:s.multi_plate_index,plateCount:s.multi_plate_count,name:n,stage:i,percent:a,elapsed:o}):t(`slice.runningWithProgress`,`{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,{name:n,stage:i,percent:a,elapsed:o});r(HW(e.id),c,`loading`);return}let l=a===`pending`?`slice.queuedToast`:`slice.runningToast`,u=a===`pending`?`Queued: {{name}} — {{elapsed}}`:`Slicing {{name}} — {{elapsed}}`;r(HW(e.id),t(l,u,{name:UW(e.sourceName),elapsed:o}),`loading`)},[r,t]),g=(0,y.useCallback)((e,t,n)=>{s(r=>r.some(t=>t.id===e)?r:[...r,{id:e,kind:t,sourceName:n}]),m.current.delete(e),d.current.set(e,Date.now()),f.current.set(e,`pending`),p.current.set(e,null),h({id:e,kind:t,sourceName:n})},[h]),_=(0,y.useCallback)((e,r)=>{m.current.has(e.id)||(m.current.add(e.id),s(t=>t.filter(t=>t.id!==e.id)),d.current.delete(e.id),f.current.delete(e.id),p.current.delete(e.id),i(HW(e.id)),r.status===`completed`?n(t(`slice.completedToast`,`Sliced {{name}}`,{name:UW(e.sourceName)}),`success`):r.status===`failed`&&l({name:UW(e.sourceName),detail:r.error_detail||t(`slice.failed`)}),a.invalidateQueries({queryKey:[`library-files`]}),a.invalidateQueries({queryKey:[`archives`]}))},[i,a,n,t]);return(0,y.useEffect)(()=>{if(o.length===0)return;let e=!1,t=!1,n=setInterval(async()=>{if(!(e||t)){t=!0;try{let t=[...u.current];for(let n of t)try{let t=await Q.getSliceJob(n.id);if(e)return;f.current.set(n.id,t.status),t.progress&&p.current.set(n.id,t.progress),(t.status===`completed`||t.status===`failed`)&&_(n,t)}catch{}}finally{t=!1}}},ZAe);return()=>{e=!0,clearInterval(n)}},[o.length,_]),(0,y.useEffect)(()=>{if(o.length===0)return;let e=setInterval(()=>{for(let e of u.current)h(e)},QAe);return()=>clearInterval(e)},[o.length,h]),(0,K.jsxs)(VW.Provider,{value:{trackJob:g,activeJobs:o},children:[e,c&&(0,K.jsx)(XAe,{title:t(`slice.failedTitle`),subtitle:c.name,message:c.detail,onClose:()=>l(null)})]})}function WW(){let e=(0,y.useContext)(VW);if(!e)throw Error(`useSliceJobTracker must be used inside SliceJobTrackerProvider`);return e}function GW({plates:e,onSelect:t,onClose:n}){let{t:r}=$e();return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4`,onClick:n,children:(0,K.jsxs)(`div`,{className:`w-full max-w-3xl max-h-[85vh] flex flex-col rounded-lg bg-bambu-dark-secondary border border-bambu-dark-tertiary/60`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex-shrink-0 flex items-start justify-between gap-3 px-4 pt-4 pb-3 border-b border-bambu-dark-tertiary/40`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`h3`,{className:`text-white font-medium`,children:r(`archives.platePicker.title`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`archives.platePicker.hint`)})]}),(0,K.jsx)(`button`,{onClick:n,className:`flex-shrink-0 text-bambu-gray hover:text-white transition-colors`,"aria-label":r(`common.close`,`Close`),children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsx)(`div`,{className:`flex-1 overflow-y-auto p-4`,children:(0,K.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-2`,children:e.map(e=>(0,K.jsxs)(`button`,{type:`button`,onClick:()=>t(e.index),className:`flex items-center gap-2 p-2 rounded-lg border border-bambu-dark-tertiary bg-bambu-dark hover:border-bambu-gray transition-colors text-left`,children:[e.has_thumbnail&&e.thumbnail_url!=null?(0,K.jsx)(`img`,{src:od(e.thumbnail_url),alt:`Plate ${e.index}`,className:`w-12 h-12 rounded object-cover bg-bambu-dark-tertiary flex-shrink-0`}):(0,K.jsx)(`div`,{className:`w-12 h-12 rounded bg-bambu-dark-tertiary flex items-center justify-center flex-shrink-0`,children:(0,K.jsx)(Hc,{className:`w-5 h-5 text-bambu-gray`})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`text-sm text-white font-medium truncate`,children:e.name?`${r(`archives.platePicker.plateLabel`,{index:e.index})} — ${e.name}`:r(`archives.platePicker.plateLabel`,{index:e.index})}),(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray truncate`,children:[e.objects.length>0?e.objects.slice(0,3).join(`, `)+(e.objects.length>3?`…`:``):e.object_count!=null&&e.object_count>0?r(`archives.platePicker.objectCount`,{count:e.object_count}):`${e.filaments.length} filament${e.filaments.length===1?``:`s`}`,e.print_time_seconds==null?``:` • ${qf(e.print_time_seconds)}`]})]})]},e.index))})})]})})}var KW=[`local`,`orca_cloud`,`cloud`,`standard`],tje={local:1.75,orca_cloud:1.5,cloud:1,standard:.5};function qW(e,t){for(let n of KW){let r=e[n][t];if(r.length>0)return{source:r[0].source,id:r[0].id}}return null}function JW(e,t,n){return t?e[t.source][n].find(e=>e.id===t.id)??null:null}function YW(e,t,n){if(!n)return null;for(let r of KW){let i=e[r][t].find(e=>e.name===n);if(i)return{source:i.source,id:i.id}}return null}function nje(e,t,n,r){let i=YW(e,`process`,r);if(i){let r=JW(e,i,`process`);if(r&&SU(r,`process`,t,n)!==`mismatch`)return i}for(let r of[`match`,`unknown`])for(let i of KW)for(let a of e[i].process)if(SU(a,`process`,t,n)===r)return{source:a.source,id:a.id};return qW(e,`process`)}function rje(e,t,n,r){let i=t.type.trim().toUpperCase(),a=$f(t.color),o=null,s=null;for(let c of KW)for(let l of e[c].filament){let e=0,u=(l.filament_type??``).trim().toUpperCase(),d=$f(l.filament_colour??``);i&&u&&i===u&&(e+=10),a&&d&&(d===a?e+=5:ap(l.filament_colour??``,t.color)&&(e+=2)),e+=tje[c];let f={source:l.source,id:l.id};SU(l,`filament`,n,r)===`mismatch`?(s==null||e>s.score)&&(s={ref:f,score:e}):(o==null||e>o.score)&&(o={ref:f,score:e})}return o==null?s==null?qW(e,`filament`):s.ref:o.ref}function ije(e){return e?`${e.source}:${e.id}`:``}function aje(e){if(!e)return null;let t=e.indexOf(`:`);if(t<0)return null;let n=e.slice(0,t),r=e.slice(t+1);return n!==`orca_cloud`&&n!==`cloud`&&n!==`local`&&n!==`standard`?null:{source:n,id:r}}function oje({requestId:e,sourceName:t}){let{t:n}=$e(),{showPersistentToast:r,dismissToast:i}=Pd(),[a,o]=(0,y.useState)(0),[s,c]=(0,y.useState)(null),l=t;try{l=decodeURIComponent(t)}catch{}(0,y.useEffect)(()=>{let e=Date.now(),t=setInterval(()=>o(Math.floor((Date.now()-e)/1e3)),1e3);return()=>clearInterval(t)},[]),(0,y.useEffect)(()=>{let t=!1,n=setInterval(async()=>{if(t)return;let n=await Q.getPreviewSliceProgress(e);!t&&n&&c(n)},1e3);return()=>{t=!0,clearInterval(n)}},[e]);let u=`slice-preview-${e}`;(0,y.useEffect)(()=>{let e=s&&s.stage&&s.total_percent>0,t=sje(a);return e?r(u,n(`slice.previewWithProgress`,`Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,{name:l,stage:s.stage,percent:Math.min(100,Math.max(0,Math.round(s.total_percent))),elapsed:t}),`loading`):r(u,n(`slice.previewToast`,{name:l,elapsed:t}),`loading`),()=>{i(u)}},[a,s,l,r,i,n,u]);let d=s?.stage,f=s?.total_percent,p=d&&typeof f==`number`&&f>0?`${d} (${Math.min(100,Math.max(0,Math.round(f)))}%)`:n(`slice.analyzingPlateFilaments`);return(0,K.jsxs)(`div`,{className:`flex flex-col gap-1 text-bambu-gray text-sm py-2`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),p,(0,K.jsxs)(`span`,{className:`text-xs tabular-nums`,children:[a,`s`]})]}),a>=5&&(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray/70 pl-6`,children:n(`slice.analyzingPlateFilamentsHint`,`Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.`)})]})}function sje(e){let t=Math.max(0,Math.floor(e));if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return n<60?`${n}m ${r}s`:`${Math.floor(n/60)}h ${n%60}m`}function cje(e){return Array.isArray(e)?e.map(e=>String(e)).join(`, `):e==null?``:String(e)}function XW({source:e,onClose:t}){let{t:n}=$e(),{trackJob:r}=WW(),i=ao(),[a,o]=(0,y.useState)(null),[s,c]=(0,y.useState)(null),[l,u]=(0,y.useState)([]),[d,f]=(0,y.useState)(null),[p,m]=(0,y.useState)(null),[h,g]=(0,y.useState)(!1),[_,v]=(0,y.useState)(null),[b,x]=(0,y.useState)(!1),[S,C]=(0,y.useState)(!1),[w,T]=(0,y.useState)(!1),[E,D]=(0,y.useState)(new Set),[O,k]=(0,y.useState)(!1),A=q({queryKey:[`slicer-pipelines`],queryFn:()=>Q.listSlicerPipelines(),staleTime:6e4}),[j,M]=(0,y.useState)(!1),[N,P]=(0,y.useState)(``),{showToast:F}=Pd(),I=J({mutationFn:e=>Q.createSlicerPipeline(e),onSuccess:()=>{i.invalidateQueries({queryKey:[`slicer-pipelines`]}),F(n(`slice.pipelines.toast.saved`,`Pipeline saved`),`success`),M(!1),P(``)},onError:e=>{F(e.message||n(`slice.pipelines.toast.saveFailed`,`Save failed`),`error`)}}),L=q({queryKey:[`slicePlates`,e.kind,e.id],queryFn:async()=>e.kind===`libraryFile`?Q.getLibraryFilePlates(e.id):Q.getArchivePlates(e.id),staleTime:6e4}),R=!!L.data?.is_multi_plate&&(L.data?.plates?.length??0)>1,z=R&&p==null,B=p??1,V=(0,y.useMemo)(()=>{let t=typeof crypto<`u`&&`randomUUID`in crypto?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2)}`;return`${e.kind}-${e.id}-p${B}-${t}`},[e.kind,e.id,B]),ee=q({queryKey:[`sliceFilamentReqs`,e.kind,e.id,B],queryFn:async()=>e.kind===`libraryFile`?Q.getLibraryFileFilamentRequirements(e.id,B,V,!0):Q.getArchiveFilamentRequirements(e.id,B,V,!0),enabled:!z,staleTime:6e4}),te=(0,y.useMemo)(()=>{let e=ee.data?.filaments??[],t=e.length>0?e:[{slot_id:1,type:``,color:``,used_grams:0,used_meters:0}];return h?t.map(e=>({...e,used_in_plate:!0})):t},[h,ee.data]),H=q({queryKey:[`slicerPresets`],queryFn:()=>Q.getSlicerPresets(),staleTime:6e4,enabled:!L.isLoading&&!z}),[ne,re]=(0,y.useState)(!1),U=async()=>{if(!ne){re(!0);try{let e=await Q.getSlicerPresets({refresh:!0});i.setQueryData([`slicerPresets`],e)}catch{i.invalidateQueries({queryKey:[`slicerPresets`]})}finally{re(!1)}}},ie=q({queryKey:[`slicerPrinterModels`],queryFn:Q.getSlicerPrinterModels,staleTime:1/0}),ae=(0,y.useMemo)(()=>!H.data||!a?null:JW(H.data,a,`printer`)?.name??null,[H.data,a]),W=(0,y.useMemo)(()=>_U(ie.data??{}),[ie.data]),oe=L.data?.embedded_printer??null,se=(0,y.useMemo)(()=>L.data?.design_overrides??[],[L.data]),ce=L.data?.embedded_process??null,le=(0,y.useMemo)(()=>{if(!oe||!ce||!ae)return!1;let e=e=>e.replace(/^#\s*/,``).trim().toLowerCase();return e(ae)===e(oe)},[oe,ce,ae]);(0,y.useEffect)(()=>{le||x(!1)},[le]),(0,y.useEffect)(()=>{D(new Set(se.filter(e=>!e.printer_coupled).map(e=>e.key)))},[se]),(0,y.useEffect)(()=>{let e=H.data;e&&(a??o(YW(e,`printer`,oe)??qW(e,`printer`)))},[H.data,oe]),(0,y.useEffect)(()=>{let e=H.data;e&&c(t=>{if(t){let n=JW(e,t,`process`);if(n&&SU(n,`process`,ae,W)!==`mismatch`)return t}return nje(e,ae,W,ce)})},[H.data,ae,W,ce]),(0,y.useEffect)(()=>{let e=H.data;e&&u(t=>te.map((n,r)=>{let i=t[r]??null;if(i){let t=JW(e,i,`filament`);if(t&&SU(t,`filament`,ae,W)!==`mismatch`)return i}return rje(e,{type:n.type,color:n.color},ae,W)}))},[H.data,te,ae,W]);let ue=J({mutationFn:async t=>{let n=de(t);return e.kind===`libraryFile`?Q.sliceLibraryFile(e.id,n):Q.sliceArchive(e.id,n)},onSuccess:n=>{r(n.job_id,e.kind,e.filename),t()},onError:e=>{f(e instanceof Error?e.message:String(e))}});function de(e){if(!a||!s||l.length===0||l.some(e=>e==null))throw Error(n(`slice.allPresetsRequired`));return{printer_preset:a,process_preset:s,filament_preset:l[0],filament_presets:l,...e==null?{}:{plate:e},..._==null?{}:{bed_type:_},...b&&le?{use_embedded_settings:!0}:{},...!b&&E.size>0?{design_overrides:[...E]}:{},...S?{auto_orient:!0}:{},...w?{auto_arrange:!0}:{}}}let fe=a!=null&&s!=null&&ee.isSuccess&&l.length>0&&l.every(e=>e!=null),pe=ue.isPending,me=L.data?.plates?.length??0,he=R&&me>1&&!z;return z&&L.data?(0,K.jsx)(GW,{plates:L.data.plates,onSelect:e=>m(e),onClose:t}):(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4`,onClick:()=>{pe||t()},children:(0,K.jsxs)(`div`,{className:`w-full max-w-xl max-h-[85vh] flex flex-col rounded-lg bg-bambu-dark-secondary border border-bambu-dark-tertiary/60`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex-shrink-0 flex items-start justify-between gap-3 px-4 pt-4 pb-3 border-b border-bambu-dark-tertiary/40`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsxs)(`h3`,{className:`text-white font-medium flex items-center gap-2`,children:[(0,K.jsx)(Ns,{className:`w-4 h-4`}),n(`slice.title`)]}),(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray mt-1 truncate`,title:e.filename,children:[e.filename,p==null?``:` • ${n(`archives.platePicker.plateLabel`,{index:p})}`]})]}),(0,K.jsx)(`button`,{onClick:t,disabled:pe,className:`flex-shrink-0 text-bambu-gray hover:text-white transition-colors disabled:opacity-50`,"aria-label":n(`common.close`),children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-4`,children:[(L.isLoading||H.isLoading)&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-bambu-gray text-sm`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),n(`slice.loadingPresets`)]}),H.isError&&(0,K.jsx)(`div`,{className:`text-sm text-red-700 dark:text-red-400`,role:`alert`,children:n(`slice.presetsLoadFailed`,`Failed to load presets. Open Settings → Profiles to import them, or sign in to Bambu Cloud.`)}),H.data&&(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,K.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,K.jsx)(ZW,{status:H.data.cloud_status,cloudName:`bambu`}),(0,K.jsx)(ZW,{status:H.data.orca_cloud_status,cloudName:`orca`})]}),(0,K.jsxs)(`button`,{type:`button`,onClick:U,disabled:ne||pe,className:`flex-shrink-0 inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs text-bambu-gray hover:text-white hover:bg-bambu-dark-tertiary/40 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,title:n(`slice.refreshPresetsTitle`),"aria-label":n(`slice.refreshPresets`),children:[(0,K.jsx)(Fl,{className:`w-3.5 h-3.5 ${ne?`animate-spin`:``}`}),n(`slice.refreshPresets`)]})]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 px-2 py-1.5 rounded-md bg-bambu-dark/40 border border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`span`,{className:`text-xs font-medium text-bambu-gray flex items-center gap-1`,children:[(0,K.jsx)(Ns,{className:`w-3.5 h-3.5`}),` `,n(`slice.pipelines.label`,`Pipeline`)]}),(0,K.jsxs)(`select`,{value:``,disabled:pe||(A.data?.pipelines.length??0)===0,onChange:e=>{let t=parseInt(e.target.value,10);if(Number.isNaN(t))return;let r=A.data?.pipelines.find(e=>e.id===t);r&&(o(r.printer_preset),c(r.process_preset),v(r.bed_type),u(e=>{let t=e.length>0?[...e]:r.filament_presets.map(()=>null);for(let e=0;e(0,K.jsx)(`option`,{value:e.id,children:e.name},e.id))]}),j?(0,K.jsxs)(`div`,{className:`flex items-center gap-1 flex-1 min-w-[16ch]`,children:[(0,K.jsx)(`input`,{autoFocus:!0,value:N,onChange:e=>P(e.target.value),placeholder:n(`slice.pipelines.namePlaceholder`,`Pipeline name`),"aria-label":n(`slice.pipelines.nameAria`,`New pipeline name`),className:`flex-1 text-xs px-2 py-1 bg-bambu-dark border border-bambu-dark-tertiary rounded text-white`}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>{let e=N.trim();if(!e||!a||!s)return;let t=l.filter(e=>e!==null);t.length!==0&&I.mutate({name:e,printer_preset:a,process_preset:s,filament_presets:t,bed_type:_})},disabled:I.isPending||!N.trim(),className:`text-xs px-2 py-1 bg-bambu-green hover:bg-bambu-green/80 text-white rounded disabled:opacity-50`,children:I.isPending?(0,K.jsx)(X,{className:`w-3 h-3 animate-spin`}):n(`common.save`,`Save`)}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>{M(!1),P(``)},className:`text-xs px-2 py-1 text-bambu-gray hover:text-white`,children:n(`common.cancel`,`Cancel`)})]}):(0,K.jsx)(`button`,{type:`button`,onClick:()=>{P(``),M(!0)},disabled:pe||!a||!s||l.length===0||l.some(e=>e===null),className:`text-xs px-2 py-1 bg-bambu-green/20 hover:bg-bambu-green/30 text-bambu-green border border-bambu-green/40 rounded disabled:opacity-50 disabled:cursor-not-allowed`,title:n(`slice.pipelines.saveTitle`,`Save the current four-slot selection as a reusable pipeline`),children:n(`slice.pipelines.saveButton`,`Save as pipeline`)})]}),(0,K.jsx)(QW,{label:n(`slice.printer`),slot:`printer`,data:H.data,value:a,onChange:o,disabled:pe||b}),le&&(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-sm text-bambu-gray cursor-pointer select-none`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:b,onChange:e=>x(e.target.checked),disabled:pe,className:`mt-0.5 cursor-pointer`}),(0,K.jsxs)(`span`,{children:[n(`slice.useEmbedded`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.useEmbeddedHint`)})]})]}),(0,K.jsx)(QW,{label:n(`slice.process`),slot:`process`,data:H.data,value:s,onChange:c,disabled:pe||b,selectedPrinterName:ae,compatIndex:W}),se.length>0&&(0,K.jsxs)(`div`,{className:`rounded-lg border border-bambu-dark-tertiary bg-bambu-dark/40 p-3`,children:[(0,K.jsxs)(`button`,{type:`button`,onClick:()=>k(e=>!e),className:`flex w-full items-center justify-between gap-2 text-left`,children:[(0,K.jsxs)(`span`,{className:`text-sm text-white`,children:[n(`slice.designSettings`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.designSettingsHint`,{count:se.length})})]}),(0,K.jsx)(`span`,{className:`shrink-0 text-xs text-bambu-gray`,children:n(`slice.designSettingsSelected`,{selected:E.size,total:se.length})})]}),O&&(0,K.jsx)(`div`,{className:`mt-3 space-y-1.5 border-t border-bambu-dark-tertiary pt-3`,children:se.map(e=>(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-xs ${b?`opacity-50`:`cursor-pointer`}`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:E.has(e.key),disabled:pe||b,onChange:t=>{D(n=>{let r=new Set(n);return t.target.checked?r.add(e.key):r.delete(e.key),r})},className:`mt-0.5 shrink-0 cursor-pointer`}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`span`,{className:`font-mono text-bambu-gray`,children:e.key}),(0,K.jsx)(`span`,{className:`ml-1.5 break-all text-white`,children:cje(e.value)}),e.printer_coupled&&(0,K.jsx)(`span`,{className:`ml-1.5 rounded bg-amber-100 px-1 py-0.5 text-[10px] text-amber-700 dark:bg-amber-500/20 dark:text-amber-400`,title:n(`slice.designSettingsPrinterCoupledHint`),children:n(`slice.designSettingsPrinterCoupled`)})]})]},e.key))})]}),(0,K.jsx)(uje,{value:_,onChange:v,disabled:pe||b}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-sm text-bambu-gray cursor-pointer select-none`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:S,onChange:e=>C(e.target.checked),disabled:pe,className:`mt-0.5 cursor-pointer`}),(0,K.jsxs)(`span`,{children:[n(`slice.autoOrient`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.autoOrientHint`)})]})]}),(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-sm text-bambu-gray cursor-pointer select-none`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:w,onChange:e=>T(e.target.checked),disabled:pe,className:`mt-0.5 cursor-pointer`}),(0,K.jsxs)(`span`,{children:[n(`slice.autoArrange`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.autoArrangeHint`)})]})]})]}),ee.isLoading?(0,K.jsx)(oje,{requestId:V,sourceName:e.filename}):te.map((e,t)=>{let r=e.used_in_plate!==!1,i=te.length>1?n(`slice.filamentSlot`,{index:t+1,type:e.type}):n(`slice.filament`);return(0,K.jsx)(QW,{label:r?i:`${i} ${n(`slice.notUsedByPlate`)}`,slot:`filament`,data:H.data,value:l[t]??null,onChange:e=>u(n=>{let r=n.length===te.length?[...n]:te.map((e,t)=>n[t]??null);return r[t]=e,r}),disabled:pe||!r||b,swatchColor:te.length>1?e.color:void 0,selectedPrinterName:ae,compatIndex:W},`filament-${t}`)})]}),d&&(0,K.jsx)(`div`,{className:`text-sm text-red-700 dark:text-red-400 bg-red-900/20 border border-red-900/40 rounded p-2`,role:`alert`,children:d})]}),(0,K.jsxs)(`div`,{className:`flex-shrink-0 flex justify-end gap-2 px-4 py-3 border-t border-bambu-dark-tertiary/40`,children:[(0,K.jsx)(`button`,{type:`button`,onClick:t,disabled:pe,className:`px-3 py-1.5 text-sm rounded-md border border-bambu-dark-tertiary text-bambu-gray hover:text-white hover:border-bambu-gray transition-colors disabled:opacity-50`,children:n(`common.cancel`)}),he&&(0,K.jsxs)(`label`,{className:`flex items-center gap-2 mr-auto text-sm text-bambu-gray cursor-pointer select-none`,title:n(`slice.actionAllTitle`,{count:me}),children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:h,onChange:e=>g(e.target.checked),disabled:pe,className:`cursor-pointer`}),n(`slice.allPlatesToggle`,{count:me})]}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>{f(null);let e=h?0:p;ue.mutate(e)},disabled:!fe||pe,className:`px-3 py-1.5 text-sm rounded-md bg-bambu-green hover:bg-bambu-green/90 text-bambu-dark font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2`,children:pe?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),n(`slice.enqueuing`)]}):h?n(`slice.actionAll`,{count:me}):n(`slice.action`)})]})]})})}function ZW({status:e,cloudName:t=`bambu`}){let{t:n}=$e();if(e===`ok`||e===`not_authenticated`)return null;let r=t===`orca`?{expired:{key:`slice.orcaCloud.expired`,fallback:`Orca Cloud session expired — sign in again to refresh your Orca presets.`},unreachable:{key:`slice.orcaCloud.unreachable`,fallback:`Orca Cloud is unreachable right now. Other presets still work.`}}:{expired:{key:`slice.cloud.expired`,fallback:`Bambu Cloud session expired — sign in again to refresh your cloud presets.`},unreachable:{key:`slice.cloud.unreachable`,fallback:`Bambu Cloud is unreachable right now. Local and standard presets still work.`}},{tone:i,icon:a}={expired:{tone:`border-amber-300 dark:border-amber-700/40 bg-amber-50 dark:bg-amber-900/20 text-amber-800 dark:text-amber-200`,icon:Es},unreachable:{tone:`border-bambu-dark-tertiary/40 bg-bambu-dark text-bambu-gray`,icon:Es}}[e],{key:o,fallback:s}=r[e];return(0,K.jsxs)(`div`,{className:`flex items-start gap-2 text-xs rounded-md border p-2 ${i}`,role:`status`,children:[(0,K.jsx)(a,{className:`w-4 h-4 flex-shrink-0 mt-0.5`}),(0,K.jsx)(`span`,{children:n(o,s)})]})}var lje=[{value:`Cool Plate`,labelKey:`slice.bedType.coolPlate`,fallback:`Cool Plate`},{value:`Cool Plate (SuperTack)`,labelKey:`slice.bedType.coolPlateSuperTack`,fallback:`Cool Plate SuperTack`},{value:`Engineering Plate`,labelKey:`slice.bedType.engineering`,fallback:`Engineering Plate`},{value:`High Temp Plate`,labelKey:`slice.bedType.highTemp`,fallback:`High Temp Plate`},{value:`Textured PEI Plate`,labelKey:`slice.bedType.texturedPEI`,fallback:`Textured PEI Plate`},{value:`Smooth PEI Plate`,labelKey:`slice.bedType.smoothPEI`,fallback:`Smooth PEI Plate`}];function uje({value:e,onChange:t,disabled:n}){let{t:r}=$e();return(0,K.jsxs)(`label`,{className:`block`,children:[(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray mb-1`,children:r(`slice.bedType.label`)}),(0,K.jsxs)(`select`,{value:e??``,onChange:e=>t(e.target.value===``?null:e.target.value),disabled:n,className:`w-full px-3 py-2 rounded-md bg-bambu-dark border border-bambu-dark-tertiary text-white text-sm focus:outline-none focus:border-bambu-gray disabled:opacity-50`,children:[(0,K.jsx)(`option`,{value:``,children:r(`slice.bedType.auto`)}),lje.map(e=>(0,K.jsx)(`option`,{value:e.value,children:r(e.labelKey,e.fallback)},e.value))]})]})}function QW({label:e,slot:t,data:n,value:r,onChange:i,disabled:a,swatchColor:o,selectedPrinterName:s,compatIndex:c}){let{t:l}=$e(),{sections:u,otherEntries:d}=(0,y.useMemo)(()=>{let e=[{key:`local`,label:`slice.tier.local`,fallback:`Imported`},{key:`orca_cloud`,label:`slice.tier.orcaCloud`,fallback:`Orca Cloud`},{key:`cloud`,label:`slice.tier.cloud`,fallback:`Bambu Cloud`},{key:`standard`,label:`slice.tier.standard`,fallback:`Standard`}],r=t!==`printer`,i=[],a=[];for(let{key:o,label:u,fallback:d}of e){let e=n[o][t];if(!r){e.length>0&&i.push({tierLabel:l(u,d),entries:e});continue}let f=[];for(let n of e)SU(n,t,s??null,c??Uke)===`mismatch`?a.push(n):f.push(n);f.length>0&&i.push({tierLabel:l(u,d),entries:f})}return{sections:i,otherEntries:a}},[n,t,l,s,c]),f=u.reduce((e,t)=>e+t.entries.length,0)+d.length;return(0,K.jsxs)(`label`,{className:`block`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2 text-xs text-bambu-gray mb-1`,children:[o&&(0,K.jsx)(`span`,{className:`inline-block w-3 h-3 rounded-full border border-bambu-dark-tertiary`,style:{backgroundColor:o||`transparent`},"aria-hidden":!0}),(0,K.jsx)(`span`,{children:e})]}),(0,K.jsxs)(`select`,{value:ije(r),onChange:e=>i(aje(e.target.value)),disabled:a||f===0,className:`w-full px-3 py-2 rounded-md bg-bambu-dark border border-bambu-dark-tertiary text-white text-sm focus:outline-none focus:border-bambu-gray disabled:opacity-50`,children:[(0,K.jsx)(`option`,{value:``,children:l(f===0?`slice.noPresetsForSlot`:`slice.selectPreset`)}),u.map(e=>(0,K.jsx)(`optgroup`,{label:e.tierLabel,children:e.entries.map(e=>(0,K.jsx)(`option`,{value:`${e.source}:${e.id}`,children:e.name},`${e.source}:${e.id}`))},e.tierLabel)),d.length>0&&(0,K.jsx)(`optgroup`,{label:l(`slice.otherPrinters`),children:d.map(e=>(0,K.jsx)(`option`,{value:`${e.source}:${e.id}`,children:e.name},`${e.source}:${e.id}`))})]})]})}function $W({source:e,onClose:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(null),[s,c]=(0,y.useState)(null),[l,u]=(0,y.useState)(1),{trackJob:d}=WW(),{data:f,isLoading:p}=q({queryKey:[`slicer-pipelines`],queryFn:()=>Q.listSlicerPipelines()}),{data:m}=q({queryKey:[`printers`],queryFn:()=>Q.getPrinters()}),{data:h}=q({queryKey:[`app-settings`],queryFn:()=>Q.getSettings()}),g=h?.pipeline_max_copies??50,_={kind:e.kind,id:e.id},v=J({mutationFn:e=>Q.checkPipelineEligibility(e,_)}),b=J({mutationFn:({pipelineId:e,force:t})=>Q.runPipeline(e,_,t,l),onSuccess:a=>{r.invalidateQueries({queryKey:[`slicer-pipelines`]}),r.invalidateQueries({queryKey:[`pipeline-runs`]}),a.slice_job_id&&d(a.slice_job_id,e.kind,e.filename),i(n(`library.runWithPipeline.toast.started`,`Pipeline run started`),`success`),t()},onError:e=>{i(e.message||n(`library.runWithPipeline.toast.failed`,`Could not start run`),`error`)}}),x=f?.pipelines??[],S=(m??[]).reduce((e,t)=>(e[t.id]=t,e),{});return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 bg-black/60 flex items-center justify-center p-4`,onClick:t,role:`dialog`,"aria-modal":`true`,"aria-label":n(`library.runWithPipeline.modalTitle`,`Run with pipeline`),children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-2xl w-full max-w-md max-h-[80vh] flex flex-col overflow-hidden`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-4 py-3 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`h3`,{className:`text-sm font-semibold text-white flex items-center gap-2`,children:[(0,K.jsx)(Dl,{className:`w-4 h-4 text-bambu-green`}),a&&s?n(`library.runWithPipeline.confirmTitle`,`Confirm run`):n(`library.runWithPipeline.modalTitle`,`Run with pipeline`)]}),(0,K.jsx)(`button`,{type:`button`,onClick:t,"aria-label":n(`common.close`,`Close`),className:`text-bambu-gray hover:text-white`,children:(0,K.jsx)(Ju,{className:`w-4 h-4`})})]}),(0,K.jsx)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-3`,children:a&&s?(0,K.jsx)(fje,{pipeline:a,report:s,source:e,onBack:()=>{o(null),c(null)},onConfirm:()=>{a&&b.mutate({pipelineId:a.id,force:!0})},running:b.isPending}):(0,K.jsx)(dje,{source:e,pipelines:x,printerById:S,loading:p||v.isPending,onPick:async e=>{if(!(e.target_printer_id||e.target_kind===`printer_class`&&e.target_model_class)){i(n(`library.runWithPipeline.noTargetMessage`,`This pipeline has no target printer set. Open it in Settings to pick one.`),`error`);return}o(e);try{let t=await v.mutateAsync(e.id);c(t),t.ok&&b.mutate({pipelineId:e.id,force:!1})}catch{o(null)}},copies:l,maxCopies:g,onCopiesChange:u})})]})})}function dje({source:e,pipelines:t,printerById:n,loading:r,onPick:i,copies:a,maxCopies:o,onCopiesChange:s}){let{t:c}=$e();return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray`,children:[c(`library.runWithPipeline.sourceHint`,`Source`),`:`,` `,(0,K.jsx)(`span`,{className:`text-white`,children:e.filename})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsxs)(`label`,{className:`text-xs text-bambu-gray`,htmlFor:`run-pipeline-copies`,children:[c(`library.runWithPipeline.copies`,`Copies`),`:`]}),(0,K.jsx)(`input`,{id:`run-pipeline-copies`,type:`number`,min:1,max:o,value:a,onChange:e=>{let t=parseInt(e.target.value,10);Number.isNaN(t)||s(Math.max(1,Math.min(o,t)))},"aria-label":c(`library.runWithPipeline.copies`,`Copies`),className:`w-20 px-2 py-1 text-xs bg-bambu-dark border border-bambu-dark-tertiary rounded text-white`}),(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray/60`,children:c(`library.runWithPipeline.copiesHint`,`max {{n}}`,{n:o})})]}),r&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-bambu-gray`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),c(`library.runWithPipeline.loading`,`Loading…`)]}),!r&&t.length===0&&(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:c(`library.runWithPipeline.empty`,`No pipelines saved yet. Open the Slice dialog and click "Save as pipeline" to create one.`)}),!r&&t.length>0&&(0,K.jsx)(`ul`,{className:`space-y-1.5`,"aria-label":c(`library.runWithPipeline.pipelineListAria`,`Available pipelines`),children:t.map(e=>{let t=e.target_kind===`printer_class`,r=e.target_printer_id?n[e.target_printer_id]?.name:null,a=t&&e.target_model_class?c(`library.runWithPipeline.classTarget`,`Any {{model}}`,{model:e.target_model_class}):null;return(0,K.jsx)(`li`,{children:(0,K.jsxs)(`button`,{type:`button`,onClick:()=>i(e),disabled:!(e.target_printer_id||t&&e.target_model_class),className:`w-full text-left px-3 py-2 rounded-md border border-bambu-dark-tertiary bg-bambu-dark/40 hover:bg-bambu-dark-tertiary disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(Ns,{className:`w-3.5 h-3.5 text-bambu-green flex-shrink-0`}),(0,K.jsx)(`span`,{className:`text-sm font-medium text-white truncate`,children:e.name})]}),(0,K.jsxs)(`div`,{className:`mt-1 text-xs text-bambu-gray flex items-center gap-1`,children:[(0,K.jsx)(Ml,{className:`w-3 h-3`}),a?(0,K.jsx)(`span`,{children:a}):r?(0,K.jsx)(`span`,{children:r}):(0,K.jsx)(`span`,{className:`text-amber-700 dark:text-amber-400`,children:c(`library.runWithPipeline.noTarget`,`No target printer set`)})]})]})},e.id)})})]})}function fje({pipeline:e,report:t,source:n,onBack:r,onConfirm:i,running:a}){let{t:o}=$e();return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`text-xs text-bambu-gray`,children:[(0,K.jsxs)(`p`,{children:[o(`library.runWithPipeline.confirmIntro`,`Pre-flight found issues with this run`),`:`]}),(0,K.jsxs)(`p`,{className:`mt-1`,children:[(0,K.jsxs)(`span`,{className:`text-bambu-gray/70`,children:[o(`library.runWithPipeline.sourceHint`,`Source`),`: `]}),(0,K.jsx)(`span`,{className:`text-white`,children:n.filename})]}),(0,K.jsxs)(`p`,{children:[(0,K.jsxs)(`span`,{className:`text-bambu-gray/70`,children:[o(`library.runWithPipeline.pipelineHint`,`Pipeline`),`: `]}),(0,K.jsx)(`span`,{className:`text-white`,children:e.name})]}),t.target_printer_name&&(0,K.jsxs)(`p`,{children:[(0,K.jsxs)(`span`,{className:`text-bambu-gray/70`,children:[o(`library.runWithPipeline.targetHint`,`Target`),`: `]}),(0,K.jsx)(`span`,{className:`text-white`,children:t.target_printer_name})]})]}),(0,K.jsx)(`ul`,{className:`space-y-1.5`,children:t.issues.map((e,t)=>(0,K.jsxs)(`li`,{className:`flex items-start gap-2 text-xs`,children:[(0,K.jsx)(Au,{className:`w-3.5 h-3.5 text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5`}),(0,K.jsx)(`span`,{className:`text-bambu-gray`,children:(0,K.jsx)(pje,{issue:e})})]},t))}),(0,K.jsxs)(`div`,{className:`flex items-center justify-end gap-2 pt-2 border-t border-bambu-dark-tertiary`,children:[(0,K.jsx)(`button`,{type:`button`,onClick:r,disabled:a,className:`px-3 py-1.5 text-xs text-bambu-gray hover:text-white`,children:o(`common.back`,`Back`)}),(0,K.jsxs)(`button`,{type:`button`,onClick:i,disabled:a,className:`px-3 py-1.5 text-xs bg-amber-500 hover:bg-amber-600 text-white rounded disabled:opacity-50 flex items-center gap-1`,children:[a?(0,K.jsx)(X,{className:`w-3 h-3 animate-spin`}):(0,K.jsx)(Dl,{className:`w-3 h-3`}),o(`library.runWithPipeline.runAnyway`,`Run anyway`)]})]})]})}function pje({issue:e}){let{t}=$e();switch(e.kind){case`printer_not_set`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerNotSet`,`No target printer set on this pipeline.`)});case`printer_not_found`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerNotFound`,`Target printer no longer exists.`)});case`printer_disabled`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerDisabled`,`Target printer is disabled.`)});case`printer_offline`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerOffline`,`Target printer is offline.`)});case`filament_type_mismatch`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.filamentType`,`Filament slot {{slot}}: expected {{expected}}, AMS has {{actual}}`,{slot:(e.slot_index??0)+1,expected:e.expected??`?`,actual:e.actual??`?`})});case`filament_color_mismatch`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.filamentColor`,`Filament slot {{slot}}: colour differs (expected {{expected}}, AMS has {{actual}})`,{slot:(e.slot_index??0)+1,expected:e.expected??`?`,actual:e.actual??`?`})});case`ams_slot_missing`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.amsSlotMissing`,`AMS slot {{slot}} not available on this printer`,{slot:(e.slot_index??0)+1})});case`filament_unverified`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.filamentUnverified`,`Filament slot {{slot}} comes from a cloud / standard preset and could not be statically verified.`,{slot:(e.slot_index??0)+1})});default:return(0,K.jsx)(K.Fragment,{children:e.kind})}}function mje(){let e=navigator.userAgent.toLowerCase(),t=navigator.platform?.toLowerCase()||``;return e.includes(`win`)||t.includes(`win`)?`windows`:e.includes(`mac`)||t.includes(`mac`)?`macos`:e.includes(`linux`)||t.includes(`linux`)?`linux`:`unknown`}function eG(e,t=`bambu_studio`){let n,r=encodeURIComponent(e);n=t===`orcaslicer`?`orcaslicer://open?file=${r}`:mje()===`macos`?`bambustudioopen://${r}`:`bambustudio://open?file=${r}`;let i=document.createElement(`a`);i.href=n,i.style.display=`none`,document.body.appendChild(i),i.click(),document.body.removeChild(i)}var hje=[[`projects`],[`project`],[`project-archives`],[`project-timeline`],[`project-file-progress`]];function gje(e){return Promise.all(hje.map(t=>e.invalidateQueries({queryKey:[...t]})))}function tG(e){return Promise.all([e.invalidateQueries({queryKey:[`archives`]}),gje(e)])}function nG({onFiles:e,onRejected:t,extensions:n,disabled:r=!1}){let[i,a]=(0,y.useState)(!1),o=(0,y.useRef)(e),s=(0,y.useRef)(t),c=(0,y.useRef)(n);(0,y.useEffect)(()=>{o.current=e},[e]),(0,y.useEffect)(()=>{s.current=t},[t]),(0,y.useEffect)(()=>{c.current=n},[n]);let l=(0,y.useCallback)(e=>{r||(e.preventDefault(),e.dataTransfer.types.includes(`Files`)&&a(!0))},[r]),u=(0,y.useCallback)(e=>{r||(e.preventDefault(),e.dataTransfer.types.includes(`Files`)&&a(!0))},[r]),d=(0,y.useCallback)(e=>{if(r)return;e.preventDefault();let t=e.currentTarget,n=e.relatedTarget;(!n||!t.contains(n))&&a(!1)},[r]),f=(0,y.useCallback)(e=>{if(r)return;e.preventDefault(),a(!1);let t=Array.from(e.dataTransfer.files);if(t.length===0)return;let n=c.current,i=n&&n.length>0?t.filter(e=>n.some(t=>e.name.toLowerCase().endsWith(t))):t;i.length>0?o.current(i):s.current?.()},[r]);return(0,y.useEffect)(()=>{if(!i)return;let e=()=>a(!1),t=t=>{t.key===`Escape`&&e()};return document.addEventListener(`drop`,e),document.addEventListener(`dragend`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`drop`,e),document.removeEventListener(`dragend`,e),document.removeEventListener(`keydown`,t)}},[i]),{isDraggingOver:i,dragHandlers:{onDragOver:l,onDragEnter:u,onDragLeave:d,onDrop:f}}}function _je({onClose:e,initialFiles:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),a=(0,y.useRef)(null),[o,s]=(0,y.useState)(()=>t?.filter(e=>e.name.endsWith(`.3mf`)).map(e=>({file:e,status:`pending`}))||[]),[c,l]=(0,y.useState)(!1),[u,d]=(0,y.useState)(null);(0,y.useEffect)(()=>{let t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]);let f=J({mutationFn:e=>Q.uploadArchivesBulk(e),onSuccess:e=>{d(e),r.invalidateQueries({queryKey:[`archives`]}),r.invalidateQueries({queryKey:[`archiveStats`]}),s(t=>t.map(t=>{let n=e.results.find(e=>e.filename===t.file.name),r=e.errors.find(e=>e.filename===t.file.name);return n?{...t,status:`success`,archiveId:n.id}:r?{...t,status:`error`,error:r.error}:t})),e.failed===0?i(`${e.uploaded} file${e.uploaded===1?``:`s`} uploaded`):e.uploaded===0?i(`Failed to upload ${e.failed} file${e.failed===1?``:`s`}`,`error`):i(`${e.uploaded} uploaded, ${e.failed} failed`,`warning`)},onError:()=>{s(e=>e.map(e=>({...e,status:`error`,error:`Upload failed`}))),i(`Upload failed`,`error`)}}),p=(0,y.useCallback)(e=>{e.preventDefault(),l(!0)},[]),m=(0,y.useCallback)(e=>{e.preventDefault(),l(!1)},[]),h=(0,y.useCallback)(e=>{e.preventDefault(),l(!1);let t=Array.from(e.dataTransfer.files).filter(e=>e.name.endsWith(`.3mf`));t.length>0&&s(e=>[...e,...t.map(e=>({file:e,status:`pending`}))])},[]),g=(0,y.useCallback)(e=>{let t=Array.from(e.target.files||[]).filter(e=>e.name.endsWith(`.3mf`));t.length>0&&s(e=>[...e,...t.map(e=>({file:e,status:`pending`}))]),a.current&&(a.current.value=``)},[]),_=(0,y.useCallback)(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),v=()=>{if(o.length===0)return;let e=o.filter(e=>e.status===`pending`);e.length!==0&&(s(e=>e.map(e=>e.status===`pending`?{...e,status:`uploading`}:e)),f.mutate(e.map(e=>e.file)))},b=o.filter(e=>e.status===`pending`).length,x=f.isPending;return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,children:(0,K.jsx)(Dd,{className:`w-full max-w-2xl max-h-[90vh] flex flex-col`,children:(0,K.jsxs)(kd,{className:`p-0 flex flex-col h-full`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`h2`,{className:`text-xl font-semibold text-white`,children:n(`uploadModal.title`)}),(0,K.jsx)(`button`,{onClick:e,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsx)(`div`,{className:`p-4`,children:(0,K.jsxs)(`div`,{className:`border-2 border-dashed rounded-lg p-8 text-center transition-colors ${c?`border-bambu-green bg-bambu-green/10`:`border-bambu-dark-tertiary hover:border-bambu-gray`}`,onDragOver:p,onDragLeave:m,onDrop:h,children:[(0,K.jsx)(Pu,{className:`w-12 h-12 mx-auto mb-4 text-bambu-gray`}),(0,K.jsx)(`p`,{className:`text-white mb-2`,children:n(`uploadModal.dragDrop`)}),(0,K.jsx)(`p`,{className:`text-bambu-gray text-sm mb-4`,children:n(`uploadModal.or`)}),(0,K.jsx)($,{variant:`secondary`,onClick:()=>a.current?.click(),disabled:x,children:n(`uploadModal.browseFiles`)}),(0,K.jsx)(`input`,{ref:a,type:`file`,accept:`.3mf`,multiple:!0,className:`hidden`,onChange:g})]})}),(0,K.jsx)(`div`,{className:`px-4 pb-4`,children:(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:n(`uploadModal.extractionInfo`)})}),o.length>0&&(0,K.jsx)(`div`,{className:`px-4 pb-4 max-h-60 overflow-y-auto`,children:(0,K.jsx)(`div`,{className:`space-y-2`,children:o.map((e,t)=>(0,K.jsxs)(`div`,{className:`flex items-center gap-3 p-3 bg-bambu-dark rounded-lg`,children:[(0,K.jsx)(sc,{className:`w-5 h-5 text-bambu-gray flex-shrink-0`}),(0,K.jsx)(`span`,{className:`flex-1 text-white text-sm truncate`,children:e.file.name}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[(e.file.size/(1024*1024)).toFixed(1),` MB`]}),e.status===`pending`&&(0,K.jsx)(`button`,{onClick:()=>_(t),className:`text-bambu-gray hover:text-red-600 dark:hover:text-red-400 transition-colors`,disabled:x,children:(0,K.jsx)(Ju,{className:`w-4 h-4`})}),e.status===`uploading`&&(0,K.jsx)(X,{className:`w-4 h-4 text-bambu-green animate-spin`}),e.status===`success`&&(0,K.jsx)(gs,{className:`w-4 h-4 text-bambu-green`}),e.status===`error`&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`text-xs text-red-700 dark:text-red-400`,children:e.error}),(0,K.jsx)(ms,{className:`w-4 h-4 text-red-600 dark:text-red-400`})]})]},`${e.file.name}-${t}`))})}),u&&(0,K.jsx)(`div`,{className:`px-4 pb-4`,children:(0,K.jsx)(`div`,{className:`p-3 bg-bambu-dark rounded-lg`,children:(0,K.jsxs)(`p`,{className:`text-sm text-white`,children:[(0,K.jsx)(`span`,{className:`text-bambu-green`,children:u.uploaded}),` `,n(`uploadModal.uploaded`),u.failed>0&&(0,K.jsxs)(K.Fragment,{children:[`, `,(0,K.jsx)(`span`,{className:`text-red-700 dark:text-red-400`,children:u.failed}),` `,n(`uploadModal.failed`)]})]})})}),(0,K.jsxs)(`div`,{className:`flex gap-3 p-4 border-t border-bambu-dark-tertiary`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:e,className:`flex-1`,children:n(u?`common.close`:`common.cancel`)}),!u&&(0,K.jsx)($,{onClick:v,disabled:b===0||x,className:`flex-1`,children:x?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),n(`uploadModal.uploading`)]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(Pu,{className:`w-4 h-4`}),n(`uploadModal.upload`),` `,b>0&&`(${b})`]})})]})]})})})}var vje=365;function yje({onClose:e,initialDays:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(t??vje),[s,c]=(0,y.useState)(!1),[l,u]=(0,y.useState)(a);(0,y.useEffect)(()=>{let e=window.setTimeout(()=>u(a),300);return()=>window.clearTimeout(e)},[a]);let d=q({queryKey:[`archive-purge-preview`,l,s],queryFn:()=>Q.previewArchivePurge(l,s),enabled:l>=1}),f=J({mutationFn:()=>Q.executeArchivePurge(a,s),onSuccess:t=>{i(n(`archivePurge.toast.success`,{count:t.deleted}),`success`),r.invalidateQueries({queryKey:[`archives`]}),r.invalidateQueries({queryKey:[`archive-stats`]}),e()},onError:e=>i(e.message||n(`archivePurge.toast.failed`),`error`)});(0,y.useEffect)(()=>{let t=t=>{t.key===`Escape`&&!f.isPending&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e,f.isPending]);let p=d.data,m=p?.count??0,h=p?.total_bytes??0,g=m>0&&!f.isPending;return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,children:(0,K.jsxs)(`div`,{className:`bg-white dark:bg-gray-900 rounded-lg shadow-xl max-w-lg w-full`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700`,children:[(0,K.jsxs)(`h2`,{className:`text-lg font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2`,children:[(0,K.jsx)(Du,{className:`w-5 h-5`}),n(`archivePurge.title`)]}),(0,K.jsx)(`button`,{onClick:e,className:`text-gray-400 hover:text-gray-600 dark:hover:text-gray-200`,"aria-label":n(`common.close`),disabled:f.isPending,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-4`,children:[(0,K.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:n(`archivePurge.description`)}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{htmlFor:`archive-purge-days`,className:`block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1`,children:n(`archivePurge.ageLabel`)}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,K.jsx)(`input`,{id:`archive-purge-days`,type:`number`,min:1,max:3650,value:a,onChange:e=>o(Math.max(1,Math.min(3650,parseInt(e.target.value||`0`,10)||0))),className:`w-24 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm px-2 py-1 text-gray-900 dark:text-gray-100`}),(0,K.jsx)(`span`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:n(`archivePurge.days`)})]})]}),(0,K.jsxs)(`div`,{className:`rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/30 p-3`,children:[(0,K.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wide text-gray-600 dark:text-gray-300 mb-2`,children:n(`archivePurge.effectsTitle`)}),(0,K.jsxs)(`ul`,{className:`text-xs text-gray-700 dark:text-gray-300 space-y-1 list-disc pl-4`,children:[(0,K.jsx)(`li`,{children:n(`archivePurge.effect1`)}),(0,K.jsx)(`li`,{children:n(`archivePurge.effect2`)}),(0,K.jsx)(`li`,{children:n(`archivePurge.effect3`)}),(0,K.jsx)(`li`,{children:n(`archivePurge.effect4`)})]})]}),(0,K.jsx)(`div`,{className:`rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 p-3`,children:d.isLoading||d.isFetching?(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),` `,n(`archivePurge.previewLoading`)]}):d.isError?(0,K.jsx)(`div`,{className:`text-sm text-red-600 dark:text-red-400`,children:d.error?.message??n(`archivePurge.previewFailed`)}):(0,K.jsxs)(`div`,{className:`text-sm text-gray-900 dark:text-gray-100`,children:[(0,K.jsx)(`div`,{className:`font-medium`,children:n(`archivePurge.previewSummary`,{count:m,size:Md(h)})}),p?.sample_filenames&&p.sample_filenames.length>0&&(0,K.jsxs)(`ul`,{className:`mt-2 text-xs text-gray-600 dark:text-gray-400 space-y-0.5 list-disc pl-4`,children:[p.sample_filenames.map(e=>(0,K.jsx)(`li`,{className:`truncate`,children:e},e)),m>p.sample_filenames.length&&(0,K.jsx)(`li`,{className:`list-none italic text-gray-500`,children:n(`archivePurge.andMore`,{count:m-p.sample_filenames.length})})]})]})}),(0,K.jsxs)(`label`,{className:`flex gap-2 items-start rounded border border-gray-200 dark:border-gray-700 px-3 py-2 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:s,onChange:e=>c(e.target.checked),disabled:f.isPending,className:`mt-0.5 shrink-0`}),(0,K.jsxs)(`span`,{className:`text-xs text-gray-700 dark:text-gray-300`,children:[(0,K.jsx)(`span`,{className:`font-medium block mb-0.5`,children:n(`archivePurge.purgeStatsLabel`)}),(0,K.jsx)(`span`,{className:`text-gray-500 dark:text-gray-400`,children:n(`archivePurge.purgeStatsHint`)})]})]}),(0,K.jsxs)(`div`,{className:`flex gap-2 items-start text-xs text-amber-700 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 rounded px-3 py-2`,children:[(0,K.jsx)(Au,{className:`w-4 h-4 mt-0.5 shrink-0`}),(0,K.jsx)(`span`,{children:n(`archivePurge.warning`)})]})]}),(0,K.jsxs)(`div`,{className:`flex justify-end gap-2 p-4 border-t border-gray-200 dark:border-gray-700`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:e,disabled:f.isPending,children:n(`common.cancel`)}),(0,K.jsx)($,{variant:`danger`,disabled:!g,onClick:()=>f.mutate(),children:f.isPending?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin mr-1`}),n(`archivePurge.purging`)]}):n(`archivePurge.confirmCta`,{count:m})})]})]})})}function bje(e){if(!e||e<=0)return`—`;let t=Math.floor(e/3600),n=Math.floor(e%3600/60);return t>0?`${t}h ${n}m`:`${n}m`}function xje(e){if(!e)return`—`;let t=Vf(e);return t?t.toLocaleString():`—`}function rG({archiveId:e}){let{t}=$e(),{data:n,isLoading:r}=q({queryKey:[`archive-runs`,e],queryFn:()=>Q.getArchiveRuns(e)});if(r)return(0,K.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,K.jsx)(X,{className:`w-5 h-5 text-bambu-gray animate-spin`})});let i=n?.items||[];return i.length===0?(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray italic py-2`,children:t(`archives.runLog.empty`)}):(0,K.jsx)(`div`,{className:`overflow-x-auto`,children:(0,K.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,K.jsx)(`thead`,{children:(0,K.jsxs)(`tr`,{className:`text-bambu-gray border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`th`,{className:`text-left py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.date`)}),(0,K.jsx)(`th`,{className:`text-left py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.status`)}),(0,K.jsx)(`th`,{className:`text-right py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.duration`)}),(0,K.jsx)(`th`,{className:`text-right py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.filament`)}),(0,K.jsx)(`th`,{className:`text-right py-1.5 font-medium`,children:t(`archives.runLog.col.cost`)})]})}),(0,K.jsx)(`tbody`,{children:i.map(e=>{let n=e.status===`completed`?`text-bambu-green`:e.status===`failed`?`text-red-700 dark:text-red-400`:`text-bambu-gray`;return(0,K.jsxs)(`tr`,{className:`border-b border-bambu-dark-tertiary/40 last:border-0`,children:[(0,K.jsx)(`td`,{className:`py-1.5 pr-2 text-bambu-gray-light`,children:xje(e.started_at||e.created_at)}),(0,K.jsxs)(`td`,{className:`py-1.5 pr-2 font-medium ${n}`,children:[t(`archives.runLog.status.${e.status}`,{defaultValue:e.status}),e.failure_reason&&(0,K.jsx)(`span`,{className:`block text-[10px] text-bambu-gray font-normal`,children:t(`editArchive.failureReasons.${e.failure_reason}`,{defaultValue:e.failure_reason})})]}),(0,K.jsx)(`td`,{className:`py-1.5 pr-2 text-right text-bambu-gray-light`,children:bje(e.duration_seconds)}),(0,K.jsx)(`td`,{className:`py-1.5 pr-2 text-right text-bambu-gray-light`,children:e.filament_used_grams==null?`—`:`${e.filament_used_grams.toFixed(1)} g`}),(0,K.jsx)(`td`,{className:`py-1.5 text-right text-bambu-gray-light`,children:e.cost==null?`—`:e.cost.toFixed(2)})]},e.id)})})]})})}var iG=[`adhesionFailure`,`spaghettiDetached`,`layerShift`,`cloggedNozzle`,`filamentRunout`,`warping`,`stringing`,`underExtrusion`,`powerFailure`,`userCancelled`,`other`],Sje=[`completed`,`failed`,`aborted`,`printing`];function aG({archive:e,onClose:t,existingTags:n=[]}){let{t:r}=$e();(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let i=ao(),[a,o]=(0,y.useState)(e.print_name||``),[s,c]=(0,y.useState)(e.printer_id),[l,u]=(0,y.useState)(e.project_id??null),[d,f]=(0,y.useState)(e.notes||``),[p,m]=(0,y.useState)(e.tags||``),[h,g]=(0,y.useState)(()=>{let t=e.failure_reason||``;return t?iG.includes(t)?t:iG.find(e=>r(`editArchive.failureReasons.${e}`)===t)||``:``}),[_,v]=(0,y.useState)(e.status),[b,x]=(0,y.useState)(e.quantity??1),[S,C]=(0,y.useState)(e.photos||[]),[w,T]=(0,y.useState)(e.external_url||``),[E,D]=(0,y.useState)(!1),[O,k]=(0,y.useState)(!1),A=(0,y.useRef)(null),j=(0,y.useRef)(null),M=(0,y.useRef)(null),{data:N}=q({queryKey:[`printers`],queryFn:Q.getPrinters}),{data:P}=q({queryKey:[`projects`],queryFn:()=>Q.getProjects(),select:e=>[...e].sort((e,t)=>e.name.localeCompare(t.name))}),{data:F}=q({queryKey:[`tags`],queryFn:Q.getTags,enabled:n.length===0}),I=n.length>0?n:F?.map(e=>e.name)||[],L=p.split(`,`).map(e=>e.trim()).filter(Boolean),R=p.includes(`,`)?p.substring(p.lastIndexOf(`,`)+1).trim().toLowerCase():p.trim().toLowerCase(),z=I.filter(e=>!L.includes(e)&&(R===``||e.toLowerCase().includes(R))),B=e=>{let t;t=R&&!I.includes(R)?p.includes(`,`)?p.substring(0,p.lastIndexOf(`,`)).split(`,`).map(e=>e.trim()).filter(Boolean):[]:L,t.includes(e)||m([...t,e].join(`, `)),M.current!==null&&clearTimeout(M.current),A.current?.focus()},V=e=>{m(L.filter(t=>t!==e).join(`, `))},ee=J({mutationFn:t=>Q.updateArchive(e.id,t),onSuccess:()=>{tG(i),t()}}),te=async t=>{let n=t.target.files?.[0];if(n){D(!0);try{C((await Q.uploadArchivePhoto(e.id,n)).photos),i.invalidateQueries({queryKey:[`archives`]})}catch(e){console.error(`Failed to upload photo:`,e)}finally{D(!1),j.current&&(j.current.value=``)}}},H=async t=>{try{C((await Q.deleteArchivePhoto(e.id,t)).photos||[]),i.invalidateQueries({queryKey:[`archives`]})}catch(e){console.error(`Failed to delete photo:`,e)}};return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4`,onClick:t,children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-md max-h-[90vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:r(`editArchive.title`)}),(0,K.jsx)(`button`,{onClick:t,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`form`,{onSubmit:t=>{t.preventDefault();let n={print_name:a||void 0,printer_id:s,project_id:l,notes:d||void 0,tags:p||void 0,quantity:b,external_url:w||null};_!==e.status&&(n.status=_),_===`failed`||_===`aborted`?n.failure_reason=h||void 0:(e.status===`failed`||e.status===`aborted`)&&(n.failure_reason=null),ee.mutate(n)},className:`p-6 space-y-4 overflow-y-auto flex-1`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`archives.runLog.title`)}),(0,K.jsx)(rG,{archiveId:e.id})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.name`)}),(0,K.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:r(`editArchive.namePlaceholder`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.printer`)}),(0,K.jsxs)(`select`,{value:s??``,onChange:e=>c(e.target.value?Number(e.target.value):null),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:[(0,K.jsx)(`option`,{value:``,children:r(`editArchive.noPrinter`)}),N?.map(e=>(0,K.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(dc,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.project`)]}),(0,K.jsxs)(`select`,{value:l??``,onChange:e=>u(e.target.value?Number(e.target.value):null),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:[(0,K.jsx)(`option`,{value:``,children:r(`editArchive.noProject`)}),P?.map(e=>(0,K.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(kc,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.itemsPrinted`)]}),(0,K.jsx)(`input`,{type:`number`,min:1,value:b,onChange:e=>x(Math.max(1,parseInt(e.target.value)||1)),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:`1`}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`editArchive.itemsPrintedHelp`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.notes`)}),(0,K.jsx)(`textarea`,{value:d,onChange:e=>f(e.target.value),rows:3,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none resize-none`,placeholder:r(`editArchive.notesPlaceholder`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(Kc,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.externalLink`)]}),(0,K.jsx)(`input`,{type:`url`,value:w,onChange:e=>T(e.target.value),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:`https://printables.com/model/...`}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`editArchive.externalLinkHelp`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.tags`)}),L.length>0&&(0,K.jsx)(`div`,{className:`flex flex-wrap gap-1.5 mb-2`,children:L.map(e=>(0,K.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-0.5 bg-bambu-dark-tertiary rounded text-sm text-white`,children:[(0,K.jsx)(yu,{className:`w-3 h-3`}),e,(0,K.jsx)(`button`,{type:`button`,onClick:()=>V(e),className:`ml-0.5 text-bambu-gray hover:text-white`,children:(0,K.jsx)(Ju,{className:`w-3 h-3`})})]},e))}),(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(`input`,{ref:A,type:`text`,value:p,onChange:e=>m(e.target.value),onFocus:()=>{M.current!==null&&clearTimeout(M.current),k(!0)},onBlur:()=>{M.current=window.setTimeout(()=>k(!1),200)},className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:L.length>0?r(`editArchive.addMoreTags`):r(`editArchive.tagsPlaceholder`)}),O&&z.length>0&&(0,K.jsxs)(`div`,{className:`absolute top-full left-0 right-0 mt-1 bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-lg z-10 max-h-40 overflow-y-auto`,children:[(0,K.jsxs)(`div`,{className:`p-2 text-xs text-bambu-gray border-b border-bambu-dark-tertiary`,children:[R?r(`editArchive.matchingTags`,{query:R}):r(`editArchive.existingTags`),` `,r(`editArchive.clickToAdd`)]}),(0,K.jsx)(`div`,{className:`p-2 flex flex-wrap gap-1.5`,children:z.map(e=>(0,K.jsx)(`button`,{type:`button`,onClick:()=>B(e),className:`px-2 py-0.5 bg-bambu-dark-tertiary hover:bg-bambu-green/20 rounded text-sm text-bambu-gray hover:text-white transition-colors`,children:e},e))})]})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.status`)}),(0,K.jsx)(`select`,{value:_,onChange:e=>{v(e.target.value),e.target.value===`completed`&&g(``)},className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:Sje.map(e=>(0,K.jsx)(`option`,{value:e,children:r(`editArchive.statuses.${e}`)},e))})]}),(_===`failed`||_===`aborted`)&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{htmlFor:`failure-reason-select`,className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.failureReason`)}),(0,K.jsxs)(`select`,{id:`failure-reason-select`,value:h,onChange:e=>g(e.target.value),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:[(0,K.jsx)(`option`,{value:``,children:r(`editArchive.selectReason`)}),iG.map(e=>(0,K.jsx)(`option`,{value:e,children:r(`editArchive.failureReasons.${e}`)},e))]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(ts,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.photos`)]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap gap-2 mb-2`,children:[S.map(t=>(0,K.jsxs)(`div`,{className:`relative group`,children:[(0,K.jsx)(`img`,{src:Q.getArchivePhotoUrl(e.id,t),alt:r(`editArchive.printResult`),className:`w-20 h-20 object-cover rounded-lg border border-bambu-dark-tertiary`}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>H(t),className:`absolute -top-1 -right-1 p-1 bg-red-500 rounded-full opacity-0 group-hover:opacity-100 transition-opacity`,children:(0,K.jsx)(Du,{className:`w-3 h-3 text-white`})})]},t)),(0,K.jsxs)(`label`,{className:`w-20 h-20 flex items-center justify-center border-2 border-dashed border-bambu-dark-tertiary rounded-lg cursor-pointer hover:border-bambu-green transition-colors`,children:[(0,K.jsx)(`input`,{ref:j,type:`file`,accept:`image/jpeg,image/png,image/webp`,onChange:te,className:`hidden`,disabled:E}),E?(0,K.jsx)(X,{className:`w-6 h-6 text-bambu-gray animate-spin`}):(0,K.jsx)(kl,{className:`w-6 h-6 text-bambu-gray`})]})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:r(`editArchive.photosHelp`)})]}),(0,K.jsxs)(`div`,{className:`flex gap-3 pt-2`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:t,className:`flex-1`,children:r(`common.cancel`)}),(0,K.jsxs)($,{type:`submit`,disabled:ee.isPending,className:`flex-1`,children:[(0,K.jsx)(Bl,{className:`w-4 h-4`}),ee.isPending?r(`common.saving`):r(`common.save`)]})]})]})]})})}function oG({archiveId:e,archiveName:t,onClose:n}){let{t:r}=$e();return(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4`,onClick:n,children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-2xl max-h-[85vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,K.jsx)(Nc,{className:`w-5 h-5 text-bambu-green flex-shrink-0`}),(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white truncate`,title:t||``,children:r(`archives.runLog.modalTitle`,{name:t||r(`archives.runLog.modalTitleFallback`)})})]}),(0,K.jsx)(`button`,{onClick:n,className:`text-bambu-gray hover:text-white transition-colors`,title:r(`common.close`),children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsx)(`div`,{className:`p-6 overflow-y-auto flex-1`,children:(0,K.jsx)(rG,{archiveId:e})})]})})}function sG({isOpen:e,onClose:t,columns:n,defaultColumns:r,onSave:i}){let{t:a}=$e(),[o,s]=(0,y.useState)(n),[c,l]=(0,y.useState)(null),u=(0,y.useRef)(null);if((0,y.useEffect)(()=>{e&&s(n.map(e=>({...e})))},[e,n]),(0,y.useEffect)(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,n),()=>window.removeEventListener(`keydown`,n)},[e,t]),!e)return null;let d=e=>{s(t=>t.map((t,n)=>n===e?{...t,visible:!t.visible}:t))},f=(e,t)=>{t<0||t>=o.length||s(n=>{let r=[...n],[i]=r.splice(e,1);return r.splice(t,0,i),r})},p=(e,t)=>{u.current=t,l(t),e.dataTransfer.effectAllowed=`move`},m=(e,t)=>{e.preventDefault(),e.dataTransfer.dropEffect=`move`;let n=u.current;n!==null&&n!==t&&(f(n,t),u.current=t,l(t))},h=e=>{e.preventDefault()},g=()=>{u.current=null,l(null)},_=()=>{s(r.map(e=>({...e})))},v=()=>{i(o),t()},b=o.filter(e=>e.visible).length;return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:t,children:(0,K.jsx)(Dd,{className:`w-full max-w-md max-h-[80vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{className:`p-6 flex flex-col min-h-0`,children:[(0,K.jsx)(`h3`,{className:`text-lg font-semibold text-white mb-2`,children:a(`inventory.configureColumns`)}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray mb-4`,children:[a(`inventory.configureColumnsDesc`),(0,K.jsxs)(`span`,{className:`ml-2 text-bambu-gray/60`,children:[`(`,b,` `,a(`inventory.of`),` `,o.length,` `,a(`inventory.visible`),`)`]})]}),(0,K.jsx)(`div`,{className:`space-y-1 overflow-y-auto flex-1 min-h-0 pr-1`,children:o.map((e,t)=>(0,K.jsxs)(`div`,{className:`flex items-center gap-2 p-2 rounded-lg border transition-colors ${c===t?`border-bambu-green bg-bambu-green/10`:`border-bambu-dark-tertiary bg-bambu-dark-tertiary/50`} ${e.visible?``:`opacity-50`}`,draggable:!0,onDragStart:e=>p(e,t),onDragOver:e=>m(e,t),onDrop:h,onDragEnd:g,children:[(0,K.jsx)(`div`,{className:`cursor-grab text-bambu-gray/50 hover:text-bambu-gray`,children:(0,K.jsx)(Tc,{className:`w-4 h-4`})}),(0,K.jsx)(`span`,{className:`flex-1 font-medium text-sm text-white`,children:e.label}),(0,K.jsxs)(`div`,{className:`flex items-center gap-0.5`,children:[(0,K.jsx)(`button`,{onClick:()=>f(t,t-1),disabled:t===0,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:a(`inventory.moveUp`),children:(0,K.jsx)(ds,{className:`w-4 h-4`})}),(0,K.jsx)(`button`,{onClick:()=>f(t,t+1),disabled:t===o.length-1,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:a(`inventory.moveDown`),children:(0,K.jsx)(cs,{className:`w-4 h-4`})})]}),(0,K.jsx)(`button`,{onClick:()=>d(t),className:`p-1.5 rounded transition-colors ${e.visible?`text-bambu-green hover:bg-bambu-green/10`:`text-bambu-gray/50 hover:bg-bambu-dark-secondary`}`,title:e.visible?a(`inventory.hideColumn`):a(`inventory.showColumn`),children:e.visible?(0,K.jsx)(ec,{className:`w-4 h-4`}):(0,K.jsx)($s,{className:`w-4 h-4`})})]},e.id))}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3 mt-4 pt-4 border-t border-bambu-dark-tertiary`,children:[(0,K.jsxs)($,{variant:`secondary`,onClick:_,className:`mr-auto`,children:[(0,K.jsx)(Ll,{className:`w-4 h-4`}),a(`inventory.reset`)]}),(0,K.jsx)($,{variant:`secondary`,onClick:t,children:a(`inventory.cancel`)}),(0,K.jsx)($,{onClick:v,children:a(`inventory.applyChanges`)})]})]})})})}function Cje({items:e,searchPlaceholder:t,onClose:n,className:r,onMouseEnter:i,onMouseLeave:a}){let[o,s]=(0,y.useState)(``),c=(0,y.useRef)(null);(0,y.useEffect)(()=>{if(t){let e=window.setTimeout(()=>c.current?.focus(),0);return()=>window.clearTimeout(e)}},[t]);let l=o.trim().toLowerCase(),u=t&&l?e.filter(e=>e.label.toLowerCase().includes(l)):e;return(0,K.jsxs)(`div`,{className:r,onMouseEnter:i,onMouseLeave:a,children:[t&&(0,K.jsx)(`div`,{className:`sticky top-0 z-[1] px-2 py-1.5 bg-bambu-dark-secondary border-b border-bambu-dark-tertiary`,children:(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(Gl,{className:`absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-bambu-gray pointer-events-none`}),(0,K.jsx)(`input`,{ref:c,type:`text`,value:o,onChange:e=>s(e.target.value),onKeyDown:e=>{if(e.key===`Enter`){let e=u.find(e=>!e.disabled);e&&(e.onClick(),n())}},placeholder:t,className:`w-full pl-7 pr-2 py-1 text-sm bg-bambu-dark border border-bambu-dark-tertiary rounded text-white placeholder-bambu-gray focus:border-bambu-green focus:outline-none`})]})}),u.map((e,t)=>(0,K.jsxs)(`button`,{onClick:()=>{e.disabled||(e.onClick(),n())},disabled:e.disabled,className:`w-full flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${e.disabled?`text-bambu-gray cursor-not-allowed`:e.danger?`text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-400/10`:`text-white hover:bg-bambu-dark-tertiary`}`,children:[e.icon&&(0,K.jsx)(`span`,{className:`w-4 h-4 flex-shrink-0 flex items-center justify-center`,children:e.icon}),(0,K.jsx)(`span`,{className:`flex-1 truncate`,children:e.label})]},t)),t&&u.length===0&&(0,K.jsx)(`div`,{className:`px-3 py-2 text-sm text-bambu-gray text-center italic`,children:`—`})]})}function cG({x:e,y:t,items:n,onClose:r}){let i=(0,y.useRef)(null),[a,o]=(0,y.useState)(null),s=(0,y.useRef)(null),[c,l]=(0,y.useState)({x:e,y:t,visible:!1}),[u,d]=(0,y.useState)(!1),[f,p]=(0,y.useState)({});(0,y.useEffect)(()=>{let e=e=>{i.current&&!i.current.contains(e.target)&&r()},t=e=>{e.key===`Escape`&&r()},n=e=>{i.current&&i.current.contains(e.target)||r()};return document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t),document.addEventListener(`scroll`,n,!0),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t),document.removeEventListener(`scroll`,n,!0),s.current&&clearTimeout(s.current)}},[r]),(0,y.useLayoutEffect)(()=>{if(i.current){i.current.style.visibility=`hidden`,i.current.style.display=`block`;let n=i.current.getBoundingClientRect(),r=window.innerWidth,a=window.innerHeight,o=e,s=t;e+n.width>r-8&&(o=Math.max(8,r-n.width-8)),o<8&&(o=8),t+n.height>a-8&&(s=Math.max(8,a-n.height-8)),s<8&&(s=8),d(r-o-n.width<180&&o>180),l({x:o,y:s,visible:!0})}},[e,t]);let m=(e,t)=>{s.current&&=(clearTimeout(s.current),null);let n=t.getBoundingClientRect(),r=window.innerHeight-n.top-8<300&&n.top>300;p(t=>({...t,[e]:r?`bottom`:`top`})),o(e)},h=()=>{s.current=window.setTimeout(()=>{o(null)},150)};return(0,K.jsx)(`div`,{ref:i,className:`fixed z-50 min-w-[180px] max-w-[280px] bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-xl py-1`,style:{left:c.x,top:c.y,visibility:c.visible?`visible`:`hidden`},children:n.map((e,t)=>{if(e.divider)return(0,K.jsx)(`div`,{className:`my-1 border-t border-bambu-dark-tertiary`},t);let n=e.submenu&&e.submenu.length>0;return(0,K.jsxs)(`div`,{className:`relative`,onMouseEnter:e=>n&&m(t,e.currentTarget),onMouseLeave:()=>n&&h(),children:[(0,K.jsxs)(`button`,{onMouseEnter:e=>n&&m(t,e.currentTarget.parentElement),onClick:()=>{n?o(a===t?null:t):e.disabled||(e.onClick(),r())},disabled:e.disabled,title:e.title,className:`w-full flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${e.disabled?`text-bambu-gray cursor-not-allowed`:e.danger?`text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-400/10`:`text-white hover:bg-bambu-dark-tertiary`} ${n&&a===t?`bg-bambu-dark-tertiary`:``}`,children:[e.icon&&(0,K.jsx)(`span`,{className:`w-4 h-4 flex-shrink-0 flex items-center justify-center`,children:e.icon}),(0,K.jsx)(`span`,{className:`flex-1`,children:e.label}),n&&(0,K.jsx)(ls,{className:`w-4 h-4 text-bambu-gray`})]}),n&&a===t&&(0,K.jsx)(Cje,{items:e.submenu,searchPlaceholder:e.submenuSearchPlaceholder,onClose:r,className:`absolute min-w-[200px] bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-xl py-1 overflow-hidden max-h-[300px] overflow-y-auto z-[60] ${u?`right-full mr-1`:`left-full ml-1`} ${f[t]===`bottom`?`bottom-0`:`top-0`}`,onMouseEnter:()=>{s.current&&=(clearTimeout(s.current),null)},onMouseLeave:()=>h()})]},t)})})}function wje({selectedIds:e,existingTags:t,onClose:n}){let r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(``),[s,c]=(0,y.useState)(new Set),[l,u]=(0,y.useState)(`add`);(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]);let d=J({mutationFn:async()=>{let t=Array.from(s),n=0;for(let r of e)try{let e=await Q.getArchive(r),i=e.tags?e.tags.split(`,`).map(e=>e.trim()).filter(Boolean):[],a;a=l===`add`?[...new Set([...i,...t])]:i.filter(e=>!s.has(e)),await Q.updateArchive(r,{tags:a.join(`, `)}),n++}catch(e){throw console.error(`Failed to update archive ${r}:`,e),Error(`Failed on archive ${r}: ${e instanceof Error?e.message:`Unknown error`}`)}return{count:n,mode:l,tags:t}},onSuccess:({count:e,mode:t,tags:a})=>{r.invalidateQueries({queryKey:[`archives`]}),i(`${t===`add`?`Added`:`Removed`} ${a.length} tag${a.length===1?``:`s`} ${t===`add`?`to`:`from`} ${e} archive${e===1?``:`s`}`),n()},onError:e=>{i(e.message||`Failed to update tags`,`error`)}}),f=e=>{c(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},p=()=>{a.trim()&&!s.has(a.trim())&&(c(e=>new Set([...e,a.trim()])),o(``))};return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,children:(0,K.jsx)(Dd,{className:`w-full max-w-md`,children:(0,K.jsxs)(kd,{className:`p-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(yu,{className:`w-5 h-5 text-bambu-green`}),(0,K.jsx)(`h2`,{className:`text-xl font-semibold text-white`,children:l===`add`?`Add Tags`:`Remove Tags`})]}),(0,K.jsx)(`button`,{onClick:n,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-4`,children:[(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray`,children:[l===`add`?`Add`:`Remove`,` tags for `,e.length,` selected archive`,e.length===1?``:`s`]}),(0,K.jsxs)(`div`,{className:`flex gap-2`,children:[(0,K.jsx)($,{size:`sm`,variant:l===`add`?`primary`:`secondary`,onClick:()=>u(`add`),children:`Add Tags`}),(0,K.jsx)($,{size:`sm`,variant:l===`remove`?`primary`:`secondary`,onClick:()=>u(`remove`),children:`Remove Tags`})]}),l===`add`&&(0,K.jsxs)(`div`,{className:`flex gap-2`,children:[(0,K.jsx)(`input`,{type:`text`,placeholder:`Enter new tag...`,className:`flex-1 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm focus:border-bambu-green focus:outline-none`,value:a,onChange:e=>o(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),p())}}),(0,K.jsx)($,{size:`sm`,variant:`secondary`,onClick:p,disabled:!a.trim(),children:(0,K.jsx)(kl,{className:`w-4 h-4`})})]}),t.length>0&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mb-2`,children:`Existing tags:`}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:t.map(e=>(0,K.jsx)(`button`,{onClick:()=>f(e),className:`px-2 py-1 rounded text-sm transition-colors ${s.has(e)?`bg-bambu-green text-white`:`bg-bambu-dark-tertiary text-bambu-gray-light hover:bg-bambu-dark`}`,children:e},e))})]}),s.size>0&&(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray mb-2`,children:[`Tags to `,l===`add`?`add`:`remove`,`:`]}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Array.from(s).map(e=>(0,K.jsxs)(`span`,{className:`px-2 py-1 rounded text-sm flex items-center gap-1 ${l===`add`?`bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400`:`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400`}`,children:[e,(0,K.jsx)(`button`,{onClick:()=>f(e),className:`hover:opacity-70`,children:(0,K.jsx)(Ju,{className:`w-3 h-3`})})]},e))})]})]}),(0,K.jsxs)(`div`,{className:`flex gap-3 p-4 border-t border-bambu-dark-tertiary`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:n,className:`flex-1`,children:`Cancel`}),(0,K.jsx)($,{onClick:()=>d.mutate(),disabled:s.size===0||d.isPending,className:`flex-1`,children:d.isPending?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),`Processing...`]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(yu,{className:`w-4 h-4`}),l===`add`?`Add Tags`:`Remove Tags`]})})]})]})})})}function Tje({selectedIds:e,onClose:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(``),{data:s,isLoading:c}=q({queryKey:[`projects`],queryFn:()=>Q.getProjects()}),l=(0,y.useMemo)(()=>s?[...s].sort((e,t)=>e.name.localeCompare(t.name)):void 0,[s]),u=a.trim().toLowerCase(),d=u?l?.filter(e=>e.name.toLowerCase().includes(u)):l,f=(l?.length??0)>5;(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let p=()=>tG(r),m=J({mutationFn:async t=>(await Q.addArchivesToProject(t,e),t),onSuccess:n=>{let r=s?.find(e=>e.id===n);p(),i(`Added ${e.length} archive${e.length===1?``:`s`} to "${r?.name}"`),t()},onError:()=>{i(`Failed to assign project`,`error`)}}),h=J({mutationFn:async()=>{for(let t of e)await Q.updateArchive(t,{project_id:null});return e.length},onSuccess:e=>{p(),i(`Removed ${e} archive${e===1?``:`s`} from project`),t()},onError:()=>{i(`Failed to remove from project`,`error`)}}),g=m.isPending||h.isPending;return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,children:(0,K.jsx)(Dd,{className:`w-full max-w-md max-h-[80vh] flex flex-col`,children:(0,K.jsxs)(kd,{className:`p-0 flex flex-col min-h-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary shrink-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(dc,{className:`w-5 h-5 text-bambu-green`}),(0,K.jsx)(`h2`,{className:`text-xl font-semibold text-white`,children:`Assign to Project`})]}),(0,K.jsx)(`button`,{onClick:t,className:`text-bambu-gray hover:text-white transition-colors`,disabled:g,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-3 overflow-y-auto min-h-0`,children:[(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray`,children:[`Assign `,e.length,` selected archive`,e.length===1?``:`s`,` to a project`]}),c?(0,K.jsx)(`div`,{className:`flex items-center justify-center py-8`,children:(0,K.jsx)(X,{className:`w-6 h-6 animate-spin text-bambu-gray`})}):(0,K.jsxs)(`div`,{className:`space-y-2`,children:[(0,K.jsxs)(`button`,{onClick:()=>h.mutate(),disabled:g,className:`w-full flex items-center gap-3 p-3 rounded-lg bg-bambu-dark hover:bg-bambu-dark-tertiary border border-bambu-dark-tertiary transition-colors text-left disabled:opacity-50`,children:[(0,K.jsx)(`div`,{className:`w-8 h-8 rounded-full bg-red-500/20 flex items-center justify-center shrink-0`,children:(0,K.jsx)(Ss,{className:`w-4 h-4 text-red-600 dark:text-red-400`})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`text-white font-medium`,children:`Remove from project`}),(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray truncate`,children:`Clear project assignment`})]}),h.isPending&&(0,K.jsx)(X,{className:`w-4 h-4 animate-spin text-bambu-gray shrink-0`})]}),l&&l.length>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 py-2`,children:[(0,K.jsx)(`div`,{className:`flex-1 h-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:`or assign to`}),(0,K.jsx)(`div`,{className:`flex-1 h-px bg-bambu-dark-tertiary`})]}),f&&(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(Gl,{className:`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none`}),(0,K.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value),placeholder:n(`archives.menu.searchProjects`),className:`w-full pl-9 pr-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white placeholder-bambu-gray text-sm focus:border-bambu-green focus:outline-none`})]}),d?.map(e=>(0,K.jsxs)(`button`,{onClick:()=>m.mutate(e.id),disabled:g,className:`w-full flex items-center gap-3 p-3 rounded-lg bg-bambu-dark hover:bg-bambu-dark-tertiary border border-bambu-dark-tertiary transition-colors text-left disabled:opacity-50`,children:[(0,K.jsx)(`div`,{className:`w-8 h-8 rounded-full flex items-center justify-center shrink-0`,style:{backgroundColor:e.color?`${e.color}20`:`rgb(var(--bambu-green) / 0.2)`},children:(0,K.jsx)(dc,{className:`w-4 h-4`,style:{color:e.color||`rgb(var(--bambu-green))`}})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`text-white font-medium truncate`,children:e.name}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray truncate`,children:[e.archive_count,` archive`,e.archive_count===1?``:`s`,e.status&&` • ${e.status}`]})]}),m.isPending&&m.variables===e.id&&(0,K.jsx)(X,{className:`w-4 h-4 animate-spin text-bambu-gray shrink-0`})]},e.id)),(!l||l.length===0)&&(0,K.jsx)(`p`,{className:`text-center text-bambu-gray py-4`,children:`No projects yet. Create one from the Projects page.`}),l&&l.length>0&&d?.length===0&&(0,K.jsx)(`p`,{className:`text-center text-bambu-gray text-sm py-4`,children:`—`})]})]}),(0,K.jsx)(`div`,{className:`flex gap-3 p-4 border-t border-bambu-dark-tertiary shrink-0`,children:(0,K.jsx)($,{variant:`secondary`,onClick:t,className:`flex-1`,disabled:g,children:`Cancel`})})]})})})}function Eje(e,t){return new Date(e,t+1,0).getDate()}function Dje(e,t){return new Date(e,t,1).getDay()}var Oje=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],kje=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function Aje({archives:e,onArchiveClick:t,highlightedArchiveId:n}){let r=new Date,[i,a]=(0,y.useState)(r.getMonth()),[o,s]=(0,y.useState)(r.getFullYear()),[c,l]=(0,y.useState)(null),[u,d]=(0,y.useState)(null),f=(0,y.useMemo)(()=>{let t=new Map;return e.forEach(e=>{let n=Vf(e.completed_at||e.created_at)||new Date,r=`${n.getFullYear()}-${String(n.getMonth()+1).padStart(2,`0`)}-${String(n.getDate()).padStart(2,`0`)}`,i=t.get(r)||[];i.push(e),t.set(r,i)}),t},[e]),p=Eje(o,i),m=Dje(o,i),h=()=>{i===0?(a(11),s(o-1)):a(i-1)},g=()=>{i===11?(a(0),s(o+1)):a(i+1)},_=()=>{a(r.getMonth()),s(r.getFullYear())},v=[];for(let e=0;e{e!==c&&d(null),l(e)};return(0,K.jsxs)(`div`,{className:`flex flex-col lg:flex-row gap-6`,children:[(0,K.jsxs)(`div`,{className:`flex-1`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-4`,children:[(0,K.jsx)(`button`,{onClick:h,className:`p-2 hover:bg-bambu-dark-tertiary rounded-lg transition-colors`,children:(0,K.jsx)(us,{className:`w-5 h-5 text-bambu-gray`})}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,K.jsxs)(`h2`,{className:`text-lg font-semibold text-white`,children:[Oje[i],` `,o]}),(0,K.jsx)(`button`,{onClick:_,className:`px-2 py-1 text-xs bg-bambu-dark-tertiary hover:bg-bambu-green/20 text-bambu-gray hover:text-white rounded transition-colors`,children:`Today`})]}),(0,K.jsx)(`button`,{onClick:g,className:`p-2 hover:bg-bambu-dark-tertiary rounded-lg transition-colors`,children:(0,K.jsx)(ls,{className:`w-5 h-5 text-bambu-gray`})})]}),(0,K.jsx)(`div`,{className:`grid grid-cols-7 gap-1 mb-1`,children:kje.map(e=>(0,K.jsx)(`div`,{className:`text-center text-xs text-bambu-gray py-2`,children:e},e))}),(0,K.jsx)(`div`,{className:`grid grid-cols-7 gap-1`,children:v.map((e,t)=>{if(e===null)return(0,K.jsx)(`div`,{className:`aspect-square`},`empty-${t}`);let n=`${o}-${String(i+1).padStart(2,`0`)}-${String(e).padStart(2,`0`)}`,a=f.get(n)||[],s=a.length>0,l=e===r.getDate()&&i===r.getMonth()&&o===r.getFullYear(),u=n===c,d=a.filter(e=>e.status===`completed`).length,p=a.filter(e=>e.status===`failed`).length;return(0,K.jsxs)(`button`,{onClick:()=>x(u?null:n),className:`aspect-square rounded-lg p-1 flex flex-col items-center justify-center transition-colors relative ${u?`bg-bambu-green text-white`:l?`bg-bambu-green/20 text-white ring-2 ring-bambu-green`:s?`bg-bambu-dark-tertiary hover:bg-bambu-dark-tertiary/70 text-white`:`hover:bg-bambu-dark-tertiary/50 text-bambu-gray`}`,children:[(0,K.jsx)(`span`,{className:`text-sm font-medium ${l&&!u?`text-bambu-green`:``}`,children:e}),s&&(0,K.jsxs)(`div`,{className:`absolute bottom-1 left-1/2 -translate-x-1/2 flex items-center gap-1`,children:[(0,K.jsx)(`div`,{className:`w-2 h-2 rounded-full ${p>0&&d===0?`bg-red-400`:p>0?`bg-yellow-400`:`bg-green-400`}`}),(0,K.jsx)(`span`,{className:`text-xs font-medium`,children:a.length})]})]},e)})}),(0,K.jsx)(`div`,{className:`mt-4 pt-4 border-t border-bambu-dark-tertiary`,children:(0,K.jsxs)(`div`,{className:`grid grid-cols-3 gap-4 text-center`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`text-2xl font-bold text-white`,children:e.filter(e=>{let t=Vf(e.completed_at||e.created_at)||new Date;return t.getMonth()===i&&t.getFullYear()===o}).length}),(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray`,children:`Prints this month`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`text-2xl font-bold text-green-700 dark:text-green-400`,children:e.filter(e=>{let t=Vf(e.completed_at||e.created_at)||new Date;return t.getMonth()===i&&t.getFullYear()===o&&e.status===`completed`}).length}),(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray`,children:`Successful`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`text-2xl font-bold text-red-700 dark:text-red-400`,children:e.filter(e=>{let t=Vf(e.completed_at||e.created_at)||new Date;return t.getMonth()===i&&t.getFullYear()===o&&e.status===`failed`}).length}),(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray`,children:`Failed`})]})]})})]}),(0,K.jsx)(`div`,{className:`lg:w-80 bg-bambu-dark rounded-xl p-4`,children:c?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`h3`,{className:`text-sm font-medium text-bambu-gray mb-3`,children:new Date(c+`T12:00:00`).toLocaleDateString(`en-US`,{weekday:`long`,month:`long`,day:`numeric`,year:`numeric`})}),b.length>0?(0,K.jsx)(`div`,{className:`calendar-scroll space-y-2 max-h-96 overflow-y-auto`,children:b.map(e=>{let r=e.id===u||e.id===n;return(0,K.jsxs)(`button`,{onClick:()=>{d(e.id),t?.(e)},className:`w-full flex items-center gap-3 p-2 rounded-lg transition-colors text-left ${r?``:`hover:bg-bambu-dark-tertiary`}`,style:r?{outline:`4px solid #facc15`,outlineOffset:`2px`}:void 0,children:[e.thumbnail_path?(0,K.jsx)(`img`,{src:Q.getArchiveThumbnail(e.id),alt:``,className:`w-12 h-12 rounded object-cover`}):(0,K.jsx)(`div`,{className:`w-12 h-12 rounded bg-bambu-dark-tertiary flex items-center justify-center`,children:(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:`3MF`})}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsx)(`p`,{className:`text-sm text-white truncate`,children:e.print_name||e.filename}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-xs`,children:[(0,K.jsx)(`span`,{className:e.status===`failed`?`text-red-700 dark:text-red-400`:`text-green-700 dark:text-green-400`,children:e.status===`failed`?`Failed`:`Completed`}),e.filament_color&&(0,K.jsx)(`div`,{className:`flex gap-0.5`,children:e.filament_color.split(`,`).map((e,t)=>(0,K.jsx)(`div`,{className:`w-3 h-3 rounded-full border border-black/20`,style:{backgroundColor:e}},t))})]})]})]},e.id)})}):(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:`No prints on this day`})]}):(0,K.jsx)(`div`,{className:`text-center py-8`,children:(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:`Select a day to see prints`})})})]})}function lG({archiveId:e,archiveName:t,onClose:n}){let r=Q.getArchiveQRCodeUrl(e,300);return(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4`,onClick:n,children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-sm`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:`QR Code`}),(0,K.jsx)(`button`,{onClick:n,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-6 flex flex-col items-center`,children:[(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mb-4 text-center truncate max-w-full`,children:t}),(0,K.jsx)(`div`,{className:`bg-white p-4 rounded-lg mb-4`,children:(0,K.jsx)(`img`,{src:r,alt:`QR Code`,className:`w-64 h-64`})}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mb-4 text-center`,children:`Scan to open this archive`}),(0,K.jsxs)($,{onClick:()=>{let e=document.createElement(`a`);e.href=r,e.download=`${t}_qrcode.png`,e.click()},className:`w-full`,children:[(0,K.jsx)(Gs,{className:`w-4 h-4`}),`Download QR Code`]})]})]})})}function uG({archiveId:e,archiveName:t,photos:n,onClose:r,onDelete:i}){let[a,o]=(0,y.useState)(0),[s,c]=(0,y.useState)(!1);if((0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&r(),e.key===`ArrowLeft`&&o(e=>Math.max(0,e-1)),e.key===`ArrowRight`&&o(e=>Math.min(n.length-1,e+1))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[r,n.length]),(0,y.useEffect)(()=>{a>=n.length&&o(Math.max(0,n.length-1))},[n.length,a]),n.length===0)return r(),null;let l=n[a],u=Q.getArchivePhotoUrl(e,l);return(0,K.jsxs)(`div`,{className:`fixed inset-0 bg-black/90 flex items-center justify-center z-50`,onClick:r,children:[(0,K.jsxs)(`div`,{className:`relative w-full h-full flex flex-col`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 bg-black/50`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:t}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray`,children:[`Photo `,a+1,` of `,n.length]})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsxs)($,{variant:`secondary`,size:`sm`,onClick:()=>{let e=document.createElement(`a`);e.href=u,e.download=`${t}_photo_${a+1}.jpg`,e.click()},children:[(0,K.jsx)(Gs,{className:`w-4 h-4`}),`Download`]}),i&&(0,K.jsx)($,{variant:`secondary`,size:`sm`,onClick:()=>{i&&c(!0)},className:`text-red-400 hover:text-red-300`,children:(0,K.jsx)(Du,{className:`w-4 h-4`})}),(0,K.jsx)(`button`,{onClick:r,className:`p-2 text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-6 h-6`})})]})]}),(0,K.jsxs)(`div`,{className:`flex-1 min-h-0 flex items-center justify-center p-4 relative overflow-hidden`,children:[a>0&&(0,K.jsx)(`button`,{onClick:()=>o(e=>e-1),className:`absolute left-4 z-10 p-3 bg-black/50 hover:bg-black/70 rounded-full transition-colors`,children:(0,K.jsx)(us,{className:`w-8 h-8 text-white`})}),(0,K.jsx)(`img`,{src:u,alt:`Photo ${a+1}`,className:`max-w-full max-h-full object-contain rounded-lg`,style:{maxHeight:`calc(100vh - 200px)`}}),ao(e=>e+1),className:`absolute right-4 z-10 p-3 bg-black/50 hover:bg-black/70 rounded-full transition-colors`,children:(0,K.jsx)(ls,{className:`w-8 h-8 text-white`})})]}),n.length>1&&(0,K.jsx)(`div`,{className:`flex justify-center gap-2 p-4 bg-black/50`,children:n.map((t,n)=>(0,K.jsx)(`button`,{onClick:()=>o(n),className:`w-16 h-16 rounded-lg overflow-hidden border-2 transition-colors ${n===a?`border-bambu-green`:`border-transparent hover:border-bambu-gray`}`,children:(0,K.jsx)(`img`,{src:Q.getArchivePhotoUrl(e,t),alt:`Thumbnail ${n+1}`,className:`w-full h-full object-cover`})},t))})]}),s&&(0,K.jsx)(Kd,{title:`Delete Photo`,message:`Delete this photo? This cannot be undone.`,confirmText:`Delete`,variant:`danger`,onConfirm:()=>{i?.(l),c(!1)},onCancel:()=>c(!1)})]})}function dG(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0||G.vt_tray.length>0)&&r===`expanded`&&(()=>{let t=cn.filter(e=>e.tray.length>1),n=cn.filter(e=>e.tray.length===1),r=cn.length>0&&G.vt_tray.length>0,g=!(r&&ve),_=e.nozzle_count===2||G?.temperatures?.nozzle_2!==void 0,v=zW[i]??1,y=e=>`${Math.round(e*v*1e3)/1e3}rem`,b=`3.5rem`,S={minWidth:b},C={minWidth:b,maxWidth:y(7.25)},w=e=>({gridTemplateColumns:`repeat(${e}, minmax(${b}, 1fr))`}),T=(G.state===`RUNNING`||G.state===`PAUSE`)&&Array.isArray(G.ams_mapping)?G.ams_mapping:[],E=e=>{let t=Math.max(1,e),n=`calc(${t} * ${b} + ${Math.max(0,t-1)} * 0.25rem + 1rem)`;return{flex:`1 1 ${n}`,minWidth:n}};return(0,K.jsxs)(`div`,{className:`mt-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] uppercase tracking-wider text-bambu-gray font-medium`,children:P(`printers.filaments`)}),(0,K.jsx)(NAe,{state:G.ams_filament_backup,onClick:()=>_e(!0)}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`}),r&&(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(PAe,{hidden:ve,onClick:be}),(0,K.jsx)(`div`,{className:`w-3 h-[2px] bg-bambu-dark-tertiary`})]})]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[t.map(t=>{let n=on[String(t.id)],r=t.id>=128?t.id-128:t.id,i=n===void 0?r:n,g=i===1,v=i===0;return(0,K.jsxs)(`div`,{style:E(4),className:`min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1`,children:[(0,K.jsxs)(`div`,{className:`flex w-full min-h-7 items-center justify-between gap-2 rounded-lg bg-bambu-dark-secondary px-2 py-1`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-1.5`,children:[(0,K.jsx)(LW,{ams:t,printerId:e.id,label:ep(t.id,t.tray.length),amsLabels:Zt,canEdit:R(`printers:update`),onSaved:Qt,children:(0,K.jsx)(`span`,{className:`block truncate text-[length:var(--pc-t10,10px)] text-white font-medium cursor-default select-none`,children:Zt?.[t.id]||ep(t.id,t.tray.length)})}),_&&(g||v)&&(0,K.jsx)(SW,{side:g?`L`:`R`})]}),(t.humidity!=null||t.temp!=null)&&(0,K.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5`,children:[t.humidity!=null&&(0,K.jsx)(DW,{humidity:t.humidity,goodThreshold:a?.humidityGood,fairThreshold:a?.humidityFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`humidity`}),compact:!0}),t.temp!=null&&(0,K.jsx)(`div`,{className:`mr-1`,children:(0,K.jsx)(OW,{temp:t.temp,goodThreshold:a?.tempGood,fairThreshold:a?.tempFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`temperature`}),compact:!0})}),(G.supports_drying||G.drying_screen_only)&&(t.module_type===`n3f`||t.module_type===`n3s`)&&R(`printers:control`)&&(0,K.jsx)(`button`,{disabled:G.drying_screen_only||!!(t.dry_sf_reason?.length&&t.dry_time===0),onClick:e=>{if(t.dry_time>0)Bn.mutate(t.id);else if(Je===t.id)Ye(null);else{let n=(t.tray.find(e=>e.tray_type)?.tray_type||`PLA`).split(` `)[0].toUpperCase(),r=x[n]||x.PLA,i=t.module_type;et(n),nt(r[i]||r.n3f),it(i===`n3s`?r.n3s_hours:r.n3f_hours),ot(!1),Ze(t.module_type),Ye(t.id),ct(Zp({triggerRect:e.currentTarget.getBoundingClientRect(),popoverWidth:yW,estimatedHeight:bW,horizontalAlign:`center`}))}},className:`ml-1 flex items-center gap-0.5 px-1 py-0.5 rounded text-[length:var(--pc-t9,9px)] transition-colors ${t.dry_time>0?`bg-amber-100 dark:bg-amber-500/20 text-amber-700 dark:text-amber-400`:G.drying_screen_only||t.dry_sf_reason?.length?`bg-bambu-dark text-bambu-gray/50 cursor-not-allowed`:`bg-bambu-dark text-bambu-gray hover:text-white hover:bg-bambu-dark/80`}`,title:G.drying_screen_only?P(`printers.drying.screenOnly`):t.dry_time>0?P(`printers.drying.stop`):t.dry_sf_reason?.length?P(`printers.drying.powerRequired`):P(`printers.drying.start`),children:(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})]})]}),t.dry_time>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 rounded-lg bg-amber-50 dark:bg-amber-500/10 px-2 py-1 text-[length:var(--pc-t9,9px)]`,children:[(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] text-amber-600 dark:text-amber-400 shrink-0`}),(0,K.jsx)(`span`,{className:`text-amber-700 dark:text-amber-400 font-medium`,children:P(`printers.drying.active`)}),t.dry_filament&&(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70`,children:t.dry_target_temp==null?t.dry_filament:P(`printers.drying.targetSummary`,{filament:t.dry_filament,temp:t.dry_target_temp})}),(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70`,children:P(`printers.drying.timeRemaining`,{time:t.dry_time>=60?`${Math.floor(t.dry_time/60)}h ${t.dry_time%60}m`:`${t.dry_time}m`})}),!G.drying_screen_only&&(0,K.jsx)(`button`,{onClick:()=>Bn.mutate(t.id),disabled:Bn.isPending,className:`ml-auto text-amber-700 dark:text-amber-400 hover:text-amber-900 dark:hover:text-amber-300 transition-colors disabled:opacity-50`,title:P(`printers.drying.stop`),children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})]}),(0,K.jsx)(`div`,{className:`grid w-full gap-1`,style:w(4),children:[0,1,2,3].map(r=>{let i=t.tray[r]||t.tray.find(e=>e.id===r),a=i?.tray_type&&i.remain>=0,g=!i?.tray_type,_=kW(i),v=t.id*4+r,y=dn===v,b=fn!==null&&fn===v,x=pn!==null&&pn===v,C=i?.tray_info_idx?Kt?.[i.tray_info_idx]:null,w=qt?.[v],E=(i?.tray_uuid||i?.tag_uid||fp(e.serial_number,t.id,r))?.toUpperCase(),D=E?s?.[E]:void 0,O=lp(D),k=o&&!m?p?.find(n=>n.printer_id===e.id&&n.ams_id===t.id&&n.tray_id===r):void 0,A=k?f?.find(e=>e.id===k.spoolman_spool_id):void 0,j=A&&(A.label_weight??0)>0?Math.round(Math.max(0,(A.label_weight??0)-A.weight_used)/(A.label_weight??1)*100):null,M=u?.(e.id,t.id,r),N=(()=>{let e=M?.spool;return e&&e.label_weight>0&&e.weight_used!=null?Math.round(Math.max(0,e.label_weight-e.weight_used)/e.label_weight*100):null})(),F=N===0&&a&&i.remain>0?null:N,I=O??j??F??(a?i.remain:null),L=O!==null||j!==null?`spoolman`:F===null?a?`ams`:void 0:`inventory`,z=i?.tray_type?{vendor:Sp(i)?`Bambu Lab`:`Generic`,profile:w?.preset_name||(A?[A.brand,A.slicer_filament_name?.split(`@`)[0].trim()||A.material].filter(Boolean).join(` `).trim():null)||M?.spool?.slicer_filament_name||C?.name||i.tray_sub_brands||i.tray_type,colorName:pf(i.tray_color||``),colorHex:i.tray_color||null,kFactor:xW(i.k),fillLevel:I,trayUuid:i.tray_uuid||null,tagUid:i.tag_uid||null,fillSource:L}:null,B=hr?.amsId===t.id&&hr?.slotId===r,V=T.indexOf(v),ee=V>=0?`P${V+1}`:null,te=(0,K.jsxs)(`div`,{className:`relative w-full bg-bambu-dark-secondary rounded-lg p-1 text-center ${g?`opacity-50`:``} ${b?`ring-2 ring-amber-400 ring-offset-1 ring-offset-bambu-dark animate-pulse`:x?`ring-2 ring-red-500/60 ring-offset-1 ring-offset-bambu-dark`:y?`ring-2 ring-bambu-green ring-offset-1 ring-offset-bambu-dark`:``}`,children:[b&&(0,K.jsx)(`span`,{"aria-label":P(`printers.expectedSlot.ariaLabel`,{n:r+1}),title:P(`printers.expectedSlot.title`),className:`absolute top-0.5 left-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-amber-400 rounded pointer-events-none leading-none`,children:`↓`}),ee&&(0,K.jsx)(`span`,{"aria-label":P(`printers.activeJobSlot.ariaLabel`,{n:V+1}),title:P(`printers.activeJobSlot.title`,{n:V+1}),className:`absolute top-0.5 right-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-bambu-green rounded pointer-events-none leading-none`,children:ee}),(0,K.jsx)(vW,{trayColor:i?.tray_color,trayType:i?.tray_type,isEmpty:g,emptyKind:_,slotNumber:r+1}),(0,K.jsx)(`div`,{className:`text-[length:var(--pc-t9,9px)] text-white font-bold truncate`,children:i?.tray_type||P(_===`reset`?`ams.slotUnconfigured`:`ams.slotEmpty`)}),(0,K.jsx)(`div`,{className:`mt-1 h-1.5 bg-black/30 rounded-full overflow-hidden`,children:I!==null&&I>=0&&!g&&i&&(0,K.jsx)(`div`,{className:`h-full rounded-full transition-all`,style:{width:`${I}%`,backgroundColor:cp(I)}})})]});return(0,K.jsxs)(`div`,{className:`relative group w-full`,style:S,children:[B&&(0,K.jsx)(`div`,{className:`absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20`,children:(0,K.jsx)(Fl,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] text-bambu-green animate-spin`})}),z?(0,K.jsx)(uU,{data:z,actions:qr({amsId:t.id,slotId:r,loadTrayId:t.id*4+r,isRefreshing:B}),spoolman:{enabled:o,linkedSpoolId:k?.spoolman_spool_id??(E?s?.[E]?.id:void 0),spoolmanUrl:c,syncMode:l,onLinkSpool:o&&!k&&!M?()=>{let n=(z.trayUuid||z.tagUid||fp(e.serial_number,t.id,r)).toUpperCase();St({tagUid:z.tagUid||n,trayUuid:z.trayUuid||``,printerId:e.id,amsId:t.id,trayId:r})}:void 0,onUnlinkSpool:D?.id?()=>Rn.mutate(D.id):void 0},inventory:(()=>{if(o){if(m)return;let n=k,a=A;return{assignedSpool:a?{id:a.id,material:a.material,brand:a.brand??null,color_name:a.color_name??null,remainingWeightGrams:a.label_weight?Math.max(0,Math.round(a.label_weight-a.weight_used)):void 0}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:r,trayInfo:{type:i?.tray_type||z.profile,material:i?.tray_type??void 0,profile:z.profile,color:z.colorHex||``,location:`${ep(t.id,t.tray.length)} Slot ${r+1}`}}),onUnassignSpool:a&&!Sp(i)?()=>h?.(a.id):void 0,isAssigned:!!n||Sp(i)}}let n=u?.(e.id,t.id,r);return{assignedSpool:n?.spool?{id:n.spool.id,material:n.spool.material,brand:n.spool.brand,color_name:n.spool.color_name,remainingWeightGrams:Math.max(0,Math.round(n.spool.label_weight-n.spool.weight_used))}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:r,trayInfo:{type:i?.tray_type||z.profile,material:i?.tray_type??void 0,profile:z.profile,color:z.colorHex||``,location:`${ep(t.id,t.tray.length)} Slot ${r+1}`}}),onUnassignSpool:n&&!Sp(i)?()=>d?.(e.id,t.id,r):void 0,isAssigned:!!n||Sp(i)}})(),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:r,trayCount:t.tray.length,trayType:i?.tray_type||void 0,trayColor:i?.tray_color||void 0,traySubBrands:i?.tray_sub_brands||void 0,trayInfoIdx:i?.tray_info_idx||void 0,extruderId:n,caliIdx:i?.cali_idx,savedPresetId:w?.preset_id})},children:te}):(0,K.jsx)(dU,{kind:_??void 0,actions:qr({amsId:t.id,slotId:r,loadTrayId:t.id*4+r,isRefreshing:B}),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:r,trayCount:t.tray.length,extruderId:n})},onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:r,trayInfo:{type:``,material:void 0,profile:``,color:``,location:`${ep(t.id,t.tray.length)} Slot ${r+1}`}}),children:te})]},r)})})]},t.id)}),n.map(t=>{let n=on[String(t.id)],r=t.id>=128?t.id-128:t.id,i=n===void 0?r:n,g=i===1,v=i===0,S=t.tray[0],w=S?.tray_type&&S.remain>=0,E=!S?.tray_type,D=kW(S),O=sp(t.id,S?.id??0,!1),k=dn===O,A=fn!==null&&fn===O,j=pn!==null&&pn===O,M=S?.tray_info_idx?Kt?.[S.tray_info_idx]:null,N=qt?.[O],F=S?.id??0,I=(S?.tray_uuid||S?.tag_uid||fp(e.serial_number,t.id,F))?.toUpperCase(),L=I?s?.[I]:void 0,z=lp(L),B=u?.(e.id,t.id,F),V=(()=>{let e=B?.spool;return e&&e.label_weight>0&&e.weight_used!=null?Math.round(Math.max(0,e.label_weight-e.weight_used)/e.label_weight*100):null})(),ee=V===0&&w&&S.remain>0?null:V,te=o&&!m?p?.find(n=>n.printer_id===e.id&&n.ams_id===t.id&&n.tray_id===F):void 0,H=te?f?.find(e=>e.id===te.spoolman_spool_id):void 0,ne=H&&(H.label_weight??0)>0?Math.round(Math.max(0,(H.label_weight??0)-H.weight_used)/(H.label_weight??1)*100):null,re=z??ne??ee??(w?S.remain:null),U=z!==null||ne!==null?`spoolman`:ee===null?w?`ams`:void 0:`inventory`,ie=S?.tray_type?{vendor:Sp(S)?`Bambu Lab`:`Generic`,profile:N?.preset_name||(H?[H.brand,H.slicer_filament_name?.split(`@`)[0].trim()||H.material].filter(Boolean).join(` `).trim():null)||B?.spool?.slicer_filament_name||M?.name||S.tray_sub_brands||S.tray_type,colorName:pf(S.tray_color||``),colorHex:S.tray_color||null,kFactor:xW(S.k),fillLevel:re,trayUuid:S.tray_uuid||null,tagUid:S.tag_uid||null,fillSource:U}:null,ae=hr?.amsId===t.id&&hr?.slotId===F,W=T.indexOf(O),oe=W>=0?`P${W+1}`:null,se=(0,K.jsxs)(`div`,{className:`relative w-full bg-bambu-dark-secondary rounded-lg p-1 text-center ${E?`opacity-50`:``} ${A?`ring-2 ring-amber-400 ring-offset-1 ring-offset-bambu-dark animate-pulse`:j?`ring-2 ring-red-500/60 ring-offset-1 ring-offset-bambu-dark`:k?`ring-2 ring-bambu-green ring-offset-1 ring-offset-bambu-dark`:``}`,children:[A&&(0,K.jsx)(`span`,{"aria-label":P(`printers.expectedSlot.ariaLabel`,{n:1}),title:P(`printers.expectedSlot.title`),className:`absolute top-0.5 left-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-amber-400 rounded pointer-events-none leading-none`,children:`↓`}),oe&&(0,K.jsx)(`span`,{"aria-label":P(`printers.activeJobSlot.ariaLabel`,{n:W+1}),title:P(`printers.activeJobSlot.title`,{n:W+1}),className:`absolute top-0.5 right-0.5 px-1 py-px text-[length:var(--pc-t8,8px)] font-bold text-bambu-dark bg-bambu-green rounded pointer-events-none leading-none`,children:oe}),(0,K.jsx)(vW,{trayColor:S?.tray_color,trayType:S?.tray_type,isEmpty:E,emptyKind:D,slotNumber:1}),(0,K.jsx)(`div`,{className:`text-[length:var(--pc-t9,9px)] text-white font-bold truncate`,children:S?.tray_type||P(D===`reset`?`ams.slotUnconfigured`:`ams.slotEmpty`)}),(0,K.jsx)(`div`,{className:`mt-1 h-1.5 bg-black/30 rounded-full overflow-hidden`,children:re!==null&&re>=0&&!E&&(0,K.jsx)(`div`,{className:`h-full rounded-full transition-all`,style:{width:`${re}%`,backgroundColor:cp(re)}})})]}),ce=y(11);return(0,K.jsxs)(`div`,{style:{flex:`1 1 ${ce}`,minWidth:ce,maxWidth:`calc(4 * ${b} + 3 * 0.25rem + 1rem)`},className:`min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1`,children:[(0,K.jsxs)(`div`,{className:`flex w-full min-h-7 items-center gap-1.5 rounded-lg bg-bambu-dark-secondary px-2 py-1`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-1.5`,children:[(0,K.jsx)(LW,{ams:t,printerId:e.id,label:ep(t.id,t.tray.length),amsLabels:Zt,canEdit:R(`printers:update`),onSaved:Qt,children:(0,K.jsx)(`span`,{className:`block truncate text-[length:var(--pc-t10,10px)] text-white font-medium cursor-default select-none`,children:Zt?.[t.id]||ep(t.id,t.tray.length)})}),_&&(g||v)&&(0,K.jsx)(SW,{side:g?`L`:`R`})]}),(G.supports_drying||G.drying_screen_only)&&(t.module_type===`n3f`||t.module_type===`n3s`)&&R(`printers:control`)&&(0,K.jsx)(`div`,{className:`relative ml-auto`,children:(0,K.jsx)(`button`,{disabled:G.drying_screen_only,onClick:e=>{if(t.dry_time>0)Bn.mutate(t.id);else if(Je===t.id)Ye(null);else{let n=(t.tray.find(e=>e.tray_type)?.tray_type||`PLA`).split(` `)[0].toUpperCase(),r=x[n]||x.PLA,i=t.module_type;et(n),nt(r[i]||r.n3f),it(i===`n3s`?r.n3s_hours:r.n3f_hours),ot(!1),Ze(t.module_type),Ye(t.id),ct(Zp({triggerRect:e.currentTarget.getBoundingClientRect(),popoverWidth:yW,estimatedHeight:bW,horizontalAlign:`center`}))}},className:`flex items-center gap-0.5 px-1 py-0.5 rounded text-[length:var(--pc-t9,9px)] transition-colors ${t.dry_time>0?`bg-amber-100 dark:bg-amber-500/20 text-amber-700 dark:text-amber-400`:G.drying_screen_only?`bg-bambu-dark text-bambu-gray/50 cursor-not-allowed`:`bg-bambu-dark text-bambu-gray hover:text-white hover:bg-bambu-dark/80`}`,title:G.drying_screen_only?P(`printers.drying.screenOnly`):t.dry_time>0?P(`printers.drying.stop`):P(`printers.drying.start`),children:(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})})]}),t.dry_time>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-1.5 overflow-hidden whitespace-nowrap rounded-lg bg-amber-50 dark:bg-amber-500/10 px-2 py-1 text-[length:var(--pc-t9,9px)]`,children:[(0,K.jsx)(lc,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] text-amber-600 dark:text-amber-400 shrink-0`}),t.dry_filament&&(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70 text-[length:var(--pc-t8,8px)] truncate`,children:t.dry_target_temp==null?t.dry_filament:P(`printers.drying.targetSummary`,{filament:t.dry_filament,temp:t.dry_target_temp})}),(0,K.jsx)(`span`,{className:`text-amber-700/80 dark:text-amber-300/70 text-[length:var(--pc-t8,8px)] truncate`,children:t.dry_time>=60?`${Math.floor(t.dry_time/60)}h ${t.dry_time%60}m`:`${t.dry_time}m`}),!G.drying_screen_only&&(0,K.jsx)(`button`,{onClick:()=>Bn.mutate(t.id),disabled:Bn.isPending,className:`ml-auto text-amber-700 dark:text-amber-400 hover:text-amber-900 dark:hover:text-amber-300 transition-colors disabled:opacity-50 shrink-0`,title:P(`printers.drying.stop`),children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)]`})})]}),(0,K.jsxs)(`div`,{className:`flex gap-1.5 max-[550px]:flex-col max-[550px]:items-start`,children:[(0,K.jsxs)(`div`,{className:`relative group flex-1`,style:C,children:[ae&&(0,K.jsx)(`div`,{className:`absolute inset-0 bg-bambu-dark-tertiary/80 rounded flex items-center justify-center z-20`,children:(0,K.jsx)(Fl,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] text-bambu-green animate-spin`})}),ie?(0,K.jsx)(uU,{data:ie,actions:qr({amsId:t.id,slotId:F,loadTrayId:t.id*4+F,isRefreshing:ae}),spoolman:{enabled:o,linkedSpoolId:te?.spoolman_spool_id??(I?s?.[I]?.id:void 0),spoolmanUrl:c,syncMode:l,onLinkSpool:o&&!te&&!B?()=>{let n=(ie.trayUuid||ie.tagUid||fp(e.serial_number,t.id,F)).toUpperCase();St({tagUid:ie.tagUid||n,trayUuid:ie.trayUuid||``,printerId:e.id,amsId:t.id,trayId:F})}:void 0,onUnlinkSpool:L?.id?()=>Rn.mutate(L.id):void 0},inventory:(()=>{if(o){if(m)return;let n=te,r=H;return{assignedSpool:r?{id:r.id,material:r.material,brand:r.brand??null,color_name:r.color_name??null,remainingWeightGrams:r.label_weight?Math.max(0,Math.round(r.label_weight-r.weight_used)):void 0}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:F,trayInfo:{type:S?.tray_type||ie.profile,material:S?.tray_type??void 0,profile:ie.profile,color:ie.colorHex||``,location:ep(t.id,t.tray.length)}}),onUnassignSpool:r&&!Sp(S)?()=>h?.(r.id):void 0,isAssigned:!!n||Sp(S)}}let n=u?.(e.id,t.id,F);return{assignedSpool:n?.spool?{id:n.spool.id,material:n.spool.material,brand:n.spool.brand,color_name:n.spool.color_name,remainingWeightGrams:Math.max(0,Math.round(n.spool.label_weight-n.spool.weight_used))}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:F,trayInfo:{type:S?.tray_type||ie.profile,material:S?.tray_type??void 0,profile:ie.profile,color:ie.colorHex||``,location:ep(t.id,t.tray.length)}}),onUnassignSpool:n&&!Sp(S)?()=>d?.(e.id,t.id,F):void 0,isAssigned:!!n||Sp(S)}})(),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:F,trayCount:t.tray.length,trayType:S?.tray_type||void 0,trayColor:S?.tray_color||void 0,traySubBrands:S?.tray_sub_brands||void 0,trayInfoIdx:S?.tray_info_idx||void 0,extruderId:n,caliIdx:S?.cali_idx,savedPresetId:N?.preset_id})},children:se}):(0,K.jsx)(dU,{kind:D??void 0,actions:qr({amsId:t.id,slotId:F,loadTrayId:t.id*4+F,isRefreshing:ae}),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:t.id,trayId:F,trayCount:t.tray.length,extruderId:n})},onAssignSpool:()=>wt({printerId:e.id,amsId:t.id,trayId:F,trayInfo:{type:``,material:void 0,profile:``,color:``,location:ep(t.id,t.tray.length)}}),children:se})]}),(t.humidity!=null||t.temp!=null)&&(0,K.jsxs)(`div`,{className:`flex flex-col justify-center gap-1 shrink-0 max-[550px]:w-full`,children:[t.temp!=null&&(0,K.jsx)(OW,{temp:t.temp,goodThreshold:a?.tempGood,fairThreshold:a?.tempFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`temperature`}),compact:!0}),t.humidity!=null&&(0,K.jsx)(DW,{humidity:t.humidity,goodThreshold:a?.humidityGood,fairThreshold:a?.humidityFair,onClick:()=>vt({amsId:t.id,amsLabel:ep(t.id,t.tray.length),mode:`humidity`}),compact:!0})]})]})]},t.id)}),G.vt_tray.length>0&&g&&(0,K.jsxs)(`div`,{style:E(G.vt_tray.length),className:`min-w-0 p-2 bg-bambu-dark rounded-[10px] space-y-1`,children:[(0,K.jsx)(`div`,{className:`flex w-full min-h-7 items-center gap-1.5 rounded-lg bg-bambu-dark-secondary px-2 py-1`,children:(0,K.jsx)(`span`,{className:`block min-w-0 flex-1 truncate text-[length:var(--pc-t10,10px)] text-white font-medium`,children:P(`printers.external`)})}),(0,K.jsx)(`div`,{className:`grid w-full gap-1`,style:w(G.vt_tray.length>1?2:1),children:[...G.vt_tray].sort((e,t)=>(e.id??254)-(t.id??254)).map(t=>{let n=t.id??254,r=_&&dn===254?n===254&&G.active_extruder===1||n===255&&G.active_extruder===0:dn===n,i=n-254,a=_?P(n===254?`printers.extL`:`printers.extR`):``,g=t.tray_info_idx?Kt?.[t.tray_info_idx]:null,v=qt?.[1020+i],y=(t.tray_uuid||t.tag_uid||fp(e.serial_number,255,i))?.toUpperCase(),b=y?s?.[y]:void 0,x=lp(b),C=u?.(e.id,255,i),w=(()=>{let e=C?.spool;return e&&e.label_weight>0&&e.weight_used!=null?Math.round(Math.max(0,e.label_weight-e.weight_used)/e.label_weight*100):null})(),T=t.tray_type&&t.remain>=0,E=w===0&&T&&t.remain>0?null:w,D=o&&!m?p?.find(t=>t.printer_id===e.id&&t.ams_id===255&&t.tray_id===i):void 0,O=D?f?.find(e=>e.id===D.spoolman_spool_id):void 0,k=O&&(O.label_weight??0)>0?Math.round(Math.max(0,(O.label_weight??0)-O.weight_used)/(O.label_weight??1)*100):null,A=x??k??E??(T?t.remain:null),j=x!==null||k!==null?`spoolman`:E===null?T?`ams`:void 0:`inventory`,M={vendor:Sp(t)?`Bambu Lab`:`Generic`,profile:v?.preset_name||(O?[O.brand,O.slicer_filament_name?.split(`@`)[0].trim()||O.material].filter(Boolean).join(` `).trim():null)||C?.spool?.slicer_filament_name||g?.name||t.tray_sub_brands||t.tray_type||`Unknown`,colorName:pf(t.tray_color||``),colorHex:t.tray_color||null,kFactor:xW(t.k),fillLevel:A,trayUuid:t.tray_uuid||null,tagUid:t.tag_uid||null,fillSource:j},N=!t.tray_type,F=kW(t),I=(0,K.jsxs)(`div`,{className:`w-full bg-bambu-dark-secondary rounded-lg p-1 text-center ${N?`opacity-50`:``} ${r?`ring-2 ring-bambu-green ring-offset-1 ring-offset-bambu-dark`:``}`,children:[(0,K.jsx)(vW,{trayColor:t.tray_color,trayType:t.tray_type,isEmpty:N,emptyKind:F,slotNumber:_?n===254?`L`:`R`:i+1}),(0,K.jsx)(`div`,{className:`text-[length:var(--pc-t9,9px)] font-bold truncate ${N?`text-white/40`:`text-white`}`,children:t.tray_type||P(`ams.slotEmpty`)}),(0,K.jsx)(`div`,{className:`mt-1 h-1.5 bg-black/30 rounded-full overflow-hidden`,children:A!==null&&A>=0&&!N&&(0,K.jsx)(`div`,{className:`h-full rounded-full transition-all`,style:{width:`${A}%`,backgroundColor:cp(A)}})})]});return(0,K.jsx)(`div`,{className:`relative group w-full`,style:S,children:N?(0,K.jsx)(dU,{kind:F??void 0,actions:qr({amsId:255,slotId:i,loadTrayId:n,includeRfid:!1}),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:255,trayId:i,trayCount:1,extruderId:_?+(n===254):void 0})},onAssignSpool:()=>wt({printerId:e.id,amsId:255,trayId:i,trayInfo:{type:``,material:void 0,profile:``,color:``,location:`External Slot ${i+1}`}}),children:I}):(0,K.jsx)(uU,{data:M,actions:qr({amsId:255,slotId:i,loadTrayId:n,includeRfid:!1}),spoolman:{enabled:o,linkedSpoolId:D?.spoolman_spool_id??(y?s?.[y]?.id:void 0),spoolmanUrl:c,syncMode:l,onLinkSpool:o&&!D&&!C?()=>{let t=(M.trayUuid||M.tagUid||fp(e.serial_number,255,i)).toUpperCase();St({tagUid:M.tagUid||t,trayUuid:M.trayUuid||``,printerId:e.id,amsId:255,trayId:i})}:void 0,onUnlinkSpool:b?.id?()=>Rn.mutate(b.id):void 0},inventory:(()=>{if(o){if(m)return;let n=D,r=O;return{assignedSpool:r?{id:r.id,material:r.material,brand:r.brand??null,color_name:r.color_name??null,remainingWeightGrams:r.label_weight?Math.max(0,Math.round(r.label_weight-r.weight_used)):void 0}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:255,trayId:i,trayInfo:{type:t.tray_type||M.profile,material:t.tray_type??void 0,profile:M.profile,color:M.colorHex||``,location:a||P(`printers.external`)}}),onUnassignSpool:r&&!Sp(t)?()=>h?.(r.id):void 0,isAssigned:!!n||Sp(t)}}let n=u?.(e.id,255,i);return{assignedSpool:n?.spool?{id:n.spool.id,material:n.spool.material,brand:n.spool.brand,color_name:n.spool.color_name,remainingWeightGrams:Math.max(0,Math.round(n.spool.label_weight-n.spool.weight_used))}:null,onAssignSpool:()=>wt({printerId:e.id,amsId:255,trayId:i,trayInfo:{type:t.tray_type||M.profile,material:t.tray_type??void 0,profile:M.profile,color:M.colorHex||``,location:a||P(`printers.external`)}}),onUnassignSpool:n&&!Sp(t)?()=>d?.(e.id,255,i):void 0,isAssigned:!!n||Sp(t)}})(),configureSlot:{enabled:R(`printers:control`),onConfigure:()=>Et({amsId:255,trayId:i,trayCount:1,trayType:t.tray_type||void 0,trayColor:t.tray_color||void 0,traySubBrands:t.tray_sub_brands||void 0,trayInfoIdx:t.tray_info_idx||void 0,extruderId:_?+(n===254):void 0,caliIdx:t.cali_idx,savedPresetId:v?.preset_id})},children:I})},n)})})]})]})]})})()]}),r===`expanded`&&(0,K.jsxs)(`div`,{className:`mt-auto`,children:[gn&&(0,K.jsxs)(`div`,{className:`pt-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] uppercase tracking-wider text-bambu-gray font-medium`,children:P(`printers.power`,`Power`)}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2 rounded-[10px] bg-bambu-dark p-2`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0 pl-1`,children:[(0,K.jsx)(Xu,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] text-bambu-gray flex-shrink-0`}),(0,K.jsx)(`span`,{className:`text-sm text-white truncate`,children:gn.name}),(0,K.jsx)(`span`,{className:`px-1.5 py-0.5 rounded-full bg-bambu-dark-tertiary text-bambu-gray text-[length:var(--pc-t10,10px)] font-medium flex-shrink-0`,title:P(`smartPlugs.power`),children:vn?.energy?.power!==null&&vn?.energy?.power!==void 0?`${Math.round(vn.energy.power)}W`:`--`})]}),(0,K.jsx)(`div`,{className:`flex-1`}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`button`,{onClick:()=>Un.mutate(!gn.auto_off),disabled:Un.isPending||gn.auto_off_executed||!R(`smart_plugs:control`),title:R(`smart_plugs:control`)?gn.auto_off_executed?P(`printers.autoOffExecuted`):P(`printers.autoOffAfterPrint`):P(`printers.permission.noSmartPlugControl`),className:`flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-xs font-bold transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${R(`smart_plugs:control`)?gn.auto_off||gn.auto_off_executed?`bg-bambu-green/20 text-bambu-green hover:bg-bambu-green/30`:`bg-bambu-dark-tertiary text-bambu-gray hover:text-white hover:bg-bambu-dark-tertiary/80`:`bg-bambu-dark-tertiary/50 text-bambu-gray/50`}`,children:(0,K.jsx)(Ts,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})}),(0,K.jsx)(`button`,{onClick:()=>{vn?.state===`ON`?le(!0):se(!0)},disabled:Hn.isPending||!R(`smart_plugs:control`),className:`flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg text-xs transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${R(`smart_plugs:control`)?vn?.state===`ON`?`bg-bambu-green/20 text-bambu-green hover:bg-bambu-green/30`:`bg-bambu-dark-tertiary text-bambu-gray hover:text-white hover:bg-bambu-dark-tertiary/80`:`bg-bambu-dark-tertiary/50 text-bambu-gray/50`}`,title:R(`smart_plugs:control`)?vn?.state===`ON`?`Turn off`:`Turn on`:P(`printers.permission.noSmartPlugControl`),children:(0,K.jsx)(Xu,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})})]})]}),_n&&_n.length>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mt-2`,children:[(0,K.jsx)(Pc,{className:`w-[var(--pc-i35,0.875rem)] h-[var(--pc-i35,0.875rem)] text-blue-600 dark:text-blue-400 flex-shrink-0`}),(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:`HA:`}),(0,K.jsx)(`div`,{className:`h-[2px] w-5 bg-bambu-dark-tertiary/50`}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:_n.map(e=>{let t=e.ha_entity_id?.startsWith(`script.`);return(0,K.jsxs)(`button`,{onClick:()=>{t?Wn.mutate({id:e.id,action:`on`}):de(e)},disabled:Wn.isPending,title:`${t?`Run`:`Toggle`} ${e.ha_entity_id}`,className:`px-2 py-0.5 text-xs bg-blue-100 dark:bg-blue-500/20 text-blue-700 dark:text-blue-400 hover:bg-blue-500/30 rounded transition-colors flex items-center gap-1`,children:[(0,K.jsx)(Dl,{className:`w-[var(--pc-i25,0.625rem)] h-[var(--pc-i25,0.625rem)]`}),e.name]},e.id)})})]})]}),(0,K.jsxs)(`div`,{className:`pt-4`,children:[(0,K.jsx)(`div`,{className:`mb-3 h-[2px] bg-bambu-dark-tertiary`}),(0,K.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[Jr,(0,K.jsxs)(`div`,{className:`flex items-center justify-end gap-2 flex-wrap`,children:[(0,K.jsx)($,{variant:`secondary`,size:`sm`,onClick:()=>{if(_===`embedded`&&v)v(e.id,e.name);else{let t=localStorage.getItem(`cameraWindowState`),n=t?JSON.parse(t):{width:640,height:400},r=[`width=${n.width}`,`height=${n.height}`,n.left===void 0?``:`left=${n.left}`,n.top===void 0?``:`top=${n.top}`,`menubar=no,toolbar=no,location=no,status=no`].filter(Boolean).join(`,`);window.open(`/camera/${e.id}`,`camera-${e.id}`,r)}},disabled:!G?.connected||!R(`camera:view`),title:R(`camera:view`)?P(_===`embedded`?`printers.openCameraOverlay`:`printers.openCameraWindow`):P(`printers.permission.noCamera`),className:Kr,children:(0,K.jsx)(Ru,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})}),(0,K.jsx)($,{variant:`secondary`,size:`sm`,onClick:()=>ie(!0),disabled:!rn||!R(`printers:files`),title:R(`printers:files`)?P(`printers.browseFiles`):P(`printers.permission.noFiles`),className:Kr,children:(0,K.jsx)(Oc,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`})}),rn&&G?.state!==`RUNNING`&&G?.state!==`PAUSE`&&(0,K.jsxs)($,{size:`sm`,onClick:()=>Be(!0),disabled:!R(`library:upload`)||!R(`queue:create`),title:R(`library:upload`)?R(`queue:create`)?P(`common.print`):P(`fileManager.noPermissionAddToQueue`):P(`fileManager.noPermissionUpload`),className:`!h-8 !min-h-8 !px-2 !py-0 !bg-bambu-green hover:!bg-bambu-green/80 !text-white`,children:[(0,K.jsx)(Ml,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)]`}),P(`common.print`)]})]})]})]})]})]}),U&&(0,K.jsx)(Ole,{printerId:e.id,printerName:e.name,onClose:()=>ie(!1)}),ze&&(0,K.jsx)(QU,{folderId:null,onClose:()=>Be(!1),onUploadComplete:()=>{},autoUpload:!0,accept:`.gcode,.3mf`,validateFile:e=>{let t=e.name.toLowerCase();if(!t.endsWith(`.gcode`)&&!t.includes(`.gcode.`))return P(`printers.dropNotPrintable`,`Only .gcode and .gcode.3mf files can be printed`)},onFileUploaded:t=>{let n=t.metadata?.sliced_for_model,r=IW(e.model);if(n&&r&&n.toLowerCase()!==r.toLowerCase())return Q.deleteLibraryFile(t.id).catch(()=>{}),P(`printers.incompatibleFile`,`This file was sliced for {{slicedFor}}, but this printer is a {{printerModel}}`,{slicedFor:n,printerModel:r});qe({id:t.id,filename:t.filename})}}),Ke&&(0,K.jsx)(gW,{mode:`create`,libraryFileId:Ke.id,archiveName:Ke.filename,initialSelectedPrinterIds:[e.id],onClose:()=>qe(null),onSuccess:()=>qe(null),cleanupLibraryAfterDispatch:!0}),ae&&(0,K.jsx)(Hle,{printerId:e.id,printerName:e.name,onClose:()=>W(!1)}),Ue&&(0,K.jsx)(jp,{printerId:e.id,printerName:e.name,onClose:()=>We(!1)}),Ve&&(0,K.jsx)(SAe,{printer:e,status:G,totalPrintHours:n?.total_print_hours,onClose:Ge}),kt&&(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:()=>Ar(),children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-xl shadow-2xl max-w-lg w-full`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[kt.needs_calibration?(0,K.jsx)(Ul,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)] text-blue-500`}):kt.is_empty?(0,K.jsx)(gs,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)] text-green-500`}):(0,K.jsx)(Ss,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)] text-yellow-500`}),(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:`Build Plate Check`}),kt.reference_count!==void 0&&kt.max_references&&(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray bg-bambu-dark-tertiary px-2 py-1 rounded`,children:[kt.reference_count,`/`,kt.max_references,` refs`]})]}),(0,K.jsx)(`button`,{onClick:()=>Ar(),className:`p-1 text-bambu-gray hover:text-white rounded transition-colors`,children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i5,1.25rem)] h-[var(--pc-i5,1.25rem)]`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-4`,children:[kt.needs_calibration?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`p-3 rounded-lg bg-blue-100 dark:bg-blue-500/20 border border-blue-300 dark:border-blue-500/50`,children:[(0,K.jsx)(`p`,{className:`font-medium text-blue-700 dark:text-blue-400`,children:P(`printers.plateDetection.calibrationRequired`)}),(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mt-1`,dangerouslySetInnerHTML:{__html:P(`printers.plateDetection.calibrationInstructions`)}})]}),(0,K.jsxs)(`div`,{className:`text-sm text-bambu-gray space-y-2`,children:[(0,K.jsx)(`p`,{children:P(`printers.plateDetection.calibrationDescription`)}),(0,K.jsx)(`p`,{dangerouslySetInnerHTML:{__html:P(`printers.plateDetection.calibrationTip`)}})]})]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`p-3 rounded-lg ${kt.is_empty?`bg-green-100 dark:bg-green-500/20 border border-green-300 dark:border-green-500/50`:`bg-yellow-100 dark:bg-yellow-500/20 border border-yellow-300 dark:border-yellow-500/50`}`,children:[(0,K.jsx)(`p`,{className:`font-medium ${kt.is_empty?`text-green-700 dark:text-green-400`:`text-yellow-700 dark:text-yellow-400`}`,children:kt.is_empty?P(`printers.plateDetection.plateEmpty`):P(`printers.plateDetection.objectsDetected`)}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray mt-1`,children:[P(`printers.plateDetection.confidence`),`: `,Math.round(kt.confidence*100),`% | `,P(`printers.plateDetection.difference`),`: `,kt.difference_percent.toFixed(1),`%`]})]}),kt.debug_image_url&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mb-2`,children:P(`printers.plateDetection.analysisPreview`)}),(0,K.jsx)(`img`,{src:kt.debug_image_url,alt:P(`printers.plateDetection.analysisPreview`),className:`w-full rounded-lg border border-bambu-dark-tertiary`}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-2`,children:P(`printers.plateDetection.analysisLegend`)})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:kt.message})]}),Cr&&Cr.references.length>0&&(0,K.jsxs)(`div`,{className:`mt-4`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,K.jsx)(`p`,{className:`text-sm font-medium text-white shrink-0`,children:P(`printers.plateDetection.savedReferences`,{count:Cr.references.length,max:Cr.max_references})}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`})]}),(0,K.jsx)(`div`,{className:`grid grid-cols-5 gap-2`,children:Cr.references.map(t=>(0,K.jsxs)(`div`,{className:`relative group`,children:[(0,K.jsx)(`img`,{src:Q.getPlateReferenceThumbnailUrl(e.id,t.index),alt:t.label||`Reference ${t.index+1}`,className:`w-full aspect-video object-cover rounded border border-bambu-dark-tertiary`}),(0,K.jsx)(`button`,{onClick:()=>Nr(t.index),className:`absolute top-1 right-1 p-0.5 bg-red-500/80 rounded opacity-0 group-hover:opacity-100 transition-opacity`,title:P(`printers.plateDetection.deleteReference`),children:(0,K.jsx)(Ju,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] text-white`})}),Tr?.index===t.index?(0,K.jsx)(`input`,{type:`text`,value:Tr.label,onChange:e=>Er({...Tr,label:e.target.value}),onBlur:()=>Mr(t.index,Tr.label),onKeyDown:e=>{e.key===`Enter`&&Mr(t.index,Tr.label),e.key===`Escape`&&Er(null)},className:`w-full mt-1 px-1 py-0.5 text-xs bg-bambu-dark-tertiary border border-bambu-green rounded text-white`,autoFocus:!0,placeholder:P(`printers.plateDetection.labelPlaceholder`)}):(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1 truncate cursor-pointer hover:text-white`,onClick:()=>Er({index:t.index,label:t.label}),title:t.label?P(`printers.plateDetection.clickToEdit`,{label:t.label}):P(`printers.plateDetection.clickToAddLabel`),children:t.label||(0,K.jsx)(`span`,{className:`italic opacity-50`,children:P(`printers.noLabel`)})}),(0,K.jsx)(`p`,{className:`text-[length:var(--pc-t10,10px)] text-bambu-gray/60`,children:t.timestamp?Vf(t.timestamp)?.toLocaleDateString()??``:``})]},t.index))})]}),!kt.needs_calibration&&(0,K.jsxs)(`div`,{className:`mt-4`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-2`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,K.jsx)(`p`,{className:`text-sm font-medium text-white shrink-0`,children:P(`printers.roi.title`)}),(0,K.jsx)(`div`,{className:`flex-1 h-[2px] bg-bambu-dark-tertiary`})]}),Ft?(0,K.jsxs)(`div`,{className:`flex gap-1`,children:[(0,K.jsx)($,{variant:`ghost`,size:`sm`,onClick:()=>It(null),disabled:Lt,children:P(`common.cancel`)}),(0,K.jsx)($,{size:`sm`,onClick:Pr,disabled:Lt,children:Lt?(0,K.jsx)(X,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] animate-spin`}):P(`common.save`)})]}):(0,K.jsxs)($,{variant:`ghost`,size:`sm`,onClick:()=>It(kt.roi||{x:.15,y:.35,w:.7,h:.55}),children:[(0,K.jsx)(Tl,{className:`w-[var(--pc-i3,0.75rem)] h-[var(--pc-i3,0.75rem)] mr-1`}),P(`common.edit`)]})]}),Ft?(0,K.jsxs)(`div`,{className:`space-y-3 bg-bambu-dark-tertiary/50 p-3 rounded-lg`,children:[(0,K.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.roi.xStart`)}),(0,K.jsx)(`input`,{type:`range`,min:`0`,max:`0.9`,step:`0.01`,value:Ft.x,onChange:e=>It({...Ft,x:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.x*100),`%`]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.roi.yStart`)}),(0,K.jsx)(`input`,{type:`range`,min:`0`,max:`0.9`,step:`0.01`,value:Ft.y,onChange:e=>It({...Ft,y:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.y*100),`%`]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.width`)}),(0,K.jsx)(`input`,{type:`range`,min:`0.1`,max:`1`,step:`0.01`,value:Ft.w,onChange:e=>It({...Ft,w:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.w*100),`%`]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-xs text-bambu-gray`,children:P(`printers.height`)}),(0,K.jsx)(`input`,{type:`range`,min:`0.1`,max:`1`,step:`0.01`,value:Ft.h,onChange:e=>It({...Ft,h:parseFloat(e.target.value)}),className:`w-full h-1.5 bg-bambu-dark-tertiary rounded-lg cursor-pointer accent-green-500`}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[Math.round(Ft.h*100),`%`]})]})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:P(`printers.roi.instruction`)})]}):(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray`,children:[`Current: X=`,Math.round((kt.roi?.x||.15)*100),`%, Y=`,Math.round((kt.roi?.y||.35)*100),`%, W=`,Math.round((kt.roi?.w||.7)*100),`%, H=`,Math.round((kt.roi?.h||.55)*100),`%`]})]})]}),(0,K.jsx)(`div`,{className:`flex justify-end gap-2 p-4`,children:kt.needs_calibration?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)($,{variant:`ghost`,onClick:()=>Ar(),children:P(`common.cancel`)}),(0,K.jsx)($,{onClick:()=>jr(),disabled:Nt,children:Nt?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-[var(--pc-i4,1rem)] h-[var(--pc-i4,1rem)] mr-2 animate-spin`}),`Calibrating...`]}):`Calibrate Empty Plate`})]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)($,{variant:`ghost`,onClick:()=>jr(),disabled:Nt,children:Nt?`Adding...`:`Add Reference (${Cr?.references.length||0}/${Cr?.max_references||5})`}),(0,K.jsx)($,{onClick:()=>Ar(),children:`Close`})]})})]})}),oe&&gn&&(0,K.jsx)(Kd,{title:P(`printers.confirm.powerOnTitle`),message:P(`printers.confirm.powerOnMessage`,{name:e.name}),confirmText:P(`printers.confirm.powerOnButton`),variant:`default`,onConfirm:()=>{Hn.mutate(`on`),se(!1)},onCancel:()=>se(!1)}),ur&&(0,K.jsx)(Kd,{title:P(`printers.maintenance.confirmMidPrintTitle`),message:P(`printers.maintenance.confirmMidPrintMessage`,{name:e.name}),confirmText:P(`printers.maintenance.menuEnter`),variant:`danger`,onConfirm:()=>{lr.mutate(!1),dr(!1)},onCancel:()=>dr(!1)}),ce&&gn&&(0,K.jsx)(Kd,{title:P(`printers.confirm.powerOffTitle`),message:G?.state===`RUNNING`?P(`printers.confirm.powerOffWarning`,{name:e.name}):P(`printers.confirm.powerOffMessage`,{name:e.name}),confirmText:P(`printers.confirm.powerOffButton`),variant:`danger`,onConfirm:()=>{Hn.mutate(`off`),le(!1)},onCancel:()=>le(!1)}),ue&&(0,K.jsx)(Kd,{title:P(`printers.confirm.haToggleTitle`,{name:ue.name}),message:G?.state===`RUNNING`?P(`printers.confirm.haToggleWarning`,{name:e.name,entity:ue.ha_entity_id||ue.name}):P(`printers.confirm.haToggleMessage`,{entity:ue.ha_entity_id||ue.name}),confirmText:P(`printers.confirm.haToggleButton`),variant:G?.state===`RUNNING`?`danger`:`default`,onConfirm:()=>{Wn.mutate({id:ue.id,action:`toggle`}),de(null)},onCancel:()=>de(null)}),xe&&(0,K.jsx)(Kd,{title:P(`printers.confirm.stopTitle`),message:P(`printers.confirm.stopMessage`,{name:e.name}),confirmText:P(`printers.confirm.stopButton`),variant:`danger`,onConfirm:()=>{Gn.mutate(),Se(!1)},onCancel:()=>Se(!1)}),Ce&&(0,K.jsx)(Kd,{title:P(`printers.confirm.pauseTitle`),message:P(`printers.confirm.pauseMessage`,{name:e.name}),confirmText:P(`printers.confirm.pauseButton`),variant:`default`,onConfirm:()=>{Kn.mutate(),we(!1)},onCancel:()=>we(!1)}),Fe&&(0,K.jsx)(Kd,{title:P(`printers.confirm.resumeTitle`),message:P(`printers.confirm.resumeMessage`,{name:e.name}),confirmText:P(`printers.confirm.resumeButton`),variant:`default`,onConfirm:()=>{qn.mutate(),Ie(!1)},onCancel:()=>Ie(!1)}),(0,K.jsx)(kT,{printerId:e.id,isOpen:Le,onClose:()=>Re(!1)}),fe&&(0,K.jsx)(vee,{printerName:e.name,errors:G?.hms_errors||[],onClose:()=>pe(!1),printerId:e.id,hasPermission:R,runoutGuidance:hn}),me&&(0,K.jsx)(Ule,{printerName:e.name,detection:M,lastError:N,onClose:()=>he(!1)}),ge&&G&&(0,K.jsx)(zke,{isOpen:ge,state:G.ams_filament_backup,amsUnits:G.ams,amsExtruderMap:G.ams_extruder_map,isDualNozzle:e.nozzle_count===2||G?.temperatures?.nozzle_2!==void 0,canToggle:R(`printers:control`),pending:Vn.isPending,onToggle:e=>Vn.mutate(e),onClose:()=>_e(!1)}),_t&&(0,K.jsx)(Fke,{isOpen:!!_t,onClose:()=>vt(null),printerId:e.id,printerName:e.name,amsId:_t.amsId,amsLabel:_t.amsLabel,initialMode:_t.mode,thresholds:a}),yt&&(0,K.jsx)(Vke,{isOpen:!!yt,onClose:()=>bt(null),printerId:e.id,printerName:e.name,initialKind:yt.initialKind,availableKinds:yt.availableKinds}),xt&&(0,K.jsx)(fU,{isOpen:!!xt,onClose:()=>St(null),tagUid:xt.tagUid,trayUuid:xt.trayUuid,printerId:xt.printerId,amsId:xt.amsId,trayId:xt.trayId}),Ct&&(0,K.jsx)(mU,{isOpen:!!Ct,onClose:()=>wt(null),printerId:Ct.printerId,amsId:Ct.amsId,trayId:Ct.trayId,trayInfo:Ct.trayInfo,spoolmanEnabled:!!o}),Tt&&(0,K.jsx)(XU,{isOpen:!!Tt,onClose:()=>Et(null),printerId:e.id,slotInfo:Tt,printerModel:IW(e.model)||void 0,nozzleDiameter:xp(G,Tt.amsId),onSuccess:()=>{F.invalidateQueries({queryKey:[`slotPresets`,e.id]}),F.invalidateQueries({queryKey:[`printerStatus`,e.id]})}}),ne&&(0,K.jsx)(KAe,{printer:e,onClose:()=>re(!1)}),Dt&&Vt&&(0,K.jsx)(GAe,{printer:e,firmwareInfo:Vt,onClose:()=>Ot(!1)}),Je!==null&&st&&(()=>{let e=Xe===`n3s`?85:65,t=e+10;return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`div`,{className:`fixed inset-0 z-[100]`,onClick:()=>Ye(null)}),(0,K.jsxs)(`div`,{className:`fixed z-[101] flex flex-col w-[240px] bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-xl shadow-2xl overflow-hidden`,style:{top:st.top,left:st.left,maxHeight:`calc(100dvh - ${st.top}px - 8px)`},onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`shrink-0 flex items-center justify-center gap-2 px-3 py-2.5`,children:[(0,K.jsx)(lc,{className:`w-[var(--pc-i35,0.875rem)] h-[var(--pc-i35,0.875rem)] text-bambu-green`}),(0,K.jsx)(`span`,{className:`text-sm text-white font-medium text-center`,children:P(`printers.drying.start`)})]}),(0,K.jsx)(`div`,{className:`shrink-0 h-px bg-bambu-dark-tertiary`}),(0,K.jsxs)(`div`,{className:`px-3 py-2.5 space-y-2.5 overflow-y-auto min-h-0`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`text-[length:var(--pc-t10,10px)] text-white/70 font-medium mb-1 block`,children:P(`printers.filaments`)}),(0,K.jsx)(AW,{value:Qe,options:Object.keys(x).map(e=>({value:e,label:e})),onChange:e=>{et(e);let t=x[e];t&&(nt(t[Xe===`n3s`?`n3s`:`n3f`]),it(Xe===`n3s`?t.n3s_hours:t.n3f_hours))},fullWidth:!0})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-1`,children:[(0,K.jsx)(`label`,{className:`text-[length:var(--pc-t10,10px)] text-white/70 font-medium`,children:P(`printers.drying.temperature`)}),(0,K.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,K.jsx)(`input`,{type:`number`,min:45,max:e,value:tt,onChange:t=>nt(Math.min(e,Math.max(45,Number(t.target.value)||45))),className:`w-12 px-1 py-0.5 bg-bambu-dark border border-bambu-dark-tertiary rounded text-white text-[length:var(--pc-t11,11px)] text-center focus:outline-none focus:border-bambu-green [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`}),(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] text-bambu-gray`,children:`°C`})]})]}),(0,K.jsx)(`input`,{type:`range`,min:35,max:t,value:tt,onChange:t=>nt(Math.min(e,Math.max(45,Number(t.target.value)))),className:`w-full h-1 accent-bambu-green cursor-pointer`}),(0,K.jsxs)(`div`,{className:`flex justify-between text-[length:var(--pc-t9,9px)] text-bambu-gray/50 mt-0.5`,children:[(0,K.jsx)(`span`,{children:`45°C`}),(0,K.jsxs)(`span`,{children:[e,`°C`]})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-1`,children:[(0,K.jsx)(`label`,{className:`text-[length:var(--pc-t10,10px)] text-white/70 font-medium`,children:P(`printers.drying.duration`)}),(0,K.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,K.jsx)(`input`,{type:`number`,min:1,max:24,value:rt,onChange:e=>it(Math.min(24,Math.max(1,Number(e.target.value)||1))),className:`w-10 px-1 py-0.5 bg-bambu-dark border border-bambu-dark-tertiary rounded text-white text-[length:var(--pc-t11,11px)] text-center focus:outline-none focus:border-bambu-green [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`}),(0,K.jsx)(`span`,{className:`text-[length:var(--pc-t10,10px)] text-bambu-gray`,children:P(`printers.drying.hours`)})]})]}),(0,K.jsx)(`input`,{type:`range`,min:1,max:24,value:rt,onChange:e=>it(Number(e.target.value)),className:`w-full h-1 accent-bambu-green cursor-pointer`}),(0,K.jsxs)(`div`,{className:`flex justify-between text-[length:var(--pc-t9,9px)] text-bambu-gray/50 mt-0.5`,children:[(0,K.jsx)(`span`,{children:`1h`}),(0,K.jsx)(`span`,{children:`24h`})]})]}),(()=>{let e=((Je===null?void 0:cn.find(e=>e.id===Je))?.tray??[]).some(e=>e.state===11),t=at&&!e;return(0,K.jsx)(`button`,{type:`button`,onClick:()=>ot(e=>!e),"aria-pressed":t,disabled:e,title:e?P(`printers.drying.rotateUnavailableReason`):void 0,className:`h-8 w-full rounded-lg border px-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${t?`bg-bambu-green border-bambu-green text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary disabled:hover:bg-bambu-dark`}`,children:P(`printers.drying.rotateTray`)})})()]}),(0,K.jsx)(`div`,{className:`shrink-0 h-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`shrink-0 px-3 pt-2.5 pb-3`,children:(0,K.jsx)(`button`,{onClick:()=>{if(Je!==null){let e=(cn.find(e=>e.id===Je)?.tray??[]).some(e=>e.state===11);zn.mutate({amsId:Je,temp:tt,duration:rt,filament:Qe,rotateTray:at&&!e})}},disabled:zn.isPending,"data-testid":`drying-start-confirm`,className:`w-full py-1.5 bg-bambu-green hover:bg-bambu-green/80 text-white text-xs font-medium rounded-lg transition-colors disabled:opacity-50`,children:zn.isPending?P(`printers.drying.startingDrying`):P(`printers.drying.start`)})})]})]})})()]})}function WAe({onClose:e,onAdd:t,existingSerials:n}){let{t:r}=$e(),[i,a]=(0,y.useState)({name:``,serial_number:``,ip_address:``,access_code:``,model:``,location:``,auto_archive:!0}),[o,s]=(0,y.useState)(!1),[c,l]=(0,y.useState)([]),[u,d]=(0,y.useState)(``),[f,p]=(0,y.useState)(!1),[m,h]=(0,y.useState)(!1),[g,_]=(0,y.useState)([]),[v,b]=(0,y.useState)(``),[x,S]=(0,y.useState)(``),[C,w]=(0,y.useState)(!1),[T,E]=(0,y.useState)({scanned:0,total:0}),[D,O]=(0,y.useState)(!1),[k,A]=(0,y.useState)(!1),[j,M]=(0,y.useState)(null);(0,y.useEffect)(()=>{ud.getInfo().then(e=>{h(e.is_docker),e.subnets.length>0&&(_(e.subnets),b(e.subnets[0]))}).catch(()=>{});try{let e=localStorage.getItem(`bambuddy.discovery.customSubnet`);e&&S(e)}catch{}},[]);let N=c.filter(e=>!n.includes(e.serial)),P=async e=>{e.preventDefault(),A(!0);try{let e=await Q.diagnoseConnection({ip_address:i.ip_address.trim(),serial_number:i.serial_number.trim()||void 0,access_code:i.access_code||void 0});if(e.checks.some(e=>e.status===`fail`)){M(e);return}}catch{}finally{A(!1)}t(i)},F=async()=>{d(``),l([]),s(!0),p(!1),E({scanned:0,total:0});let e=C?x.trim():v,t=m||C;if(t&&C)try{localStorage.setItem(`bambuddy.discovery.customSubnet`,e)}catch{}try{if(t){await ud.startSubnetScan(e);let t=setInterval(async()=>{try{let e=await ud.getScanStatus();E({scanned:e.scanned,total:e.total}),l(await ud.getDiscoveredPrinters()),e.running||(clearInterval(t),s(!1),p(!0))}catch(e){console.error(`Failed to get scan status:`,e)}},500)}else{await ud.startDiscovery(10);let e=setInterval(async()=>{try{l(await ud.getDiscoveredPrinters())}catch(e){console.error(`Failed to get discovered printers:`,e)}},1e3);setTimeout(async()=>{clearInterval(e);try{await ud.stopDiscovery()}catch{}s(!1),p(!0);try{l(await ud.getDiscoveredPrinters())}catch(e){console.error(`Failed to get final discovered printers:`,e)}},1e4)}}catch(e){console.error(`Failed to start discovery:`,e),d(e instanceof Error?e.message:r(`printers.discovery.failedToStart`)),s(!1),p(!0)}},I=e=>{let t=e.serial.startsWith(`unknown-`)?``:e.serial;a({...i,name:e.name||``,serial_number:t,ip_address:e.ip_address,model:IW(e.model)}),l([])};return(0,y.useEffect)(()=>()=>{ud.stopDiscovery().catch(()=>{}),ud.stopSubnetScan().catch(()=>{})},[]),(0,y.useEffect)(()=>{let t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]),(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-start sm:items-center justify-center z-50 p-4 overflow-y-auto`,onClick:e,children:(0,K.jsx)(Dd,{className:`w-full max-w-md my-auto max-h-[calc(100vh-2rem)] overflow-y-auto`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{children:[(0,K.jsx)(`h2`,{className:`text-xl font-semibold mb-4`,children:r(`printers.addPrinter`)}),(0,K.jsxs)(`div`,{className:`mb-4 pb-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`mb-3`,children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.discovery.subnetToScan`)}),g.length>0?(0,K.jsxs)(`select`,{className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm`,value:C?`__custom__`:v,onChange:e=>{e.target.value===`__custom__`?w(!0):(w(!1),b(e.target.value))},disabled:o,children:[g.map(e=>(0,K.jsx)(`option`,{value:e,children:e},e)),(0,K.jsx)(`option`,{value:`__custom__`,children:r(`printers.discovery.customSubnetOption`)})]}):(0,K.jsx)(`input`,{type:`text`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm`,value:v,onChange:e=>b(e.target.value),placeholder:`192.168.1.0/24`,disabled:o}),C&&(0,K.jsx)(`input`,{type:`text`,"aria-label":r(`printers.discovery.customSubnetLabel`),className:`mt-2 w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm`,value:x,onChange:e=>S(e.target.value),placeholder:`10.1.1.0/24`,disabled:o}),(0,K.jsx)(`p`,{className:`mt-1 text-xs text-bambu-gray`,children:r(m?`printers.discovery.dockerNote`:`printers.discovery.customSubnetNote`)})]}),(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:F,disabled:o,className:`w-full`,children:o?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),(m||C)&&T.total>0?r(`printers.discovery.scanProgress`,{scanned:T.scanned,total:T.total}):r(`printers.discovery.scanning`)]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(Gl,{className:`w-4 h-4`}),r(m||C?`printers.discovery.scanSubnet`:`printers.discovery.discoverNetwork`)]})}),u&&(0,K.jsx)(`div`,{className:`mt-2 text-sm text-red-700 dark:text-red-400`,children:u}),N.length>0&&(0,K.jsx)(`div`,{className:`mt-3 space-y-2 max-h-40 overflow-y-auto`,children:N.map(e=>(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-2 bg-bambu-dark rounded-lg hover:bg-bambu-dark-secondary cursor-pointer transition-colors`,onClick:()=>I(e),children:[(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`font-medium text-white text-sm truncate`,children:e.name||e.serial}),(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray truncate`,children:[IW(e.model)||r(`printers.discovery.unknown`),` • `,e.ip_address,e.serial.startsWith(`unknown-`)&&(0,K.jsxs)(`span`,{className:`text-yellow-500`,children:[` • `,r(`printers.discovery.serialRequired`)]})]})]}),(0,K.jsx)(cs,{className:`w-4 h-4 text-bambu-gray -rotate-90 flex-shrink-0 ml-2`})]},e.serial))}),o&&(0,K.jsx)(`p`,{className:`mt-2 text-sm text-bambu-gray text-center`,children:r(m||C?`printers.discovery.scanningSubnet`:`printers.discovery.scanningNetwork`)}),f&&!o&&c.length===0&&(0,K.jsx)(`p`,{className:`mt-2 text-sm text-bambu-gray text-center`,children:r(m||C?`printers.discovery.noPrintersFoundSubnet`:`printers.discovery.noPrintersFoundNetwork`)}),f&&!o&&c.length>0&&N.length===0&&(0,K.jsx)(`p`,{className:`mt-2 text-sm text-bambu-gray text-center`,children:r(`printers.discovery.allConfigured`)})]}),(0,K.jsxs)(`form`,{onSubmit:P,className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.name`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.name,onChange:e=>a({...i,name:e.target.value}),placeholder:r(`printers.modal.myPrinter`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.ipAddress`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,pattern:`(\\d{1,3}(\\.\\d{1,3}){3}|[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*)`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.ip_address,onChange:e=>a({...i,ip_address:e.target.value}),placeholder:`192.168.1.100 or printer.local`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.serialNumber`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.serial_number,onChange:e=>a({...i,serial_number:e.target.value}),placeholder:`01P00A000000000`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.accessCode`)}),(0,K.jsx)(`input`,{type:`password`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.access_code,onChange:e=>a({...i,access_code:e.target.value}),placeholder:r(`printers.modal.fromPrinterSettings`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.modal.modelOptional`)}),(0,K.jsxs)(`select`,{className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.model||``,onChange:e=>a({...i,model:e.target.value}),children:[(0,K.jsx)(`option`,{value:``,children:r(`printers.modal.selectModel`)}),(0,K.jsxs)(`optgroup`,{label:`A1 Series`,children:[(0,K.jsx)(`option`,{value:`A1`,children:`A1`}),(0,K.jsx)(`option`,{value:`A1 Mini`,children:`A1 Mini`})]}),(0,K.jsx)(`optgroup`,{label:`A2 Series`,children:(0,K.jsx)(`option`,{value:`A2L`,children:`A2L`})}),(0,K.jsxs)(`optgroup`,{label:`H2 Series`,children:[(0,K.jsx)(`option`,{value:`H2C`,children:`H2C`}),(0,K.jsx)(`option`,{value:`H2D`,children:`H2D`}),(0,K.jsx)(`option`,{value:`H2D Pro`,children:`H2D Pro`}),(0,K.jsx)(`option`,{value:`H2S`,children:`H2S`})]}),(0,K.jsxs)(`optgroup`,{label:`P Series`,children:[(0,K.jsx)(`option`,{value:`P1P`,children:`P1P`}),(0,K.jsx)(`option`,{value:`P1S`,children:`P1S`}),(0,K.jsx)(`option`,{value:`P2S`,children:`P2S`})]}),(0,K.jsxs)(`optgroup`,{label:`X1 Series`,children:[(0,K.jsx)(`option`,{value:`X1`,children:`X1`}),(0,K.jsx)(`option`,{value:`X1C`,children:`X1 Carbon`}),(0,K.jsx)(`option`,{value:`X1E`,children:`X1E`})]}),(0,K.jsx)(`optgroup`,{label:`X2 Series`,children:(0,K.jsx)(`option`,{value:`X2D`,children:`X2D`})})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`printers.modal.locationGroup`)}),(0,K.jsx)(`input`,{type:`text`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:i.location||``,onChange:e=>a({...i,location:e.target.value}),placeholder:r(`printers.modal.locationPlaceholder`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`printers.locationHelp`)})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`input`,{type:`checkbox`,id:`auto_archive`,checked:i.auto_archive,onChange:e=>a({...i,auto_archive:e.target.checked}),className:`rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green`}),(0,K.jsx)(`label`,{htmlFor:`auto_archive`,className:`text-sm text-bambu-gray`,children:r(`printers.modal.autoArchiveLabel`)})]}),(0,K.jsxs)(`button`,{type:`button`,onClick:()=>O(!0),disabled:!i.ip_address.trim(),className:`w-full flex items-center justify-center gap-2 px-3 py-2 text-sm text-bambu-gray hover:text-white disabled:opacity-40 disabled:cursor-not-allowed border border-bambu-dark-tertiary rounded-lg transition-colors`,children:[(0,K.jsx)(hu,{className:`w-4 h-4`}),r(`diagnostic.runButton`)]}),j?(0,K.jsxs)(`div`,{className:`rounded-lg bg-amber-50 dark:bg-amber-500/10 border border-amber-300 dark:border-amber-500/30 p-3 space-y-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,K.jsx)(Au,{className:`w-4 h-4 mt-0.5 flex-shrink-0 text-amber-600 dark:text-amber-400`}),(0,K.jsx)(`p`,{className:`text-sm text-amber-700 dark:text-amber-300`,children:r(`printers.addPreflight.warning`)})]}),(0,K.jsx)(kp,{result:j}),(0,K.jsxs)(`div`,{className:`flex gap-3`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:()=>M(null),className:`flex-1`,children:r(`printers.addPreflight.back`)}),(0,K.jsx)($,{type:`button`,onClick:()=>t(i),className:`flex-1`,children:r(`printers.addPreflight.saveAnyway`)})]})]}):(0,K.jsxs)(`div`,{className:`flex gap-3 pt-2`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:e,className:`flex-1`,children:r(`common.cancel`)}),(0,K.jsx)($,{type:`submit`,disabled:k,className:`flex-1`,children:r(k?`printers.addPreflight.checking`:`printers.addPrinter`)})]})]})]})})}),D&&(0,K.jsx)(jp,{connection:{ip_address:i.ip_address.trim(),serial_number:i.serial_number.trim()||void 0,access_code:i.access_code||void 0},printerName:i.name||null,onClose:()=>O(!1)})]})}function GAe({printer:e,firmwareInfo:t,onClose:n}){let{t:r}=$e(),i=ao(),{showToast:a}=Pd(),{hasPermission:o}=xd(),s=o(`firmware:update`),[c,l]=(0,y.useState)(null),[u,d]=(0,y.useState)(!1),[f,p]=(0,y.useState)(null),[m,h]=(0,y.useState)(t.update_available?t.latest_version:null),{data:g,isLoading:_}=q({queryKey:[`firmwarePrepare`,e.id,m],queryFn:()=>md.prepareUpload(e.id,m??void 0),staleTime:3e4,enabled:!!m&&s&&!u}),v=J({mutationFn:()=>md.startUpload(e.id,m??void 0),onSuccess:()=>{d(!0);let t=setInterval(async()=>{try{let n=await md.getUploadStatus(e.id);l(n),(n.status===`complete`||n.status===`error`)&&(clearInterval(t),p(null),d(!1),n.status===`complete`&&(a(r(`printers.firmwareModal.uploadedToast`),`success`),i.invalidateQueries({queryKey:[`firmwareUpdate`,e.id]})))}catch{}},2e3);p(t)},onError:e=>{a(r(`printers.firmwareModal.uploadFailed`,{error:e.message}),`error`),d(!1)}});return(0,y.useEffect)(()=>()=>{f&&clearInterval(f)},[f]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50`,children:(0,K.jsx)(Dd,{className:`w-full max-w-md mx-4`,children:(0,K.jsxs)(kd,{children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-3 mb-4`,children:[(0,K.jsx)(`div`,{className:`p-2 rounded-full ${t.update_available?`bg-orange-100 dark:bg-orange-500/20`:`bg-status-ok/20`}`,children:t.update_available?(0,K.jsx)(Gs,{className:`w-5 h-5 text-orange-600 dark:text-orange-400`}):(0,K.jsx)(gs,{className:`w-5 h-5 text-status-ok`})}),(0,K.jsxs)(`div`,{className:`flex-1`,children:[(0,K.jsx)(`h3`,{className:`text-lg font-semibold text-white`,children:t.update_available?r(`printers.firmwareModal.title`):r(`printers.firmwareModal.titleUpToDate`)}),(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mt-1`,children:e.name})]})]}),(()=>{let e=m?t.available_versions?.find(e=>e.version===m):null,n=m??t.latest_version,i=e?.release_notes??t.release_notes,a=!!n&&n!==t.current_version;return(0,K.jsxs)(`div`,{className:`bg-bambu-dark rounded-lg p-3 mb-4`,children:[(0,K.jsxs)(`div`,{className:`flex justify-between items-center text-sm`,children:[(0,K.jsx)(`span`,{className:`text-bambu-gray`,children:r(`printers.firmwareModal.currentVersion`)}),(0,K.jsx)(`span`,{className:`font-mono ${a?`text-white`:`text-status-ok`}`,children:t.current_version||r(`common.unknown`)})]}),a&&(0,K.jsxs)(`div`,{className:`flex justify-between items-center text-sm mt-1`,children:[(0,K.jsx)(`span`,{className:`text-bambu-gray`,children:r(`printers.firmwareModal.latestVersion`)}),(0,K.jsx)(`span`,{className:`text-orange-700 dark:text-orange-400 font-mono`,children:n})]}),i&&(0,K.jsxs)(`details`,{className:`mt-3 text-sm`,open:!a,children:[(0,K.jsx)(`summary`,{className:`cursor-pointer hover:underline ${a?`text-orange-700 dark:text-orange-400`:`text-status-ok`}`,children:r(`printers.firmwareModal.releaseNotes`)}),(0,K.jsx)(`div`,{className:`mt-2 text-bambu-gray text-xs max-h-40 overflow-y-auto whitespace-pre-wrap`,children:i})]},n??`none`)]})})(),t.available_versions&&t.available_versions.length>0&&!u&&c?.status!==`complete`&&(0,K.jsxs)(`div`,{className:`mb-4`,children:[(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray mb-2`,children:r(`printers.firmwareModal.availableVersions`)}),(0,K.jsx)(`div`,{className:`max-h-56 overflow-y-auto border border-bambu-dark-tertiary rounded-lg divide-y divide-bambu-dark-tertiary`,children:t.available_versions.map(e=>{let n=t.current_version===e.version,i=m===e.version,a=t.current_version?lee(e.version,t.current_version):0,o=r(n?`printers.firmwareModal.currentBadge`:a>0?`printers.firmwareModal.newerBadge`:`printers.firmwareModal.olderBadge`),c=n?`text-bambu-gray`:a>0?`text-orange-700 dark:text-orange-400`:`text-blue-700 dark:text-blue-400`;return(0,K.jsxs)(`button`,{type:`button`,disabled:!e.file_available||!s||n,onClick:()=>h(e.version),className:`w-full text-left px-3 py-2 text-sm flex items-center justify-between gap-2 transition-colors ${i?`bg-orange-50 dark:bg-orange-500/10`:`hover:bg-bambu-dark`} ${!e.file_available||!s||n?`opacity-60 cursor-not-allowed`:`cursor-pointer`}`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,K.jsx)(`span`,{className:`font-mono text-white`,children:e.version}),(0,K.jsx)(`span`,{className:`text-xs ${c}`,children:o})]}),(0,K.jsx)(`span`,{className:`text-xs px-2 py-0.5 rounded-full ${n?`bg-blue-50 dark:bg-blue-500/15 text-blue-700 dark:text-blue-400 border border-blue-300 dark:border-blue-500/30`:e.file_available?`bg-bambu-green/15 text-bambu-green border border-bambu-green/30`:`bg-bambu-gray/10 text-bambu-gray border border-bambu-gray/30`}`,children:n?r(`printers.firmwareModal.installed`):e.file_available?r(`printers.firmwareModal.usable`):r(`printers.firmwareModal.unavailable`)})]},e.version)})})]}),m?_?(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-bambu-gray text-sm mb-4`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),r(`printers.firmwareModal.checkingPrereqs`)]}):g&&!u&&!c?(0,K.jsx)(`div`,{className:`mb-4`,children:g.can_proceed?(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-bambu-green text-sm`,children:[(0,K.jsx)(qo,{className:`w-4 h-4`}),r(`printers.firmwareModal.sdCardReady`)]}):(0,K.jsx)(`div`,{className:`space-y-1`,children:g.errors.map((e,t)=>(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-red-700 dark:text-red-400 text-sm`,children:[(0,K.jsx)(ms,{className:`w-4 h-4 flex-shrink-0`}),e]},t))})}):null:null,(u||c)&&c&&(0,K.jsxs)(`div`,{className:`mb-4`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between text-sm mb-1`,children:[(0,K.jsx)(`span`,{className:`text-bambu-gray capitalize`,children:c.status}),(0,K.jsxs)(`span`,{className:`text-white`,children:[c.progress,`%`]})]}),(0,K.jsx)(`div`,{className:`w-full bg-bambu-dark-tertiary rounded-full h-2`,children:(0,K.jsx)(`div`,{className:`h-2 rounded-full transition-all ${c.status===`error`?`bg-status-error`:c.status===`complete`?`bg-status-ok`:`bg-orange-500`} ${c.status===`uploading`?`animate-pulse`:``}`,style:{width:`${c.progress}%`}})}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:c.message}),c.error&&(0,K.jsx)(`p`,{className:`text-xs text-red-700 dark:text-red-400 mt-1`,children:c.error})]}),c?.status===`complete`&&(0,K.jsxs)(`div`,{className:`bg-bambu-green/10 border border-bambu-green/30 rounded-lg p-3 mb-4`,children:[(0,K.jsx)(`p`,{className:`text-sm text-bambu-green font-medium mb-2`,children:r(`printers.firmwareModal.uploadedSuccess`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:r(`printers.firmwareModal.applyInstructions`)}),(0,K.jsxs)(`ol`,{className:`text-xs text-bambu-gray mt-1 list-decimal list-inside space-y-1`,children:[(0,K.jsx)(`li`,{dangerouslySetInnerHTML:{__html:r(`printers.firmwareModal.step1`)}}),(0,K.jsx)(`li`,{dangerouslySetInnerHTML:{__html:r(`printers.firmwareModal.step2`)}}),(0,K.jsx)(`li`,{dangerouslySetInnerHTML:{__html:r(`printers.firmwareModal.step3`)}}),(0,K.jsx)(`li`,{children:r(`printers.firmwareModal.step4`)})]})]}),(0,K.jsxs)(`div`,{className:`flex gap-2 justify-end`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:n,children:c?.status===`complete`?r(`printers.firmwareModal.done`):r(`common.cancel`)}),g?.can_proceed&&!u&&c?.status!==`complete`&&s&&(0,K.jsx)($,{onClick:()=>{l(null),v.mutate()},disabled:v.isPending,children:v.isPending?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin mr-2`}),r(`printers.firmwareModal.starting`)]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(Gs,{className:`w-4 h-4 mr-2`}),r(`printers.firmwareModal.uploadFirmware`)]})})]})]})})})}function KAe({printer:e,onClose:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)({name:e.name,ip_address:e.ip_address,access_code:``,model:e.model||``,location:e.location||``,auto_archive:e.auto_archive,is_active:e.is_active}),[s,c]=(0,y.useState)(!1),[l,u]=(0,y.useState)(null),d=J({mutationFn:t=>Q.updatePrinter(e.id,t),onSuccess:()=>{r.invalidateQueries({queryKey:[`printers`]}),r.invalidateQueries({queryKey:[`printerStatus`,e.id]}),t()},onError:e=>i(e.message||n(`printers.toast.failedToUpdate`),`error`)});(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let f=()=>{let e={name:a.name,ip_address:a.ip_address,model:a.model||void 0,location:a.location||void 0,auto_archive:a.auto_archive,is_active:a.is_active};a.access_code&&(e.access_code=a.access_code),d.mutate(e)};return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-start sm:items-center justify-center z-50 p-4 overflow-y-auto`,onClick:t,children:(0,K.jsx)(Dd,{className:`w-full max-w-md my-auto max-h-[calc(100vh-2rem)] overflow-y-auto`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{children:[(0,K.jsx)(`h2`,{className:`text-xl font-semibold mb-4`,children:n(`printers.editPrinter`)}),(0,K.jsxs)(`form`,{onSubmit:async t=>{t.preventDefault(),c(!0);try{let t=await Q.diagnoseConnection({ip_address:a.ip_address.trim(),serial_number:e.serial_number,access_code:a.access_code||void 0});if(t.checks.some(e=>e.status===`fail`)){u(t);return}}catch{}finally{c(!1)}f()},className:`space-y-4`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.name`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.name,onChange:e=>o({...a,name:e.target.value}),placeholder:n(`printers.modal.myPrinter`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.ipAddress`)}),(0,K.jsx)(`input`,{type:`text`,required:!0,pattern:`(\\d{1,3}(\\.\\d{1,3}){3}|[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*)`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.ip_address,onChange:e=>o({...a,ip_address:e.target.value}),placeholder:`192.168.1.100 or printer.local`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.serialNumber`)}),(0,K.jsx)(`input`,{type:`text`,disabled:!0,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-bambu-gray cursor-not-allowed`,value:e.serial_number}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:n(`printers.serialCannotBeChanged`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.accessCode`)}),(0,K.jsx)(`input`,{type:`password`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.access_code,onChange:e=>o({...a,access_code:e.target.value}),placeholder:n(`printers.accessCodePlaceholder`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:n(`printers.model`)}),(0,K.jsxs)(`select`,{className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.model,onChange:e=>o({...a,model:e.target.value}),children:[(0,K.jsx)(`option`,{value:``,children:n(`printers.modal.selectModel`)}),(0,K.jsxs)(`optgroup`,{label:`A1 Series`,children:[(0,K.jsx)(`option`,{value:`A1`,children:`A1`}),(0,K.jsx)(`option`,{value:`A1 Mini`,children:`A1 Mini`})]}),(0,K.jsx)(`optgroup`,{label:`A2 Series`,children:(0,K.jsx)(`option`,{value:`A2L`,children:`A2L`})}),(0,K.jsxs)(`optgroup`,{label:`H2 Series`,children:[(0,K.jsx)(`option`,{value:`H2C`,children:`H2C`}),(0,K.jsx)(`option`,{value:`H2D`,children:`H2D`}),(0,K.jsx)(`option`,{value:`H2D Pro`,children:`H2D Pro`}),(0,K.jsx)(`option`,{value:`H2S`,children:`H2S`})]}),(0,K.jsxs)(`optgroup`,{label:`P Series`,children:[(0,K.jsx)(`option`,{value:`P1P`,children:`P1P`}),(0,K.jsx)(`option`,{value:`P1S`,children:`P1S`}),(0,K.jsx)(`option`,{value:`P2S`,children:`P2S`})]}),(0,K.jsxs)(`optgroup`,{label:`X1 Series`,children:[(0,K.jsx)(`option`,{value:`X1`,children:`X1`}),(0,K.jsx)(`option`,{value:`X1C`,children:`X1 Carbon`}),(0,K.jsx)(`option`,{value:`X1E`,children:`X1E`})]}),(0,K.jsx)(`optgroup`,{label:`X2 Series`,children:(0,K.jsx)(`option`,{value:`X2D`,children:`X2D`})})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:`Location / Group`}),(0,K.jsx)(`input`,{type:`text`,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,value:a.location,onChange:e=>o({...a,location:e.target.value}),placeholder:n(`printers.modal.locationPlaceholder`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:n(`printers.locationHelp`)})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`input`,{type:`checkbox`,id:`edit_auto_archive`,checked:a.auto_archive,onChange:e=>o({...a,auto_archive:e.target.checked}),className:`rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green`}),(0,K.jsx)(`label`,{htmlFor:`edit_auto_archive`,className:`text-sm text-bambu-gray`,children:n(`printers.modal.autoArchiveLabel`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`input`,{type:`checkbox`,id:`edit_maintenance_mode`,checked:!a.is_active,onChange:e=>o({...a,is_active:!e.target.checked}),className:`rounded border-bambu-dark-tertiary bg-bambu-dark text-amber-400 focus:ring-amber-400`}),(0,K.jsxs)(`label`,{htmlFor:`edit_maintenance_mode`,className:`text-sm text-bambu-gray flex items-center gap-1.5`,children:[(0,K.jsx)(qu,{className:`w-3.5 h-3.5 text-amber-600 dark:text-amber-400`}),n(`printers.maintenance.editFieldLabel`)]})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray/70 mt-1 ml-6`,children:n(`printers.maintenance.editFieldHelp`)})]}),l?(0,K.jsxs)(`div`,{className:`rounded-lg bg-amber-50 dark:bg-amber-500/10 border border-amber-300 dark:border-amber-500/30 p-3 space-y-3`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,K.jsx)(Au,{className:`w-4 h-4 mt-0.5 flex-shrink-0 text-amber-600 dark:text-amber-400`}),(0,K.jsx)(`p`,{className:`text-sm text-amber-700 dark:text-amber-300`,children:n(`printers.addPreflight.warning`)})]}),(0,K.jsx)(kp,{result:l}),(0,K.jsxs)(`div`,{className:`flex gap-3`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:()=>u(null),className:`flex-1`,children:n(`printers.addPreflight.back`)}),(0,K.jsx)($,{type:`button`,onClick:f,className:`flex-1`,disabled:d.isPending,children:n(`printers.addPreflight.saveAnyway`)})]})]}):(0,K.jsxs)(`div`,{className:`flex gap-3 pt-4`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:t,className:`flex-1`,children:n(`common.cancel`)}),(0,K.jsx)($,{type:`submit`,className:`flex-1`,disabled:d.isPending||s,children:s?n(`printers.addPreflight.checking`):d.isPending?n(`common.saving`):n(`printers.modal.saveChanges`)})]})]})]})})})}function qAe(e){let{data:t}=q({queryKey:[`printerStatus`,e],queryFn:()=>Q.getPrinterStatus(e),refetchInterval:3e4});return!t?.connected}function JAe({printer:e,plug:t,onPowerOn:n,isPowering:r}){let i=qAe(e.id),{data:a}=q({queryKey:[`smartPlugStatus`,t.id],queryFn:()=>Q.getSmartPlugStatus(t.id),refetchInterval:1e4});return i?(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 hover:bg-gray-100 dark:hover:bg-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,K.jsx)(`span`,{className:`text-sm text-white truncate`,children:e.name}),a&&(0,K.jsx)(`span`,{className:`text-xs px-1.5 py-0.5 rounded ${a.state===`ON`?`bg-bambu-green/20 text-bambu-green`:`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400`}`,children:a.state||`?`})]}),(0,K.jsxs)(`button`,{onClick:()=>n(t.id),disabled:r||a?.state===`ON`,className:`px-2 py-1 text-xs rounded transition-colors flex items-center gap-1 ${a?.state===`ON`?`bg-bambu-green/20 text-bambu-green cursor-default`:`bg-bambu-green/20 text-bambu-green hover:bg-bambu-green hover:text-white`}`,children:[(0,K.jsx)(jl,{className:`w-3 h-3`}),r?`...`:`On`]})]}):null}function YAe(){let{t:e}=$e(),{resolvedMode:t,darkAccent:n,lightAccent:r}=wd(),i={green:`bg-green-500 text-white hover:bg-green-400 border-green-400/60`,teal:`bg-teal-500 text-white hover:bg-teal-400 border-teal-400/60`,blue:`bg-blue-500 text-white hover:bg-blue-400 border-blue-400/60`,orange:`bg-orange-500 text-white hover:bg-orange-400 border-orange-400/60`,purple:`bg-purple-500 text-white hover:bg-purple-400 border-purple-400/60`,red:`bg-red-500 text-white hover:bg-red-400 border-red-400/60`}[t===`dark`?n:r],[a,o]=(0,y.useState)(!1),[s,c]=(0,y.useState)(()=>localStorage.getItem(`hideDisconnectedPrinters`)===`true`),[l,u]=(0,y.useState)(!1),[d,f]=(0,y.useState)(null),[p,m]=(0,y.useState)(()=>localStorage.getItem(`printerSortBy`)||`name`),[h,g]=(0,y.useState)(()=>localStorage.getItem(`printerSortAsc`)!==`false`),[_,v]=(0,y.useState)(()=>{let e=localStorage.getItem(`printerCardSize`);return e?parseInt(e,10):2}),[b,x]=(0,y.useState)(()=>localStorage.getItem(`printerPageView`)===`camwall`?`camwall`:`cards`),[S,C]=(0,y.useState)(()=>{let e=parseInt(localStorage.getItem(`camWallMaxLive`)||``,10);return Number.isFinite(e)&&e>0?e:4}),[w,T]=(0,y.useState)(()=>{let e=parseInt(localStorage.getItem(`camWallSnapshotSec`)||``,10);return Number.isFinite(e)&&e>0?e:8}),[E,D]=(0,y.useState)(()=>{let e=localStorage.getItem(`camWallStatusMode`);return e===`off`||e===`compact`||e===`full`?e:`full`}),O=_===1?`compact`:`expanded`,[k,A]=(0,y.useState)(null),j=(0,y.useCallback)(e=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{let t=document.getElementById(`printer-card-${e}`);if(!t)return;let n=document.querySelector(`header`)?.getBoundingClientRect().height??56,r=t.getBoundingClientRect().top+window.scrollY-n-16;window.scrollTo({top:Math.max(0,r),behavior:`smooth`})})})},[]),M=(0,y.useCallback)(e=>{A(e),v(2),localStorage.setItem(`printerCardSize`,`2`),j(e)},[j]),N=(0,y.useCallback)(()=>{let e=k;A(null),v(1),localStorage.setItem(`printerCardSize`,`1`),e!=null&&j(e)},[k,j]),[P,F]=(0,y.useState)(``),[I,L]=(0,y.useState)(`all`),[R,z]=(0,y.useState)(`all`),[B,V]=(0,y.useState)(0),[ee,te]=(0,y.useState)(()=>{try{let e=localStorage.getItem(`printerCollapsedSections`);return e?JSON.parse(e):{}}catch{return{}}}),H=ao(),{showToast:ne}=Pd(),{hasPermission:re}=xd(),[U,ie]=(0,y.useState)(()=>{let e=localStorage.getItem(`openEmbeddedCameras`);if(e)try{let t=JSON.parse(e);return new Map(t.map(e=>[e.id,e]))}catch{return new Map}return new Map});(0,y.useEffect)(()=>{let e=Array.from(U.values());e.length>0?localStorage.setItem(`openEmbeddedCameras`,JSON.stringify(e)):localStorage.removeItem(`openEmbeddedCameras`)},[U]);let{data:ae,isLoading:W}=q({queryKey:[`printers`],queryFn:Q.getPrinters}),{data:oe}=q({queryKey:[`ui-preferences`],queryFn:Q.getUiPreferences}),se=(0,y.useMemo)(()=>cm(oe?.nozzle_temp_presets,im,0,320),[oe?.nozzle_temp_presets]),ce=(0,y.useMemo)(()=>cm(oe?.bed_temp_presets,am,0,140),[oe?.bed_temp_presets]),le=(0,y.useMemo)(()=>cm(oe?.chamber_temp_presets,om,0,65),[oe?.chamber_temp_presets]),ue=(0,y.useMemo)(()=>cm(oe?.fan_speed_presets,sm,0,100),[oe?.fan_speed_presets]),de=(0,y.useMemo)(()=>{if(oe?.drying_presets)try{let e=JSON.parse(oe.drying_presets);if(typeof e==`object`&&e&&Object.keys(e).length>0)return{...RW,...e}}catch{}return RW},[oe?.drying_presets]);(0,y.useEffect)(()=>{oe?.camera_view_mode===`window`&&U.size>0&&ie(new Map)},[oe?.camera_view_mode,U.size]);let{data:fe}=q({queryKey:[`smart-plugs`],queryFn:Q.getSmartPlugs}),{data:pe}=q({queryKey:[`maintenanceOverview`],queryFn:Q.getMaintenanceOverview,staleTime:60*1e3}),{data:me}=q({queryKey:[`obico-printer-status`],queryFn:Q.getObicoPrinterStatus,refetchInterval:1e4}),he=(0,y.useCallback)(e=>me?.enabled===!0&&(me.monitored_printers===null||me.monitored_printers.includes(e)),[me]),{data:ge}=q({queryKey:[`spoolman-status`],queryFn:Q.getSpoolmanStatus,staleTime:60*1e3}),_e=ge?.enabled&&ge?.connected,{data:ve}=q({queryKey:[`spoolman-settings`],queryFn:Q.getSpoolmanSettings,enabled:!!_e,staleTime:60*1e3}),ye=ve?.spoolman_sync_mode,{data:be}=q({queryKey:[`unlinked-spools`],queryFn:Q.getUnlinkedSpools,enabled:!!_e,staleTime:30*1e3}),xe=be&&be.length>0,{data:Se}=q({queryKey:[`linked-spools`],queryFn:Q.getLinkedSpools,enabled:!!_e,staleTime:30*1e3}),Ce=Se?.linked,{data:we}=q({queryKey:[`spool-assignments`],queryFn:()=>Q.getAssignments(),enabled:re(`inventory:view_assignments`),staleTime:30*1e3}),Te=J({mutationFn:({printerId:e,amsId:t,trayId:n})=>Q.unassignSpool(e,t,n),onSuccess:()=>{H.invalidateQueries({queryKey:[`spool-assignments`]})}}),{data:Ee,isLoading:De}=q({queryKey:[`spoolman-inventory-spools`],queryFn:()=>Q.getSpoolmanInventorySpools(!1),enabled:!!_e,staleTime:30*1e3}),{data:Oe,isLoading:ke}=q({queryKey:[`spoolman-slot-assignments`],queryFn:()=>Q.getSpoolmanSlotAssignments(),enabled:!!_e,staleTime:30*1e3}),Ae=J({mutationFn:e=>Q.unassignSpoolmanSlot(e),onSuccess:()=>{H.invalidateQueries({queryKey:[`spoolman-inventory-spools`]}),H.invalidateQueries({queryKey:[`spoolman-slot-assignments`]})}}),je=(e,t,n)=>we?.find(r=>r.printer_id===e&&r.ams_id===Number(t)&&r.tray_id===Number(n)),Me=pe?.reduce((e,t)=>(e[t.printer_id]={due_count:t.due_count,warning_count:t.warning_count,total_print_hours:t.total_print_hours},e),{})||{},Ne=fe?.reduce((e,t)=>(t.printer_id&&(e[t.printer_id]=t),e),{})||{},Pe=J({mutationFn:Q.createPrinter,onSuccess:()=>{H.invalidateQueries({queryKey:[`printers`]}),H.invalidateQueries({queryKey:[`maintenanceOverview`]}),o(!1)},onError:t=>{if(t instanceof $u&&t.code===`printer_connection_failed`){ne(e(`printers.toast.connectionFailedNotAdded`),`error`);return}ne(t.message||e(`printers.toast.failedToAdd`),`error`)}}),Fe=J({mutationFn:e=>Q.controlSmartPlug(e,`on`),onSuccess:()=>{H.invalidateQueries({queryKey:[`smart-plugs`]}),f(null)},onError:()=>{f(null)}}),[Ie,Le]=(0,y.useState)(new Set),[Re,ze]=(0,y.useState)(!1),[Be,Ve]=(0,y.useState)(null),[He,Ue]=(0,y.useState)(!1),We=Re||Ie.size>0,Ge=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),Ke=(0,y.useCallback)(()=>{Le(new Set),ze(!1)},[]);(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&We&&Ke()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[We,Ke]);let qe=(0,y.useCallback)(async t=>{Ue(!0);let n=Array.from(Ie).filter(e=>{let n=H.getQueryData([`printerStatus`,e]);if(!n?.connected)return!1;switch(t){case`stop`:return n.state===`RUNNING`||n.state===`PAUSE`;case`pause`:return n.state===`RUNNING`;case`resume`:return n.state===`PAUSE`;case`clearPlate`:return!!n.awaiting_plate_clear;case`clearHMS`:return n.hms_errors&&pm(n.hms_errors).length>0;default:return!1}});if(n.length===0){ne(e(`printers.bulk.noneApplicable`),`error`),Ue(!1),Ve(null);return}let r={stop:Q.stopPrint,pause:Q.pausePrint,resume:Q.resumePrint,clearPlate:Q.clearPlate,clearHMS:Q.clearHMSErrors}[t],i=await Promise.allSettled(n.map(e=>r(e))),a=i.filter(e=>e.status===`fulfilled`).length,o=i.filter(e=>e.status===`rejected`).length;o===0?ne(e(`printers.bulk.success`,{action:e(`printers.bulk.actions.${t}`),count:a})):ne(e(`printers.bulk.partial`,{succeeded:a,failed:o}),`error`),n.forEach(e=>{H.invalidateQueries({queryKey:[`printerStatus`,e]})}),Ue(!1),Ve(null)},[Ie,H,ne,e]),Je=(0,y.useCallback)(e=>{e===`stop`||e===`pause`||e===`clearPlate`?Ve(e):qe(e)},[qe]),Ye=()=>{let e=!s;c(e),localStorage.setItem(`hideDisconnectedPrinters`,String(e))},Xe=e=>{m(e),localStorage.setItem(`printerSortBy`,e)},Ze=()=>{let e=!h;g(e),localStorage.setItem(`printerSortAsc`,String(e))},Qe=()=>{switch(_){case 1:return`grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5`;case 2:return`grid-cols-1 md:grid-cols-2 xl:grid-cols-3`;case 3:return`grid-cols-1 lg:grid-cols-2`;case 4:return`grid-cols-1`;default:return`grid-cols-1 md:grid-cols-2 xl:grid-cols-3`}},et=[`S`,`M`,`L`,`XL`];(0,y.useEffect)(()=>H.getQueryCache().subscribe(e=>{e.type===`updated`&&Array.isArray(e.query.queryKey)&&e.query.queryKey[0]===`printerStatus`&&V(e=>e+1)}),[H]);let tt=(0,y.useMemo)(()=>{if(!ae)return[];let e=ae;if(P.trim()){let t=P.trim().toLowerCase();e=e.filter(e=>e.name.toLowerCase().includes(t)||(e.model||``).toLowerCase().includes(t)||(e.location||``).toLowerCase().includes(t)||(e.serial_number||``).toLowerCase().includes(t))}return R!==`all`&&(e=e.filter(e=>(e.location||``)===R)),I!==`all`&&(e=e.filter(e=>{let t=H.getQueryData([`printerStatus`,e.id]);if(!t?.connected)return I===`offline`;let n=t.hms_errors?pm(t.hms_errors):[];switch(I){case`printing`:return t.state===`RUNNING`;case`paused`:return t.state===`PAUSE`;case`finished`:return t.state===`FINISH`;case`error`:return t.state===`FAILED`||n.length>0;case`idle`:return t.state!==`RUNNING`&&t.state!==`PAUSE`&&t.state!==`FINISH`&&t.state!==`FAILED`&&n.length===0;case`offline`:return!1;default:return!0}})),e},[ae,P,I,R,H,B]),nt=(0,y.useMemo)(()=>ae?[...new Set(ae.map(e=>e.location||``).filter(Boolean))].sort():[],[ae]),rt=(0,y.useMemo)(()=>{let e=[...tt];switch(p){case`name`:e.sort((e,t)=>e.name.localeCompare(t.name));break;case`model`:e.sort((e,t)=>(e.model||``).localeCompare(t.model||``));break;case`location`:e.sort((e,t)=>{let n=e.location||``,r=t.location||``;return!n&&r?1:n&&!r?-1:n.localeCompare(r)||e.name.localeCompare(t.name)});break;case`status`:e.sort((e,t)=>{let n=H.getQueryData([`printerStatus`,e.id]),r=H.getQueryData([`printerStatus`,t.id]),i=e=>e?.connected?(e.hms_errors?pm(e.hms_errors):[]).length>0?0:e.state===`RUNNING`?1:2:3;return i(n)-i(r)});break;case`eta`:e.sort((e,t)=>{let n=H.getQueryData([`printerStatus`,e.id]),r=H.getQueryData([`printerStatus`,t.id]),i=e=>e?.connected?e.state===`RUNNING`&&e.remaining_time!=null&&e.remaining_time>0?0:e.state===`RUNNING`?1:2:3,a=i(n),o=i(r);if(a!==o)return a-o;if(a===0){let e=(n.remaining_time??0)-(r.remaining_time??0);if(e!==0)return e}return e.name.localeCompare(t.name)});break}return h||e.reverse(),e},[tt,p,h,H]),it=(0,y.useCallback)(()=>{Le(new Set(rt.map(e=>e.id))),ze(!0)},[rt]),at=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return rt.forEach(t=>{FW(H.getQueryData([`printerStatus`,t.id]))===e&&n.add(t.id)}),n}),ze(!0)},[rt,H]),ot=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return rt.filter(t=>(t.location||``)===e).forEach(e=>n.add(e.id)),n}),ze(!0)},[rt]),st=(0,y.useCallback)(e=>{Le(t=>{let n=new Set(t);return rt.filter(t=>(t.model||`Unknown`)===e).forEach(e=>n.add(e.id)),n}),ze(!0)},[rt]),ct=(0,y.useCallback)(e=>{te(t=>{let n={...t,[e]:!t[e]};try{localStorage.setItem(`printerCollapsedSections`,JSON.stringify(n))}catch{}return n})},[]),lt=(0,y.useMemo)(()=>{if(p===`name`||p===`eta`)return null;let e={};return p===`location`?rt.forEach(t=>{let n=t.location||`Ungrouped`;e[n]||(e[n]=[]),e[n].push(t)}):p===`model`?rt.forEach(t=>{let n=t.model||`Unknown`;e[n]||(e[n]=[]),e[n].push(t)}):p===`status`&&rt.forEach(t=>{let n=FW(H.getQueryData([`printerStatus`,t.id]));e[n]||(e[n]=[]),e[n].push(t)}),e},[p,rt,H,B]),ut=(0,y.useRef)(null),dt=(0,y.useRef)(null),ft=(0,y.useRef)(0),[pt,mt]=(0,y.useState)(!1),ht=(0,y.useCallback)(()=>{let e=ut.current;if(!e)return;let t=dt.current?.offsetWidth;t&&(ft.current=t);let n=ft.current>0&&e.clientWidthe===n?e:n)},[]),gt=Object.keys(Ne).length;(0,y.useLayoutEffect)(()=>{ht();let e=ut.current;if(!e)return;if(typeof ResizeObserver>`u`)return window.addEventListener(`resize`,ht),()=>window.removeEventListener(`resize`,ht);let t=new ResizeObserver(()=>ht());return t.observe(e),window.addEventListener(`resize`,ht),()=>{t.disconnect(),window.removeEventListener(`resize`,ht)}},[ht,ae?.length,nt.length,s,gt]);let _t=(t=!1)=>(0,K.jsxs)(K.Fragment,{children:[ae&&ae.length>0&&(0,K.jsx)(AW,{value:I,onChange:L,fullWidth:t,options:[{value:`all`,label:e(`printers.filter.allStatuses`)},{value:`printing`,label:e(`printers.status.printing`)},{value:`paused`,label:e(`printers.status.paused`)},{value:`idle`,label:e(`printers.status.idle`)},{value:`finished`,label:e(`printers.status.finished`)},{value:`error`,label:e(`printers.status.error`)},{value:`offline`,label:e(`printers.status.offline`)}]}),ae&&ae.length>0&&nt.length>0&&(0,K.jsx)(AW,{value:R,onChange:z,fullWidth:t,options:[{value:`all`,label:e(`printers.filter.allLocations`)},...nt.map(e=>({value:e,label:e}))]}),(0,K.jsx)(`button`,{type:`button`,onClick:Ye,"aria-pressed":s,className:`h-8 px-2 rounded-lg border text-sm font-medium transition-colors ${t?`w-full`:``} ${s?`bg-bambu-green border-bambu-green text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary`}`,children:e(`printers.hideOffline`)})]}),vt=(t=!1)=>(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-1 ${t?`w-full`:``}`,children:[(0,K.jsx)(AW,{value:p,onChange:Xe,fullWidth:t,options:[{value:`name`,label:e(`printers.sort.name`)},{value:`status`,label:e(`printers.sort.status`)},{value:`model`,label:e(`printers.sort.model`)},{value:`location`,label:e(`printers.sort.location`)},{value:`eta`,label:e(`printers.sort.eta`)}]}),(0,K.jsx)(`button`,{onClick:Ze,className:`h-8 shrink-0 px-2 rounded-lg border bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary transition-colors flex items-center justify-center`,title:e(h?`printers.sort.descending`:`printers.sort.ascending`),children:h?(0,K.jsx)(zo,{className:`w-4 h-4 text-white`}):(0,K.jsx)(No,{className:`w-4 h-4 text-white`})})]}),(0,K.jsxs)(`div`,{className:`flex h-8 items-center bg-bambu-dark rounded-lg border border-bambu-dark-tertiary ${t?`w-full`:``}`,children:[(0,K.jsxs)(`button`,{type:`button`,onClick:()=>{x(`cards`),localStorage.setItem(`printerPageView`,`cards`)},className:`flex h-full items-center gap-1 rounded-l-lg px-2 text-xs font-medium transition-colors ${t?`flex-1 justify-center`:``} ${b===`cards`?`bg-bambu-green text-white`:`text-white hover:bg-bambu-dark-tertiary`}`,title:e(`printers.pageView.cards`),"aria-pressed":b===`cards`,children:[(0,K.jsx)(Uc,{className:`w-3.5 h-3.5`}),t&&(0,K.jsx)(`span`,{children:e(`printers.pageView.cards`)})]}),(0,K.jsxs)(`button`,{type:`button`,onClick:()=>{x(`camwall`),localStorage.setItem(`printerPageView`,`camwall`)},className:`flex h-full items-center gap-1 rounded-r-lg px-2 text-xs font-medium transition-colors ${t?`flex-1 justify-center`:``} ${b===`camwall`?`bg-bambu-green text-white`:`text-white hover:bg-bambu-dark-tertiary`}`,title:e(`printers.pageView.camWall`),"aria-pressed":b===`camwall`,disabled:!re(`camera:view`),children:[(0,K.jsx)(ul,{className:`w-3.5 h-3.5`}),t&&(0,K.jsx)(`span`,{children:e(`printers.pageView.camWall`)})]})]}),b===`camwall`&&re(`camera:view`)&&(0,K.jsxs)(Di,{to:`/camwall`,className:`flex h-8 items-center gap-1 rounded-lg border border-bambu-dark-tertiary bg-bambu-dark px-2 text-xs font-medium text-white transition-colors hover:bg-bambu-dark-tertiary ${t?`w-full justify-center`:``}`,title:e(`printers.pageView.openCamWallPage`),children:[(0,K.jsx)(Qs,{className:`w-3.5 h-3.5`}),t&&(0,K.jsx)(`span`,{children:e(`printers.pageView.openCamWallPage`)})]}),(0,K.jsx)(`div`,{className:`flex h-8 items-center bg-bambu-dark rounded-lg border border-bambu-dark-tertiary ${b===`camwall`?`opacity-40 pointer-events-none`:``} ${t?`w-full`:``}`,children:et.map((n,r)=>{let i=r+1,a=_===i;return(0,K.jsx)(`button`,{onClick:()=>{A(null),v(i),localStorage.setItem(`printerCardSize`,String(i))},className:`h-full px-2 text-xs font-medium transition-colors ${t?`flex-1`:``} ${r===0?`rounded-l-lg`:``} ${r===et.length-1?`rounded-r-lg`:``} ${a?`bg-bambu-green text-white`:`text-white hover:bg-bambu-dark-tertiary`}`,title:e(n===`S`?`printers.cardSize.small`:n===`M`?`printers.cardSize.medium`:n===`L`?`printers.cardSize.large`:`printers.cardSize.extraLarge`),children:n},n)})})]}),yt=(t=!1)=>(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`button`,{onClick:()=>{We?Ke():ze(!0)},className:`h-8 px-2 rounded-lg border transition-colors ${t?`w-full justify-center gap-1.5 text-sm font-medium flex items-center`:``} ${We?`bg-bambu-green border-bambu-green text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary`}`,title:e(`printers.bulk.select`),disabled:!re(`printers:control`),children:[(0,K.jsx)(du,{className:`w-4 h-4`}),t&&(0,K.jsx)(`span`,{children:e(`printers.bulk.select`)})]}),s&&Object.keys(Ne).length>0&&(0,K.jsxs)(`div`,{className:`relative ${t?`w-full`:``}`,children:[(0,K.jsxs)(`button`,{onClick:()=>u(!l),className:`h-8 flex items-center gap-1.5 px-2 text-sm rounded-lg border transition-colors ${t?`w-full justify-between bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary hover:text-white`:`bg-bambu-dark border-bambu-dark-tertiary text-white hover:bg-bambu-dark-tertiary`}`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-1.5`,children:[(0,K.jsx)(jl,{className:`w-4 h-4`}),e(`printers.powerOn`)]}),(0,K.jsx)(cs,{className:`w-3 h-3 transition-transform ${l?`rotate-180`:``}`})]}),l&&(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`div`,{className:`fixed inset-0 z-10`,onClick:()=>u(!1)}),(0,K.jsxs)(`div`,{className:`absolute right-0 mt-2 w-56 bg-white dark:bg-bambu-dark-secondary border border-gray-200 dark:border-bambu-dark-tertiary rounded-lg shadow-lg z-20 py-1`,children:[(0,K.jsx)(`div`,{className:`px-3 py-2 text-xs text-gray-500 dark:text-bambu-gray border-b border-gray-200 dark:border-bambu-dark-tertiary`,children:e(`printers.offlinePrintersWithPlugs`)}),ae?.filter(e=>Ne[e.id]).map(e=>(0,K.jsx)(JAe,{printer:e,plug:Ne[e.id],onPowerOn:e=>{f(e),Fe.mutate(e)},isPowering:d===Ne[e.id]?.id},e.id)),ae?.filter(e=>Ne[e.id]).length===0&&(0,K.jsx)(`div`,{className:`px-3 py-2 text-sm text-bambu-gray`,children:`No printers with smart plugs`})]})]})]}),(0,K.jsxs)($,{onClick:()=>o(!0),disabled:!re(`printers:create`),title:re(`printers:create`)?void 0:e(`printers.permission.noAdd`),className:`!h-8 !min-h-8 px-2 py-0 ${t?`w-full`:``}`,children:[(0,K.jsx)(kl,{className:`w-4 h-4`}),e(`printers.addPrinter`)]})]});return(0,K.jsxs)(`div`,{className:`p-4 md:p-8`,children:[(0,K.jsxs)(`div`,{className:`space-y-3 mb-6`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`h1`,{className:`text-2xl font-bold text-white flex items-center gap-3`,children:[(0,K.jsx)(Ml,{className:`w-7 h-7 text-bambu-green`}),e(`printers.title`)]}),(0,K.jsx)(LAe,{printers:ae})]}),(0,K.jsxs)(`div`,{ref:ut,className:`relative flex items-center gap-2`,children:[ae&&ae.length>0&&(0,K.jsxs)(`div`,{className:`relative min-w-0 flex-1`,children:[(0,K.jsx)(Gl,{className:`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray/50`}),(0,K.jsx)(`input`,{type:`search`,name:`printer-search`,autoComplete:`off`,"data-1p-ignore":!0,"data-lpignore":`true`,value:P,onChange:e=>F(e.target.value),placeholder:e(`printers.search`),"aria-label":e(`printers.search`),className:`w-full h-8 pl-9 pr-8 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm placeholder:text-bambu-gray/50 focus:outline-none focus:border-bambu-green`}),P&&(0,K.jsx)(`button`,{type:`button`,"aria-label":e(`common.clear`),onClick:()=>F(``),className:`absolute right-3 top-1/2 -translate-y-1/2 text-bambu-gray hover:text-white`,children:(0,K.jsx)(Ju,{className:`w-4 h-4`})})]}),(0,K.jsxs)(`div`,{ref:dt,"aria-hidden":pt,inert:pt,className:`${pt?`absolute -left-[9999px] top-0 flex w-max pointer-events-none opacity-0`:`flex`} ml-auto items-center justify-end gap-2 flex-nowrap [&>*]:shrink-0`,children:[(0,K.jsx)(`div`,{className:`h-6 w-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`flex items-center gap-2`,children:_t()}),(0,K.jsx)(`div`,{className:`h-6 w-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`flex items-center gap-2`,children:vt()}),(0,K.jsx)(`div`,{className:`h-6 w-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`div`,{className:`flex items-center gap-2`,children:yt()})]}),pt&&(0,K.jsxs)(`div`,{className:`ml-auto flex items-center justify-end gap-1`,children:[(0,K.jsx)(jW,{label:e(`printers.toolbar.filters`,`Filters`),icon:(0,K.jsx)(vc,{className:`w-4 h-4`}),children:(0,K.jsx)(`div`,{className:`flex w-48 flex-col gap-2`,children:_t(!0)})}),(0,K.jsx)(jW,{label:e(`printers.toolbar.view`,`View`),icon:(0,K.jsx)(au,{className:`w-4 h-4`}),children:(0,K.jsx)(`div`,{className:`flex w-48 flex-col gap-2`,children:vt(!0)})}),(0,K.jsx)(jW,{label:e(`printers.toolbar.actions`,`Actions`),icon:(0,K.jsx)(Ys,{className:`w-4 h-4`}),children:(0,K.jsx)(`div`,{className:`flex w-48 flex-col gap-2`,children:yt(!0)})})]})]})]}),W?(0,K.jsx)(`div`,{className:`text-center py-12 text-bambu-gray`,children:e(`common.loading`)}):ae?.length===0?(0,K.jsx)(Dd,{children:(0,K.jsxs)(kd,{className:`text-center py-12`,children:[(0,K.jsx)(`p`,{className:`text-bambu-gray mb-4`,children:e(`printers.noPrintersConfigured`)}),(0,K.jsxs)($,{onClick:()=>o(!0),disabled:!re(`printers:create`),title:re(`printers:create`)?void 0:e(`printers.permission.noAdd`),children:[(0,K.jsx)(kl,{className:`w-4 h-4`}),e(`printers.addPrinter`)]})]})}):rt.length===0&&(P.trim()||I!==`all`||R!==`all`)?(0,K.jsx)(Dd,{children:(0,K.jsx)(kd,{className:`text-center py-12`,children:(0,K.jsx)(`p`,{className:`text-bambu-gray`,children:e(`printers.noSearchResults`)})})}):b===`camwall`?(0,K.jsx)(LT,{printers:rt,maxLive:S,snapshotIntervalSec:w,onTileClick:(e,t)=>{if((oe?.camera_view_mode||`window`)===`embedded`)ie(n=>new Map(n).set(e,{id:e,name:t}));else{let t=localStorage.getItem(`cameraWindowState`),n=t?JSON.parse(t):{width:640,height:400},r=[`width=${n.width}`,`height=${n.height}`,n.left===void 0?``:`left=${n.left}`,n.top===void 0?``:`top=${n.top}`,`menubar=no,toolbar=no,location=no,status=no`].filter(Boolean).join(`,`);window.open(`/camera/${e}`,`camera-${e}`,r)}},statusMode:E,onChangeMaxLive:e=>{C(e),localStorage.setItem(`camWallMaxLive`,String(e))},onChangeSnapshotIntervalSec:e=>{T(e),localStorage.setItem(`camWallSnapshotSec`,String(e))},onChangeStatusMode:e=>{D(e),localStorage.setItem(`camWallStatusMode`,e)}}):lt?(0,K.jsx)(`div`,{className:`space-y-6`,children:(()=>{let e=p===`status`?zAe.filter(e=>lt[e]?.length>0):Object.keys(lt);return h?e:[...e].reverse()})().map(t=>{let n=lt[t],r=`${p}:${t}`,i=!ee[r],a=p===`status`&&PW[t]?.dot||`bg-bambu-green`,o=p===`status`?e(PW[t]?.labelKey||t):t;return(0,K.jsx)(Ip,{open:i,onToggle:()=>ct(r),summaryClassName:`py-1`,summary:(0,K.jsxs)(`h2`,{className:`text-lg font-semibold text-white flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`w-2 h-2 rounded-full ${a}`}),o,(0,K.jsxs)(`span`,{className:`text-sm font-normal text-bambu-gray`,children:[`(`,n.length,`)`]}),We&&(0,K.jsx)(`button`,{onClick:e=>{e.stopPropagation(),p===`location`?ot(t===`Ungrouped`?``:t):p===`status`?at(t):p===`model`&&st(t)},className:`text-xs text-bambu-green hover:text-bambu-green-light transition-colors ml-1`,children:e(`printers.bulk.selectAll`)})]}),children:(0,K.jsx)(`div`,{className:`grid gap-4 ${_>=3?`gap-6`:``} ${Qe()}`,children:n.map(e=>(0,K.jsx)(BW,{printer:e,hideIfDisconnected:s,maintenanceInfo:Me[e.id],viewMode:O,cardSize:_,amsThresholds:oe?{humidityGood:Number(oe.ams_humidity_good)||40,humidityFair:Number(oe.ams_humidity_fair)||60,tempGood:Number(oe.ams_temp_good)||28,tempFair:Number(oe.ams_temp_fair)||35}:void 0,spoolmanEnabled:_e,hasUnlinkedSpools:xe,linkedSpools:Ce,spoolmanUrl:ge?.url,spoolmanSyncMode:ye,onGetAssignment:je,onUnassignSpool:(e,t,n)=>Te.mutate({printerId:e,amsId:t,trayId:n}),spoolmanSpools:Ee,spoolmanSlotAssignments:Oe,spoolmanLoading:De||ke,onUnassignSpoolmanSpool:e=>Ae.mutate(e),timeFormat:oe?.time_format||`system`,cameraViewMode:oe?.camera_view_mode||`window`,onOpenEmbeddedCamera:(e,t)=>ie(n=>new Map(n).set(e,{id:e,name:t})),checkPrinterFirmware:oe?.check_printer_firmware!==!1,dryingPresets:de,nozzleTempPresets:se,bedTempPresets:ce,chamberTempPresets:le,fanSpeedPresets:ue,requirePlateClear:oe?.require_plate_clear===!0,selectionMode:We,isSelected:Ie.has(e.id),onToggleSelect:Ge,onOpenCompactCard:M,aiDetectionEnabled:he(e.id),aiDetection:me?.enabled?me.per_printer[String(e.id)]:void 0,aiLastError:me?.last_error??null},e.id))})},t)})}):(0,K.jsx)(`div`,{className:`grid gap-4 ${_>=3?`gap-6`:``} ${Qe()}`,children:rt.map(e=>(0,K.jsx)(BW,{printer:e,hideIfDisconnected:s,maintenanceInfo:Me[e.id],viewMode:O,cardSize:_,spoolmanEnabled:_e,hasUnlinkedSpools:xe,linkedSpools:Ce,spoolmanUrl:ge?.url,spoolmanSyncMode:ye,onGetAssignment:je,onUnassignSpool:(e,t,n)=>Te.mutate({printerId:e,amsId:t,trayId:n}),spoolmanSpools:Ee,spoolmanSlotAssignments:Oe,spoolmanLoading:De||ke,onUnassignSpoolmanSpool:e=>Ae.mutate(e),amsThresholds:oe?{humidityGood:Number(oe.ams_humidity_good)||40,humidityFair:Number(oe.ams_humidity_fair)||60,tempGood:Number(oe.ams_temp_good)||28,tempFair:Number(oe.ams_temp_fair)||35}:void 0,timeFormat:oe?.time_format||`system`,cameraViewMode:oe?.camera_view_mode||`window`,onOpenEmbeddedCamera:(e,t)=>ie(n=>new Map(n).set(e,{id:e,name:t})),checkPrinterFirmware:oe?.check_printer_firmware!==!1,dryingPresets:de,nozzleTempPresets:se,bedTempPresets:ce,chamberTempPresets:le,fanSpeedPresets:ue,requirePlateClear:oe?.require_plate_clear===!0,selectionMode:We,isSelected:Ie.has(e.id),onToggleSelect:Ge,onOpenCompactCard:M,aiDetectionEnabled:he(e.id),aiDetection:me?.enabled?me.per_printer[String(e.id)]:void 0,aiLastError:me?.last_error??null},e.id))}),_===2&&k!=null&&(0,K.jsxs)(`button`,{type:`button`,onClick:N,className:`fixed bottom-5 left-1/2 z-40 inline-flex -translate-x-1/2 items-center gap-2 rounded-full border px-4 py-2 text-sm font-medium shadow-xl transition-colors ${i}`,title:e(`common.back`,`Back`),children:[(0,K.jsx)(Po,{className:`w-4 h-4`}),e(`common.back`,`Back`)]}),a&&(0,K.jsx)(WAe,{onClose:()=>o(!1),onAdd:e=>Pe.mutate(e),existingSerials:ae?.map(e=>e.serial_number)||[]}),We&&ae&&(0,K.jsx)(bee,{selectedIds:Ie,printers:ae,onClose:Ke,onSelectAll:it,onSelectByLocation:ot,onSelectByState:at,onAction:Je,actionPending:He}),Be===`stop`&&(0,K.jsx)(Kd,{title:e(`printers.bulk.confirm.stopTitle`,{count:Ie.size}),message:e(`printers.bulk.confirm.stopMessage`,{count:Ie.size}),confirmText:e(`printers.bulk.confirm.stopButton`),variant:`danger`,isLoading:He,onConfirm:()=>qe(`stop`),onCancel:()=>Ve(null)}),Be===`pause`&&(0,K.jsx)(Kd,{title:e(`printers.bulk.confirm.pauseTitle`,{count:Ie.size}),message:e(`printers.bulk.confirm.pauseMessage`,{count:Ie.size}),confirmText:e(`printers.bulk.confirm.pauseButton`),isLoading:He,onConfirm:()=>qe(`pause`),onCancel:()=>Ve(null)}),Be===`clearPlate`&&(0,K.jsx)(Kd,{title:e(`printers.bulk.confirm.clearPlateTitle`,{count:Ie.size}),message:e(`printers.bulk.confirm.clearPlateMessage`,{count:Ie.size}),confirmText:e(`printers.bulk.confirm.clearPlateButton`),isLoading:He,onConfirm:()=>qe(`clearPlate`),onCancel:()=>Ve(null)}),Array.from(U.values()).map((e,t)=>(0,K.jsx)(Ile,{printerId:e.id,printerName:e.name,viewerIndex:t,onClose:()=>ie(t=>{let n=new Map(t);return n.delete(e.id),n})},e.id))]})}function XAe({title:e,message:t,subtitle:n,closeText:r,variant:i=`error`,onClose:a}){let{t:o}=$e(),s=r??o(`common.close`);return(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&a()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[a]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-[120]`,onClick:a,children:(0,K.jsx)(Dd,{className:`w-full max-w-md`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{className:`p-6`,children:[(0,K.jsxs)(`div`,{className:`flex items-start gap-4`,children:[(0,K.jsx)(`div`,{className:`p-2 rounded-full bg-bambu-dark ${i===`warning`?`text-yellow-600 dark:text-yellow-400`:`text-red-600 dark:text-red-400`}`,children:(0,K.jsx)(Au,{className:`w-6 h-6`})}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsx)(`h3`,{className:`text-lg font-semibold text-white mb-1`,children:e}),n&&(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mb-2 truncate`,children:n}),(0,K.jsx)(`p`,{className:`text-bambu-gray text-sm whitespace-pre-line break-words`,children:t})]})]}),(0,K.jsx)(`div`,{className:`flex mt-6`,children:(0,K.jsx)($,{onClick:a,className:`flex-1`,children:s})})]})})})}var VW=(0,y.createContext)(null),ZAe=1500,QAe=1e3,HW=e=>`slice-job-${e}`;function UW(e){try{return decodeURIComponent(e)}catch{return e}}function $Ae(e){let t=Math.max(0,Math.floor(e));if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return n<60?`${n}m ${r}s`:`${Math.floor(n/60)}h ${n%60}m`}function eje({children:e}){let{t}=$e(),{showToast:n,showPersistentToast:r,dismissToast:i}=Pd(),a=ao(),[o,s]=(0,y.useState)([]),[c,l]=(0,y.useState)(null),u=(0,y.useRef)([]);u.current=o;let d=(0,y.useRef)(new Map),f=(0,y.useRef)(new Map),p=(0,y.useRef)(new Map),m=(0,y.useRef)(new Set),h=(0,y.useCallback)(e=>{let n=d.current.get(e.id);if(n==null)return;let i=(Date.now()-n)/1e3,a=f.current.get(e.id)??`pending`,o=$Ae(i),s=p.current.get(e.id)??null,c=s&&s.stage&&s.total_percent>0;if(a===`running`&&c){let n=UW(e.sourceName),i=s.stage,a=Math.min(100,Math.max(0,Math.round(s.total_percent))),c=typeof s.multi_plate_index==`number`&&typeof s.multi_plate_count==`number`&&s.multi_plate_count>1?t(`slice.runningWithProgressMultiPlate`,`Plate {{plateIndex}} of {{plateCount}} • {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,{plateIndex:s.multi_plate_index,plateCount:s.multi_plate_count,name:n,stage:i,percent:a,elapsed:o}):t(`slice.runningWithProgress`,`{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,{name:n,stage:i,percent:a,elapsed:o});r(HW(e.id),c,`loading`);return}let l=a===`pending`?`slice.queuedToast`:`slice.runningToast`,u=a===`pending`?`Queued: {{name}} — {{elapsed}}`:`Slicing {{name}} — {{elapsed}}`;r(HW(e.id),t(l,u,{name:UW(e.sourceName),elapsed:o}),`loading`)},[r,t]),g=(0,y.useCallback)((e,t,n)=>{s(r=>r.some(t=>t.id===e)?r:[...r,{id:e,kind:t,sourceName:n}]),m.current.delete(e),d.current.set(e,Date.now()),f.current.set(e,`pending`),p.current.set(e,null),h({id:e,kind:t,sourceName:n})},[h]),_=(0,y.useCallback)((e,r)=>{m.current.has(e.id)||(m.current.add(e.id),s(t=>t.filter(t=>t.id!==e.id)),d.current.delete(e.id),f.current.delete(e.id),p.current.delete(e.id),i(HW(e.id)),r.status===`completed`?n(t(`slice.completedToast`,`Sliced {{name}}`,{name:UW(e.sourceName)}),`success`):r.status===`failed`&&l({name:UW(e.sourceName),detail:r.error_detail||t(`slice.failed`)}),a.invalidateQueries({queryKey:[`library-files`]}),a.invalidateQueries({queryKey:[`archives`]}))},[i,a,n,t]);return(0,y.useEffect)(()=>{if(o.length===0)return;let e=!1,t=!1,n=setInterval(async()=>{if(!(e||t)){t=!0;try{let t=[...u.current];for(let n of t)try{let t=await Q.getSliceJob(n.id);if(e)return;f.current.set(n.id,t.status),t.progress&&p.current.set(n.id,t.progress),(t.status===`completed`||t.status===`failed`)&&_(n,t)}catch{}}finally{t=!1}}},ZAe);return()=>{e=!0,clearInterval(n)}},[o.length,_]),(0,y.useEffect)(()=>{if(o.length===0)return;let e=setInterval(()=>{for(let e of u.current)h(e)},QAe);return()=>clearInterval(e)},[o.length,h]),(0,K.jsxs)(VW.Provider,{value:{trackJob:g,activeJobs:o},children:[e,c&&(0,K.jsx)(XAe,{title:t(`slice.failedTitle`),subtitle:c.name,message:c.detail,onClose:()=>l(null)})]})}function WW(){let e=(0,y.useContext)(VW);if(!e)throw Error(`useSliceJobTracker must be used inside SliceJobTrackerProvider`);return e}function GW({plates:e,onSelect:t,onClose:n}){let{t:r}=$e();return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4`,onClick:n,children:(0,K.jsxs)(`div`,{className:`w-full max-w-3xl max-h-[85vh] flex flex-col rounded-lg bg-bambu-dark-secondary border border-bambu-dark-tertiary/60`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex-shrink-0 flex items-start justify-between gap-3 px-4 pt-4 pb-3 border-b border-bambu-dark-tertiary/40`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsx)(`h3`,{className:`text-white font-medium`,children:r(`archives.platePicker.title`)}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`archives.platePicker.hint`)})]}),(0,K.jsx)(`button`,{onClick:n,className:`flex-shrink-0 text-bambu-gray hover:text-white transition-colors`,"aria-label":r(`common.close`,`Close`),children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsx)(`div`,{className:`flex-1 overflow-y-auto p-4`,children:(0,K.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-2`,children:e.map(e=>(0,K.jsxs)(`button`,{type:`button`,onClick:()=>t(e.index),className:`flex items-center gap-2 p-2 rounded-lg border border-bambu-dark-tertiary bg-bambu-dark hover:border-bambu-gray transition-colors text-left`,children:[e.has_thumbnail&&e.thumbnail_url!=null?(0,K.jsx)(`img`,{src:od(e.thumbnail_url),alt:`Plate ${e.index}`,className:`w-12 h-12 rounded object-cover bg-bambu-dark-tertiary flex-shrink-0`}):(0,K.jsx)(`div`,{className:`w-12 h-12 rounded bg-bambu-dark-tertiary flex items-center justify-center flex-shrink-0`,children:(0,K.jsx)(Hc,{className:`w-5 h-5 text-bambu-gray`})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`text-sm text-white font-medium truncate`,children:e.name?`${r(`archives.platePicker.plateLabel`,{index:e.index})} — ${e.name}`:r(`archives.platePicker.plateLabel`,{index:e.index})}),(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray truncate`,children:[e.objects.length>0?e.objects.slice(0,3).join(`, `)+(e.objects.length>3?`…`:``):e.object_count!=null&&e.object_count>0?r(`archives.platePicker.objectCount`,{count:e.object_count}):`${e.filaments.length} filament${e.filaments.length===1?``:`s`}`,e.print_time_seconds==null?``:` • ${qf(e.print_time_seconds)}`]})]})]},e.index))})})]})})}var KW=[`local`,`orca_cloud`,`cloud`,`standard`],tje={local:1.75,orca_cloud:1.5,cloud:1,standard:.5};function qW(e,t){for(let n of KW){let r=e[n][t];if(r.length>0)return{source:r[0].source,id:r[0].id}}return null}function JW(e,t,n){return t?e[t.source][n].find(e=>e.id===t.id)??null:null}function YW(e,t,n){if(!n)return null;for(let r of KW){let i=e[r][t].find(e=>e.name===n);if(i)return{source:i.source,id:i.id}}return null}function nje(e,t,n,r){let i=YW(e,`process`,r);if(i){let r=JW(e,i,`process`);if(r&&SU(r,`process`,t,n)!==`mismatch`)return i}for(let r of[`match`,`unknown`])for(let i of KW)for(let a of e[i].process)if(SU(a,`process`,t,n)===r)return{source:a.source,id:a.id};return qW(e,`process`)}function rje(e,t,n,r){let i=t.type.trim().toUpperCase(),a=$f(t.color),o=null,s=null;for(let c of KW)for(let l of e[c].filament){let e=0,u=(l.filament_type??``).trim().toUpperCase(),d=$f(l.filament_colour??``);i&&u&&i===u&&(e+=10),a&&d&&(d===a?e+=5:ap(l.filament_colour??``,t.color)&&(e+=2)),e+=tje[c];let f={source:l.source,id:l.id};SU(l,`filament`,n,r)===`mismatch`?(s==null||e>s.score)&&(s={ref:f,score:e}):(o==null||e>o.score)&&(o={ref:f,score:e})}return o==null?s==null?qW(e,`filament`):s.ref:o.ref}function ije(e){return e?`${e.source}:${e.id}`:``}function aje(e){if(!e)return null;let t=e.indexOf(`:`);if(t<0)return null;let n=e.slice(0,t),r=e.slice(t+1);return n!==`orca_cloud`&&n!==`cloud`&&n!==`local`&&n!==`standard`?null:{source:n,id:r}}function oje({requestId:e,sourceName:t}){let{t:n}=$e(),{showPersistentToast:r,dismissToast:i}=Pd(),[a,o]=(0,y.useState)(0),[s,c]=(0,y.useState)(null),l=t;try{l=decodeURIComponent(t)}catch{}(0,y.useEffect)(()=>{let e=Date.now(),t=setInterval(()=>o(Math.floor((Date.now()-e)/1e3)),1e3);return()=>clearInterval(t)},[]),(0,y.useEffect)(()=>{let t=!1,n=setInterval(async()=>{if(t)return;let n=await Q.getPreviewSliceProgress(e);!t&&n&&c(n)},1e3);return()=>{t=!0,clearInterval(n)}},[e]);let u=`slice-preview-${e}`;(0,y.useEffect)(()=>{let e=s&&s.stage&&s.total_percent>0,t=sje(a);return e?r(u,n(`slice.previewWithProgress`,`Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,{name:l,stage:s.stage,percent:Math.min(100,Math.max(0,Math.round(s.total_percent))),elapsed:t}),`loading`):r(u,n(`slice.previewToast`,{name:l,elapsed:t}),`loading`),()=>{i(u)}},[a,s,l,r,i,n,u]);let d=s?.stage,f=s?.total_percent,p=d&&typeof f==`number`&&f>0?`${d} (${Math.min(100,Math.max(0,Math.round(f)))}%)`:n(`slice.analyzingPlateFilaments`);return(0,K.jsxs)(`div`,{className:`flex flex-col gap-1 text-bambu-gray text-sm py-2`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),p,(0,K.jsxs)(`span`,{className:`text-xs tabular-nums`,children:[a,`s`]})]}),a>=5&&(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray/70 pl-6`,children:n(`slice.analyzingPlateFilamentsHint`,`Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.`)})]})}function sje(e){let t=Math.max(0,Math.floor(e));if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return n<60?`${n}m ${r}s`:`${Math.floor(n/60)}h ${n%60}m`}function cje(e){return Array.isArray(e)?e.map(e=>String(e)).join(`, `):e==null?``:String(e)}function XW({source:e,onClose:t}){let{t:n}=$e(),{trackJob:r}=WW(),i=ao(),[a,o]=(0,y.useState)(null),[s,c]=(0,y.useState)(null),[l,u]=(0,y.useState)([]),[d,f]=(0,y.useState)(null),[p,m]=(0,y.useState)(null),[h,g]=(0,y.useState)(!1),[_,v]=(0,y.useState)(null),[b,x]=(0,y.useState)(!1),[S,C]=(0,y.useState)(!1),[w,T]=(0,y.useState)(!1),[E,D]=(0,y.useState)(new Set),[O,k]=(0,y.useState)(!1),A=q({queryKey:[`slicer-pipelines`],queryFn:()=>Q.listSlicerPipelines(),staleTime:6e4}),[j,M]=(0,y.useState)(!1),[N,P]=(0,y.useState)(``),{showToast:F}=Pd(),I=J({mutationFn:e=>Q.createSlicerPipeline(e),onSuccess:()=>{i.invalidateQueries({queryKey:[`slicer-pipelines`]}),F(n(`slice.pipelines.toast.saved`,`Pipeline saved`),`success`),M(!1),P(``)},onError:e=>{F(e.message||n(`slice.pipelines.toast.saveFailed`,`Save failed`),`error`)}}),L=q({queryKey:[`slicePlates`,e.kind,e.id],queryFn:async()=>e.kind===`libraryFile`?Q.getLibraryFilePlates(e.id):Q.getArchivePlates(e.id),staleTime:6e4}),R=!!L.data?.is_multi_plate&&(L.data?.plates?.length??0)>1,z=R&&p==null,B=p??1,V=(0,y.useMemo)(()=>{let t=typeof crypto<`u`&&`randomUUID`in crypto?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2)}`;return`${e.kind}-${e.id}-p${B}-${t}`},[e.kind,e.id,B]),ee=q({queryKey:[`sliceFilamentReqs`,e.kind,e.id,B],queryFn:async()=>e.kind===`libraryFile`?Q.getLibraryFileFilamentRequirements(e.id,B,V,!0):Q.getArchiveFilamentRequirements(e.id,B,V,!0),enabled:!z,staleTime:6e4}),te=(0,y.useMemo)(()=>{let e=ee.data?.filaments??[],t=e.length>0?e:[{slot_id:1,type:``,color:``,used_grams:0,used_meters:0}];return h?t.map(e=>({...e,used_in_plate:!0})):t},[h,ee.data]),H=q({queryKey:[`slicerPresets`],queryFn:()=>Q.getSlicerPresets(),staleTime:6e4,enabled:!L.isLoading&&!z}),[ne,re]=(0,y.useState)(!1),U=async()=>{if(!ne){re(!0);try{let e=await Q.getSlicerPresets({refresh:!0});i.setQueryData([`slicerPresets`],e)}catch{i.invalidateQueries({queryKey:[`slicerPresets`]})}finally{re(!1)}}},ie=q({queryKey:[`slicerPrinterModels`],queryFn:Q.getSlicerPrinterModels,staleTime:1/0}),ae=(0,y.useMemo)(()=>!H.data||!a?null:JW(H.data,a,`printer`)?.name??null,[H.data,a]),W=(0,y.useMemo)(()=>_U(ie.data??{}),[ie.data]),oe=L.data?.embedded_printer??null,se=(0,y.useMemo)(()=>L.data?.design_overrides??[],[L.data]),ce=L.data?.embedded_process??null,le=(0,y.useMemo)(()=>{if(!oe||!ce||!ae)return!1;let e=e=>e.replace(/^#\s*/,``).trim().toLowerCase();return e(ae)===e(oe)},[oe,ce,ae]);(0,y.useEffect)(()=>{le||x(!1)},[le]),(0,y.useEffect)(()=>{D(new Set(se.filter(e=>!e.printer_coupled).map(e=>e.key)))},[se]),(0,y.useEffect)(()=>{let e=H.data;e&&(a??o(YW(e,`printer`,oe)??qW(e,`printer`)))},[H.data,oe]),(0,y.useEffect)(()=>{let e=H.data;e&&c(t=>{if(t){let n=JW(e,t,`process`);if(n&&SU(n,`process`,ae,W)!==`mismatch`)return t}return nje(e,ae,W,ce)})},[H.data,ae,W,ce]),(0,y.useEffect)(()=>{let e=H.data;e&&u(t=>te.map((n,r)=>{let i=t[r]??null;if(i){let t=JW(e,i,`filament`);if(t&&SU(t,`filament`,ae,W)!==`mismatch`)return i}return rje(e,{type:n.type,color:n.color},ae,W)}))},[H.data,te,ae,W]);let ue=J({mutationFn:async t=>{let n=de(t);return e.kind===`libraryFile`?Q.sliceLibraryFile(e.id,n):Q.sliceArchive(e.id,n)},onSuccess:n=>{r(n.job_id,e.kind,e.filename),t()},onError:e=>{f(e instanceof Error?e.message:String(e))}});function de(e){if(!a||!s||l.length===0||l.some(e=>e==null))throw Error(n(`slice.allPresetsRequired`));return{printer_preset:a,process_preset:s,filament_preset:l[0],filament_presets:l,...e==null?{}:{plate:e},..._==null?{}:{bed_type:_},...b&&le?{use_embedded_settings:!0}:{},...!b&&E.size>0?{design_overrides:[...E]}:{},...S?{auto_orient:!0}:{},...w?{auto_arrange:!0}:{}}}let fe=a!=null&&s!=null&&ee.isSuccess&&l.length>0&&l.every(e=>e!=null),pe=ue.isPending,me=L.data?.plates?.length??0,he=R&&me>1&&!z;return z&&L.data?(0,K.jsx)(GW,{plates:L.data.plates,onSelect:e=>m(e),onClose:t}):(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4`,onClick:()=>{pe||t()},children:(0,K.jsxs)(`div`,{className:`w-full max-w-xl max-h-[85vh] flex flex-col rounded-lg bg-bambu-dark-secondary border border-bambu-dark-tertiary/60`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex-shrink-0 flex items-start justify-between gap-3 px-4 pt-4 pb-3 border-b border-bambu-dark-tertiary/40`,children:[(0,K.jsxs)(`div`,{className:`min-w-0`,children:[(0,K.jsxs)(`h3`,{className:`text-white font-medium flex items-center gap-2`,children:[(0,K.jsx)(Ns,{className:`w-4 h-4`}),n(`slice.title`)]}),(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray mt-1 truncate`,title:e.filename,children:[e.filename,p==null?``:` • ${n(`archives.platePicker.plateLabel`,{index:p})}`]})]}),(0,K.jsx)(`button`,{onClick:t,disabled:pe,className:`flex-shrink-0 text-bambu-gray hover:text-white transition-colors disabled:opacity-50`,"aria-label":n(`common.close`),children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-4`,children:[(L.isLoading||H.isLoading)&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-bambu-gray text-sm`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),n(`slice.loadingPresets`)]}),H.isError&&(0,K.jsx)(`div`,{className:`text-sm text-red-700 dark:text-red-400`,role:`alert`,children:n(`slice.presetsLoadFailed`,`Failed to load presets. Open Settings → Profiles to import them, or sign in to Bambu Cloud.`)}),H.data&&(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,K.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,K.jsx)(ZW,{status:H.data.cloud_status,cloudName:`bambu`}),(0,K.jsx)(ZW,{status:H.data.orca_cloud_status,cloudName:`orca`})]}),(0,K.jsxs)(`button`,{type:`button`,onClick:U,disabled:ne||pe,className:`flex-shrink-0 inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs text-bambu-gray hover:text-white hover:bg-bambu-dark-tertiary/40 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,title:n(`slice.refreshPresetsTitle`),"aria-label":n(`slice.refreshPresets`),children:[(0,K.jsx)(Fl,{className:`w-3.5 h-3.5 ${ne?`animate-spin`:``}`}),n(`slice.refreshPresets`)]})]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 px-2 py-1.5 rounded-md bg-bambu-dark/40 border border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`span`,{className:`text-xs font-medium text-bambu-gray flex items-center gap-1`,children:[(0,K.jsx)(Ns,{className:`w-3.5 h-3.5`}),` `,n(`slice.pipelines.label`,`Pipeline`)]}),(0,K.jsxs)(`select`,{value:``,disabled:pe||(A.data?.pipelines.length??0)===0,onChange:e=>{let t=parseInt(e.target.value,10);if(Number.isNaN(t))return;let r=A.data?.pipelines.find(e=>e.id===t);r&&(o(r.printer_preset),c(r.process_preset),v(r.bed_type),u(e=>{let t=e.length>0?[...e]:r.filament_presets.map(()=>null);for(let e=0;e(0,K.jsx)(`option`,{value:e.id,children:e.name},e.id))]}),j?(0,K.jsxs)(`div`,{className:`flex items-center gap-1 flex-1 min-w-[16ch]`,children:[(0,K.jsx)(`input`,{autoFocus:!0,value:N,onChange:e=>P(e.target.value),placeholder:n(`slice.pipelines.namePlaceholder`,`Pipeline name`),"aria-label":n(`slice.pipelines.nameAria`,`New pipeline name`),className:`flex-1 text-xs px-2 py-1 bg-bambu-dark border border-bambu-dark-tertiary rounded text-white`}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>{let e=N.trim();if(!e||!a||!s)return;let t=l.filter(e=>e!==null);t.length!==0&&I.mutate({name:e,printer_preset:a,process_preset:s,filament_presets:t,bed_type:_})},disabled:I.isPending||!N.trim(),className:`text-xs px-2 py-1 bg-bambu-green hover:bg-bambu-green/80 text-white rounded disabled:opacity-50`,children:I.isPending?(0,K.jsx)(X,{className:`w-3 h-3 animate-spin`}):n(`common.save`,`Save`)}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>{M(!1),P(``)},className:`text-xs px-2 py-1 text-bambu-gray hover:text-white`,children:n(`common.cancel`,`Cancel`)})]}):(0,K.jsx)(`button`,{type:`button`,onClick:()=>{P(``),M(!0)},disabled:pe||!a||!s||l.length===0||l.some(e=>e===null),className:`text-xs px-2 py-1 bg-bambu-green/20 hover:bg-bambu-green/30 text-bambu-green border border-bambu-green/40 rounded disabled:opacity-50 disabled:cursor-not-allowed`,title:n(`slice.pipelines.saveTitle`,`Save the current four-slot selection as a reusable pipeline`),children:n(`slice.pipelines.saveButton`,`Save as pipeline`)})]}),(0,K.jsx)(QW,{label:n(`slice.printer`),slot:`printer`,data:H.data,value:a,onChange:o,disabled:pe||b}),le&&(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-sm text-bambu-gray cursor-pointer select-none`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:b,onChange:e=>x(e.target.checked),disabled:pe,className:`mt-0.5 cursor-pointer`}),(0,K.jsxs)(`span`,{children:[n(`slice.useEmbedded`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.useEmbeddedHint`)})]})]}),(0,K.jsx)(QW,{label:n(`slice.process`),slot:`process`,data:H.data,value:s,onChange:c,disabled:pe||b,selectedPrinterName:ae,compatIndex:W}),se.length>0&&(0,K.jsxs)(`div`,{className:`rounded-lg border border-bambu-dark-tertiary bg-bambu-dark/40 p-3`,children:[(0,K.jsxs)(`button`,{type:`button`,onClick:()=>k(e=>!e),className:`flex w-full items-center justify-between gap-2 text-left`,children:[(0,K.jsxs)(`span`,{className:`text-sm text-white`,children:[n(`slice.designSettings`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.designSettingsHint`,{count:se.length})})]}),(0,K.jsx)(`span`,{className:`shrink-0 text-xs text-bambu-gray`,children:n(`slice.designSettingsSelected`,{selected:E.size,total:se.length})})]}),O&&(0,K.jsx)(`div`,{className:`mt-3 space-y-1.5 border-t border-bambu-dark-tertiary pt-3`,children:se.map(e=>(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-xs ${b?`opacity-50`:`cursor-pointer`}`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:E.has(e.key),disabled:pe||b,onChange:t=>{D(n=>{let r=new Set(n);return t.target.checked?r.add(e.key):r.delete(e.key),r})},className:`mt-0.5 shrink-0 cursor-pointer`}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`span`,{className:`font-mono text-bambu-gray`,children:e.key}),(0,K.jsx)(`span`,{className:`ml-1.5 break-all text-white`,children:cje(e.value)}),e.printer_coupled&&(0,K.jsx)(`span`,{className:`ml-1.5 rounded bg-amber-100 px-1 py-0.5 text-[10px] text-amber-700 dark:bg-amber-500/20 dark:text-amber-400`,title:n(`slice.designSettingsPrinterCoupledHint`),children:n(`slice.designSettingsPrinterCoupled`)})]})]},e.key))})]}),(0,K.jsx)(uje,{value:_,onChange:v,disabled:pe||b}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-sm text-bambu-gray cursor-pointer select-none`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:S,onChange:e=>C(e.target.checked),disabled:pe,className:`mt-0.5 cursor-pointer`}),(0,K.jsxs)(`span`,{children:[n(`slice.autoOrient`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.autoOrientHint`)})]})]}),(0,K.jsxs)(`label`,{className:`flex items-start gap-2 text-sm text-bambu-gray cursor-pointer select-none`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:w,onChange:e=>T(e.target.checked),disabled:pe,className:`mt-0.5 cursor-pointer`}),(0,K.jsxs)(`span`,{children:[n(`slice.autoArrange`),(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray/70`,children:n(`slice.autoArrangeHint`)})]})]})]}),ee.isLoading?(0,K.jsx)(oje,{requestId:V,sourceName:e.filename}):te.map((e,t)=>{let r=e.used_in_plate!==!1,i=te.length>1?n(`slice.filamentSlot`,{index:t+1,type:e.type}):n(`slice.filament`);return(0,K.jsx)(QW,{label:r?i:`${i} ${n(`slice.notUsedByPlate`)}`,slot:`filament`,data:H.data,value:l[t]??null,onChange:e=>u(n=>{let r=n.length===te.length?[...n]:te.map((e,t)=>n[t]??null);return r[t]=e,r}),disabled:pe||!r||b,swatchColor:te.length>1?e.color:void 0,selectedPrinterName:ae,compatIndex:W},`filament-${t}`)})]}),d&&(0,K.jsx)(`div`,{className:`text-sm text-red-700 dark:text-red-400 bg-red-900/20 border border-red-900/40 rounded p-2`,role:`alert`,children:d})]}),(0,K.jsxs)(`div`,{className:`flex-shrink-0 flex justify-end gap-2 px-4 py-3 border-t border-bambu-dark-tertiary/40`,children:[(0,K.jsx)(`button`,{type:`button`,onClick:t,disabled:pe,className:`px-3 py-1.5 text-sm rounded-md border border-bambu-dark-tertiary text-bambu-gray hover:text-white hover:border-bambu-gray transition-colors disabled:opacity-50`,children:n(`common.cancel`)}),he&&(0,K.jsxs)(`label`,{className:`flex items-center gap-2 mr-auto text-sm text-bambu-gray cursor-pointer select-none`,title:n(`slice.actionAllTitle`,{count:me}),children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:h,onChange:e=>g(e.target.checked),disabled:pe,className:`cursor-pointer`}),n(`slice.allPlatesToggle`,{count:me})]}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>{f(null);let e=h?0:p;ue.mutate(e)},disabled:!fe||pe,className:`px-3 py-1.5 text-sm rounded-md bg-bambu-green hover:bg-bambu-green/90 text-bambu-dark font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2`,children:pe?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),n(`slice.enqueuing`)]}):h?n(`slice.actionAll`,{count:me}):n(`slice.action`)})]})]})})}function ZW({status:e,cloudName:t=`bambu`}){let{t:n}=$e();if(e===`ok`||e===`not_authenticated`)return null;let r=t===`orca`?{expired:{key:`slice.orcaCloud.expired`,fallback:`Orca Cloud session expired — sign in again to refresh your Orca presets.`},unreachable:{key:`slice.orcaCloud.unreachable`,fallback:`Orca Cloud is unreachable right now. Other presets still work.`}}:{expired:{key:`slice.cloud.expired`,fallback:`Bambu Cloud session expired — sign in again to refresh your cloud presets.`},unreachable:{key:`slice.cloud.unreachable`,fallback:`Bambu Cloud is unreachable right now. Local and standard presets still work.`}},{tone:i,icon:a}={expired:{tone:`border-amber-300 dark:border-amber-700/40 bg-amber-50 dark:bg-amber-900/20 text-amber-800 dark:text-amber-200`,icon:Es},unreachable:{tone:`border-bambu-dark-tertiary/40 bg-bambu-dark text-bambu-gray`,icon:Es}}[e],{key:o,fallback:s}=r[e];return(0,K.jsxs)(`div`,{className:`flex items-start gap-2 text-xs rounded-md border p-2 ${i}`,role:`status`,children:[(0,K.jsx)(a,{className:`w-4 h-4 flex-shrink-0 mt-0.5`}),(0,K.jsx)(`span`,{children:n(o,s)})]})}var lje=[{value:`Cool Plate`,labelKey:`slice.bedType.coolPlate`,fallback:`Cool Plate`},{value:`Cool Plate (SuperTack)`,labelKey:`slice.bedType.coolPlateSuperTack`,fallback:`Cool Plate SuperTack`},{value:`Engineering Plate`,labelKey:`slice.bedType.engineering`,fallback:`Engineering Plate`},{value:`High Temp Plate`,labelKey:`slice.bedType.highTemp`,fallback:`High Temp Plate`},{value:`Textured PEI Plate`,labelKey:`slice.bedType.texturedPEI`,fallback:`Textured PEI Plate`},{value:`Smooth PEI Plate`,labelKey:`slice.bedType.smoothPEI`,fallback:`Smooth PEI Plate`}];function uje({value:e,onChange:t,disabled:n}){let{t:r}=$e();return(0,K.jsxs)(`label`,{className:`block`,children:[(0,K.jsx)(`span`,{className:`block text-xs text-bambu-gray mb-1`,children:r(`slice.bedType.label`)}),(0,K.jsxs)(`select`,{value:e??``,onChange:e=>t(e.target.value===``?null:e.target.value),disabled:n,className:`w-full px-3 py-2 rounded-md bg-bambu-dark border border-bambu-dark-tertiary text-white text-sm focus:outline-none focus:border-bambu-gray disabled:opacity-50`,children:[(0,K.jsx)(`option`,{value:``,children:r(`slice.bedType.auto`)}),lje.map(e=>(0,K.jsx)(`option`,{value:e.value,children:r(e.labelKey,e.fallback)},e.value))]})]})}function QW({label:e,slot:t,data:n,value:r,onChange:i,disabled:a,swatchColor:o,selectedPrinterName:s,compatIndex:c}){let{t:l}=$e(),{sections:u,otherEntries:d}=(0,y.useMemo)(()=>{let e=[{key:`local`,label:`slice.tier.local`,fallback:`Imported`},{key:`orca_cloud`,label:`slice.tier.orcaCloud`,fallback:`Orca Cloud`},{key:`cloud`,label:`slice.tier.cloud`,fallback:`Bambu Cloud`},{key:`standard`,label:`slice.tier.standard`,fallback:`Standard`}],r=t!==`printer`,i=[],a=[];for(let{key:o,label:u,fallback:d}of e){let e=n[o][t];if(!r){e.length>0&&i.push({tierLabel:l(u,d),entries:e});continue}let f=[];for(let n of e)SU(n,t,s??null,c??Uke)===`mismatch`?a.push(n):f.push(n);f.length>0&&i.push({tierLabel:l(u,d),entries:f})}return{sections:i,otherEntries:a}},[n,t,l,s,c]),f=u.reduce((e,t)=>e+t.entries.length,0)+d.length;return(0,K.jsxs)(`label`,{className:`block`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2 text-xs text-bambu-gray mb-1`,children:[o&&(0,K.jsx)(`span`,{className:`inline-block w-3 h-3 rounded-full border border-bambu-dark-tertiary`,style:{backgroundColor:o||`transparent`},"aria-hidden":!0}),(0,K.jsx)(`span`,{children:e})]}),(0,K.jsxs)(`select`,{value:ije(r),onChange:e=>i(aje(e.target.value)),disabled:a||f===0,className:`w-full px-3 py-2 rounded-md bg-bambu-dark border border-bambu-dark-tertiary text-white text-sm focus:outline-none focus:border-bambu-gray disabled:opacity-50`,children:[(0,K.jsx)(`option`,{value:``,children:l(f===0?`slice.noPresetsForSlot`:`slice.selectPreset`)}),u.map(e=>(0,K.jsx)(`optgroup`,{label:e.tierLabel,children:e.entries.map(e=>(0,K.jsx)(`option`,{value:`${e.source}:${e.id}`,children:e.name},`${e.source}:${e.id}`))},e.tierLabel)),d.length>0&&(0,K.jsx)(`optgroup`,{label:l(`slice.otherPrinters`),children:d.map(e=>(0,K.jsx)(`option`,{value:`${e.source}:${e.id}`,children:e.name},`${e.source}:${e.id}`))})]})]})}function $W({source:e,onClose:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(null),[s,c]=(0,y.useState)(null),[l,u]=(0,y.useState)(1),{trackJob:d}=WW(),{data:f,isLoading:p}=q({queryKey:[`slicer-pipelines`],queryFn:()=>Q.listSlicerPipelines()}),{data:m}=q({queryKey:[`printers`],queryFn:()=>Q.getPrinters()}),{data:h}=q({queryKey:[`app-settings`],queryFn:()=>Q.getSettings()}),g=h?.pipeline_max_copies??50,_={kind:e.kind,id:e.id},v=J({mutationFn:e=>Q.checkPipelineEligibility(e,_)}),b=J({mutationFn:({pipelineId:e,force:t})=>Q.runPipeline(e,_,t,l),onSuccess:a=>{r.invalidateQueries({queryKey:[`slicer-pipelines`]}),r.invalidateQueries({queryKey:[`pipeline-runs`]}),a.slice_job_id&&d(a.slice_job_id,e.kind,e.filename),i(n(`library.runWithPipeline.toast.started`,`Pipeline run started`),`success`),t()},onError:e=>{i(e.message||n(`library.runWithPipeline.toast.failed`,`Could not start run`),`error`)}}),x=f?.pipelines??[],S=(m??[]).reduce((e,t)=>(e[t.id]=t,e),{});return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 bg-black/60 flex items-center justify-center p-4`,onClick:t,role:`dialog`,"aria-modal":`true`,"aria-label":n(`library.runWithPipeline.modalTitle`,`Run with pipeline`),children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-2xl w-full max-w-md max-h-[80vh] flex flex-col overflow-hidden`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-4 py-3 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`h3`,{className:`text-sm font-semibold text-white flex items-center gap-2`,children:[(0,K.jsx)(Dl,{className:`w-4 h-4 text-bambu-green`}),a&&s?n(`library.runWithPipeline.confirmTitle`,`Confirm run`):n(`library.runWithPipeline.modalTitle`,`Run with pipeline`)]}),(0,K.jsx)(`button`,{type:`button`,onClick:t,"aria-label":n(`common.close`,`Close`),className:`text-bambu-gray hover:text-white`,children:(0,K.jsx)(Ju,{className:`w-4 h-4`})})]}),(0,K.jsx)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-3`,children:a&&s?(0,K.jsx)(fje,{pipeline:a,report:s,source:e,onBack:()=>{o(null),c(null)},onConfirm:()=>{a&&b.mutate({pipelineId:a.id,force:!0})},running:b.isPending}):(0,K.jsx)(dje,{source:e,pipelines:x,printerById:S,loading:p||v.isPending,onPick:async e=>{if(!(e.target_printer_id||e.target_kind===`printer_class`&&e.target_model_class)){i(n(`library.runWithPipeline.noTargetMessage`,`This pipeline has no target printer set. Open it in Settings to pick one.`),`error`);return}o(e);try{let t=await v.mutateAsync(e.id);c(t),t.ok&&b.mutate({pipelineId:e.id,force:!1})}catch{o(null)}},copies:l,maxCopies:g,onCopiesChange:u})})]})})}function dje({source:e,pipelines:t,printerById:n,loading:r,onPick:i,copies:a,maxCopies:o,onCopiesChange:s}){let{t:c}=$e();return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray`,children:[c(`library.runWithPipeline.sourceHint`,`Source`),`:`,` `,(0,K.jsx)(`span`,{className:`text-white`,children:e.filename})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsxs)(`label`,{className:`text-xs text-bambu-gray`,htmlFor:`run-pipeline-copies`,children:[c(`library.runWithPipeline.copies`,`Copies`),`:`]}),(0,K.jsx)(`input`,{id:`run-pipeline-copies`,type:`number`,min:1,max:o,value:a,onChange:e=>{let t=parseInt(e.target.value,10);Number.isNaN(t)||s(Math.max(1,Math.min(o,t)))},"aria-label":c(`library.runWithPipeline.copies`,`Copies`),className:`w-20 px-2 py-1 text-xs bg-bambu-dark border border-bambu-dark-tertiary rounded text-white`}),(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray/60`,children:c(`library.runWithPipeline.copiesHint`,`max {{n}}`,{n:o})})]}),r&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-bambu-gray`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),c(`library.runWithPipeline.loading`,`Loading…`)]}),!r&&t.length===0&&(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:c(`library.runWithPipeline.empty`,`No pipelines saved yet. Open the Slice dialog and click "Save as pipeline" to create one.`)}),!r&&t.length>0&&(0,K.jsx)(`ul`,{className:`space-y-1.5`,"aria-label":c(`library.runWithPipeline.pipelineListAria`,`Available pipelines`),children:t.map(e=>{let t=e.target_kind===`printer_class`,r=e.target_printer_id?n[e.target_printer_id]?.name:null,a=t&&e.target_model_class?c(`library.runWithPipeline.classTarget`,`Any {{model}}`,{model:e.target_model_class}):null;return(0,K.jsx)(`li`,{children:(0,K.jsxs)(`button`,{type:`button`,onClick:()=>i(e),disabled:!(e.target_printer_id||t&&e.target_model_class),className:`w-full text-left px-3 py-2 rounded-md border border-bambu-dark-tertiary bg-bambu-dark/40 hover:bg-bambu-dark-tertiary disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(Ns,{className:`w-3.5 h-3.5 text-bambu-green flex-shrink-0`}),(0,K.jsx)(`span`,{className:`text-sm font-medium text-white truncate`,children:e.name})]}),(0,K.jsxs)(`div`,{className:`mt-1 text-xs text-bambu-gray flex items-center gap-1`,children:[(0,K.jsx)(Ml,{className:`w-3 h-3`}),a?(0,K.jsx)(`span`,{children:a}):r?(0,K.jsx)(`span`,{children:r}):(0,K.jsx)(`span`,{className:`text-amber-700 dark:text-amber-400`,children:c(`library.runWithPipeline.noTarget`,`No target printer set`)})]})]})},e.id)})})]})}function fje({pipeline:e,report:t,source:n,onBack:r,onConfirm:i,running:a}){let{t:o}=$e();return(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`div`,{className:`text-xs text-bambu-gray`,children:[(0,K.jsxs)(`p`,{children:[o(`library.runWithPipeline.confirmIntro`,`Pre-flight found issues with this run`),`:`]}),(0,K.jsxs)(`p`,{className:`mt-1`,children:[(0,K.jsxs)(`span`,{className:`text-bambu-gray/70`,children:[o(`library.runWithPipeline.sourceHint`,`Source`),`: `]}),(0,K.jsx)(`span`,{className:`text-white`,children:n.filename})]}),(0,K.jsxs)(`p`,{children:[(0,K.jsxs)(`span`,{className:`text-bambu-gray/70`,children:[o(`library.runWithPipeline.pipelineHint`,`Pipeline`),`: `]}),(0,K.jsx)(`span`,{className:`text-white`,children:e.name})]}),t.target_printer_name&&(0,K.jsxs)(`p`,{children:[(0,K.jsxs)(`span`,{className:`text-bambu-gray/70`,children:[o(`library.runWithPipeline.targetHint`,`Target`),`: `]}),(0,K.jsx)(`span`,{className:`text-white`,children:t.target_printer_name})]})]}),(0,K.jsx)(`ul`,{className:`space-y-1.5`,children:t.issues.map((e,t)=>(0,K.jsxs)(`li`,{className:`flex items-start gap-2 text-xs`,children:[(0,K.jsx)(Au,{className:`w-3.5 h-3.5 text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5`}),(0,K.jsx)(`span`,{className:`text-bambu-gray`,children:(0,K.jsx)(pje,{issue:e})})]},t))}),(0,K.jsxs)(`div`,{className:`flex items-center justify-end gap-2 pt-2 border-t border-bambu-dark-tertiary`,children:[(0,K.jsx)(`button`,{type:`button`,onClick:r,disabled:a,className:`px-3 py-1.5 text-xs text-bambu-gray hover:text-white`,children:o(`common.back`,`Back`)}),(0,K.jsxs)(`button`,{type:`button`,onClick:i,disabled:a,className:`px-3 py-1.5 text-xs bg-amber-500 hover:bg-amber-600 text-white rounded disabled:opacity-50 flex items-center gap-1`,children:[a?(0,K.jsx)(X,{className:`w-3 h-3 animate-spin`}):(0,K.jsx)(Dl,{className:`w-3 h-3`}),o(`library.runWithPipeline.runAnyway`,`Run anyway`)]})]})]})}function pje({issue:e}){let{t}=$e();switch(e.kind){case`printer_not_set`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerNotSet`,`No target printer set on this pipeline.`)});case`printer_not_found`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerNotFound`,`Target printer no longer exists.`)});case`printer_disabled`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerDisabled`,`Target printer is disabled.`)});case`printer_offline`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.printerOffline`,`Target printer is offline.`)});case`filament_type_mismatch`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.filamentType`,`Filament slot {{slot}}: expected {{expected}}, AMS has {{actual}}`,{slot:(e.slot_index??0)+1,expected:e.expected??`?`,actual:e.actual??`?`})});case`filament_color_mismatch`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.filamentColor`,`Filament slot {{slot}}: colour differs (expected {{expected}}, AMS has {{actual}})`,{slot:(e.slot_index??0)+1,expected:e.expected??`?`,actual:e.actual??`?`})});case`ams_slot_missing`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.amsSlotMissing`,`AMS slot {{slot}} not available on this printer`,{slot:(e.slot_index??0)+1})});case`filament_unverified`:return(0,K.jsx)(K.Fragment,{children:t(`library.runWithPipeline.issue.filamentUnverified`,`Filament slot {{slot}} comes from a cloud / standard preset and could not be statically verified.`,{slot:(e.slot_index??0)+1})});default:return(0,K.jsx)(K.Fragment,{children:e.kind})}}function mje(){let e=navigator.userAgent.toLowerCase(),t=navigator.platform?.toLowerCase()||``;return e.includes(`win`)||t.includes(`win`)?`windows`:e.includes(`mac`)||t.includes(`mac`)?`macos`:e.includes(`linux`)||t.includes(`linux`)?`linux`:`unknown`}function eG(e,t=`bambu_studio`){let n,r=encodeURIComponent(e);n=t===`orcaslicer`?`orcaslicer://open?file=${r}`:mje()===`macos`?`bambustudioopen://${r}`:`bambustudio://open?file=${r}`;let i=document.createElement(`a`);i.href=n,i.style.display=`none`,document.body.appendChild(i),i.click(),document.body.removeChild(i)}var hje=[[`projects`],[`project`],[`project-archives`],[`project-timeline`],[`project-file-progress`]];function gje(e){return Promise.all(hje.map(t=>e.invalidateQueries({queryKey:[...t]})))}function tG(e){return Promise.all([e.invalidateQueries({queryKey:[`archives`]}),gje(e)])}function nG({onFiles:e,onRejected:t,extensions:n,disabled:r=!1}){let[i,a]=(0,y.useState)(!1),o=(0,y.useRef)(e),s=(0,y.useRef)(t),c=(0,y.useRef)(n);(0,y.useEffect)(()=>{o.current=e},[e]),(0,y.useEffect)(()=>{s.current=t},[t]),(0,y.useEffect)(()=>{c.current=n},[n]);let l=(0,y.useCallback)(e=>{r||(e.preventDefault(),e.dataTransfer.types.includes(`Files`)&&a(!0))},[r]),u=(0,y.useCallback)(e=>{r||(e.preventDefault(),e.dataTransfer.types.includes(`Files`)&&a(!0))},[r]),d=(0,y.useCallback)(e=>{if(r)return;e.preventDefault();let t=e.currentTarget,n=e.relatedTarget;(!n||!t.contains(n))&&a(!1)},[r]),f=(0,y.useCallback)(e=>{if(r)return;e.preventDefault(),a(!1);let t=Array.from(e.dataTransfer.files);if(t.length===0)return;let n=c.current,i=n&&n.length>0?t.filter(e=>n.some(t=>e.name.toLowerCase().endsWith(t))):t;i.length>0?o.current(i):s.current?.()},[r]);return(0,y.useEffect)(()=>{if(!i)return;let e=()=>a(!1),t=t=>{t.key===`Escape`&&e()};return document.addEventListener(`drop`,e),document.addEventListener(`dragend`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`drop`,e),document.removeEventListener(`dragend`,e),document.removeEventListener(`keydown`,t)}},[i]),{isDraggingOver:i,dragHandlers:{onDragOver:l,onDragEnter:u,onDragLeave:d,onDrop:f}}}function _je({onClose:e,initialFiles:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),a=(0,y.useRef)(null),[o,s]=(0,y.useState)(()=>t?.filter(e=>e.name.endsWith(`.3mf`)).map(e=>({file:e,status:`pending`}))||[]),[c,l]=(0,y.useState)(!1),[u,d]=(0,y.useState)(null);(0,y.useEffect)(()=>{let t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]);let f=J({mutationFn:e=>Q.uploadArchivesBulk(e),onSuccess:e=>{d(e),r.invalidateQueries({queryKey:[`archives`]}),r.invalidateQueries({queryKey:[`archiveStats`]}),s(t=>t.map(t=>{let n=e.results.find(e=>e.filename===t.file.name),r=e.errors.find(e=>e.filename===t.file.name);return n?{...t,status:`success`,archiveId:n.id}:r?{...t,status:`error`,error:r.error}:t})),e.failed===0?i(`${e.uploaded} file${e.uploaded===1?``:`s`} uploaded`):e.uploaded===0?i(`Failed to upload ${e.failed} file${e.failed===1?``:`s`}`,`error`):i(`${e.uploaded} uploaded, ${e.failed} failed`,`warning`)},onError:()=>{s(e=>e.map(e=>({...e,status:`error`,error:`Upload failed`}))),i(`Upload failed`,`error`)}}),p=(0,y.useCallback)(e=>{e.preventDefault(),l(!0)},[]),m=(0,y.useCallback)(e=>{e.preventDefault(),l(!1)},[]),h=(0,y.useCallback)(e=>{e.preventDefault(),l(!1);let t=Array.from(e.dataTransfer.files).filter(e=>e.name.endsWith(`.3mf`));t.length>0&&s(e=>[...e,...t.map(e=>({file:e,status:`pending`}))])},[]),g=(0,y.useCallback)(e=>{let t=Array.from(e.target.files||[]).filter(e=>e.name.endsWith(`.3mf`));t.length>0&&s(e=>[...e,...t.map(e=>({file:e,status:`pending`}))]),a.current&&(a.current.value=``)},[]),_=(0,y.useCallback)(e=>{s(t=>t.filter((t,n)=>n!==e))},[]),v=()=>{if(o.length===0)return;let e=o.filter(e=>e.status===`pending`);e.length!==0&&(s(e=>e.map(e=>e.status===`pending`?{...e,status:`uploading`}:e)),f.mutate(e.map(e=>e.file)))},b=o.filter(e=>e.status===`pending`).length,x=f.isPending;return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,children:(0,K.jsx)(Dd,{className:`w-full max-w-2xl max-h-[90vh] flex flex-col`,children:(0,K.jsxs)(kd,{className:`p-0 flex flex-col h-full`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`h2`,{className:`text-xl font-semibold text-white`,children:n(`uploadModal.title`)}),(0,K.jsx)(`button`,{onClick:e,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsx)(`div`,{className:`p-4`,children:(0,K.jsxs)(`div`,{className:`border-2 border-dashed rounded-lg p-8 text-center transition-colors ${c?`border-bambu-green bg-bambu-green/10`:`border-bambu-dark-tertiary hover:border-bambu-gray`}`,onDragOver:p,onDragLeave:m,onDrop:h,children:[(0,K.jsx)(Pu,{className:`w-12 h-12 mx-auto mb-4 text-bambu-gray`}),(0,K.jsx)(`p`,{className:`text-white mb-2`,children:n(`uploadModal.dragDrop`)}),(0,K.jsx)(`p`,{className:`text-bambu-gray text-sm mb-4`,children:n(`uploadModal.or`)}),(0,K.jsx)($,{variant:`secondary`,onClick:()=>a.current?.click(),disabled:x,children:n(`uploadModal.browseFiles`)}),(0,K.jsx)(`input`,{ref:a,type:`file`,accept:`.3mf`,multiple:!0,className:`hidden`,onChange:g})]})}),(0,K.jsx)(`div`,{className:`px-4 pb-4`,children:(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:n(`uploadModal.extractionInfo`)})}),o.length>0&&(0,K.jsx)(`div`,{className:`px-4 pb-4 max-h-60 overflow-y-auto`,children:(0,K.jsx)(`div`,{className:`space-y-2`,children:o.map((e,t)=>(0,K.jsxs)(`div`,{className:`flex items-center gap-3 p-3 bg-bambu-dark rounded-lg`,children:[(0,K.jsx)(sc,{className:`w-5 h-5 text-bambu-gray flex-shrink-0`}),(0,K.jsx)(`span`,{className:`flex-1 text-white text-sm truncate`,children:e.file.name}),(0,K.jsxs)(`span`,{className:`text-xs text-bambu-gray`,children:[(e.file.size/(1024*1024)).toFixed(1),` MB`]}),e.status===`pending`&&(0,K.jsx)(`button`,{onClick:()=>_(t),className:`text-bambu-gray hover:text-red-600 dark:hover:text-red-400 transition-colors`,disabled:x,children:(0,K.jsx)(Ju,{className:`w-4 h-4`})}),e.status===`uploading`&&(0,K.jsx)(X,{className:`w-4 h-4 text-bambu-green animate-spin`}),e.status===`success`&&(0,K.jsx)(gs,{className:`w-4 h-4 text-bambu-green`}),e.status===`error`&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(`span`,{className:`text-xs text-red-700 dark:text-red-400`,children:e.error}),(0,K.jsx)(ms,{className:`w-4 h-4 text-red-600 dark:text-red-400`})]})]},`${e.file.name}-${t}`))})}),u&&(0,K.jsx)(`div`,{className:`px-4 pb-4`,children:(0,K.jsx)(`div`,{className:`p-3 bg-bambu-dark rounded-lg`,children:(0,K.jsxs)(`p`,{className:`text-sm text-white`,children:[(0,K.jsx)(`span`,{className:`text-bambu-green`,children:u.uploaded}),` `,n(`uploadModal.uploaded`),u.failed>0&&(0,K.jsxs)(K.Fragment,{children:[`, `,(0,K.jsx)(`span`,{className:`text-red-700 dark:text-red-400`,children:u.failed}),` `,n(`uploadModal.failed`)]})]})})}),(0,K.jsxs)(`div`,{className:`flex gap-3 p-4 border-t border-bambu-dark-tertiary`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:e,className:`flex-1`,children:n(u?`common.close`:`common.cancel`)}),!u&&(0,K.jsx)($,{onClick:v,disabled:b===0||x,className:`flex-1`,children:x?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),n(`uploadModal.uploading`)]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(Pu,{className:`w-4 h-4`}),n(`uploadModal.upload`),` `,b>0&&`(${b})`]})})]})]})})})}var vje=365;function yje({onClose:e,initialDays:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(t??vje),[s,c]=(0,y.useState)(!1),[l,u]=(0,y.useState)(a);(0,y.useEffect)(()=>{let e=window.setTimeout(()=>u(a),300);return()=>window.clearTimeout(e)},[a]);let d=q({queryKey:[`archive-purge-preview`,l,s],queryFn:()=>Q.previewArchivePurge(l,s),enabled:l>=1}),f=J({mutationFn:()=>Q.executeArchivePurge(a,s),onSuccess:t=>{i(n(`archivePurge.toast.success`,{count:t.deleted}),`success`),r.invalidateQueries({queryKey:[`archives`]}),r.invalidateQueries({queryKey:[`archive-stats`]}),e()},onError:e=>i(e.message||n(`archivePurge.toast.failed`),`error`)});(0,y.useEffect)(()=>{let t=t=>{t.key===`Escape`&&!f.isPending&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e,f.isPending]);let p=d.data,m=p?.count??0,h=p?.total_bytes??0,g=m>0&&!f.isPending;return(0,K.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,children:(0,K.jsxs)(`div`,{className:`bg-white dark:bg-gray-900 rounded-lg shadow-xl max-w-lg w-full`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700`,children:[(0,K.jsxs)(`h2`,{className:`text-lg font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2`,children:[(0,K.jsx)(Du,{className:`w-5 h-5`}),n(`archivePurge.title`)]}),(0,K.jsx)(`button`,{onClick:e,className:`text-gray-400 hover:text-gray-600 dark:hover:text-gray-200`,"aria-label":n(`common.close`),disabled:f.isPending,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-4`,children:[(0,K.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:n(`archivePurge.description`)}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{htmlFor:`archive-purge-days`,className:`block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1`,children:n(`archivePurge.ageLabel`)}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,K.jsx)(`input`,{id:`archive-purge-days`,type:`number`,min:1,max:3650,value:a,onChange:e=>o(Math.max(1,Math.min(3650,parseInt(e.target.value||`0`,10)||0))),className:`w-24 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm px-2 py-1 text-gray-900 dark:text-gray-100`}),(0,K.jsx)(`span`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:n(`archivePurge.days`)})]})]}),(0,K.jsxs)(`div`,{className:`rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/30 p-3`,children:[(0,K.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wide text-gray-600 dark:text-gray-300 mb-2`,children:n(`archivePurge.effectsTitle`)}),(0,K.jsxs)(`ul`,{className:`text-xs text-gray-700 dark:text-gray-300 space-y-1 list-disc pl-4`,children:[(0,K.jsx)(`li`,{children:n(`archivePurge.effect1`)}),(0,K.jsx)(`li`,{children:n(`archivePurge.effect2`)}),(0,K.jsx)(`li`,{children:n(`archivePurge.effect3`)}),(0,K.jsx)(`li`,{children:n(`archivePurge.effect4`)})]})]}),(0,K.jsx)(`div`,{className:`rounded border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 p-3`,children:d.isLoading||d.isFetching?(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400`,children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),` `,n(`archivePurge.previewLoading`)]}):d.isError?(0,K.jsx)(`div`,{className:`text-sm text-red-600 dark:text-red-400`,children:d.error?.message??n(`archivePurge.previewFailed`)}):(0,K.jsxs)(`div`,{className:`text-sm text-gray-900 dark:text-gray-100`,children:[(0,K.jsx)(`div`,{className:`font-medium`,children:n(`archivePurge.previewSummary`,{count:m,size:Md(h)})}),p?.sample_filenames&&p.sample_filenames.length>0&&(0,K.jsxs)(`ul`,{className:`mt-2 text-xs text-gray-600 dark:text-gray-400 space-y-0.5 list-disc pl-4`,children:[p.sample_filenames.map(e=>(0,K.jsx)(`li`,{className:`truncate`,children:e},e)),m>p.sample_filenames.length&&(0,K.jsx)(`li`,{className:`list-none italic text-gray-500`,children:n(`archivePurge.andMore`,{count:m-p.sample_filenames.length})})]})]})}),(0,K.jsxs)(`label`,{className:`flex gap-2 items-start rounded border border-gray-200 dark:border-gray-700 px-3 py-2 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50`,children:[(0,K.jsx)(`input`,{type:`checkbox`,checked:s,onChange:e=>c(e.target.checked),disabled:f.isPending,className:`mt-0.5 shrink-0`}),(0,K.jsxs)(`span`,{className:`text-xs text-gray-700 dark:text-gray-300`,children:[(0,K.jsx)(`span`,{className:`font-medium block mb-0.5`,children:n(`archivePurge.purgeStatsLabel`)}),(0,K.jsx)(`span`,{className:`text-gray-500 dark:text-gray-400`,children:n(`archivePurge.purgeStatsHint`)})]})]}),(0,K.jsxs)(`div`,{className:`flex gap-2 items-start text-xs text-amber-700 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 rounded px-3 py-2`,children:[(0,K.jsx)(Au,{className:`w-4 h-4 mt-0.5 shrink-0`}),(0,K.jsx)(`span`,{children:n(`archivePurge.warning`)})]})]}),(0,K.jsxs)(`div`,{className:`flex justify-end gap-2 p-4 border-t border-gray-200 dark:border-gray-700`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:e,disabled:f.isPending,children:n(`common.cancel`)}),(0,K.jsx)($,{variant:`danger`,disabled:!g,onClick:()=>f.mutate(),children:f.isPending?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin mr-1`}),n(`archivePurge.purging`)]}):n(`archivePurge.confirmCta`,{count:m})})]})]})})}function bje(e){if(!e||e<=0)return`—`;let t=Math.floor(e/3600),n=Math.floor(e%3600/60);return t>0?`${t}h ${n}m`:`${n}m`}function xje(e){if(!e)return`—`;let t=Vf(e);return t?t.toLocaleString():`—`}function rG({archiveId:e}){let{t}=$e(),{data:n,isLoading:r}=q({queryKey:[`archive-runs`,e],queryFn:()=>Q.getArchiveRuns(e)});if(r)return(0,K.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,K.jsx)(X,{className:`w-5 h-5 text-bambu-gray animate-spin`})});let i=n?.items||[];return i.length===0?(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray italic py-2`,children:t(`archives.runLog.empty`)}):(0,K.jsx)(`div`,{className:`overflow-x-auto`,children:(0,K.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,K.jsx)(`thead`,{children:(0,K.jsxs)(`tr`,{className:`text-bambu-gray border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`th`,{className:`text-left py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.date`)}),(0,K.jsx)(`th`,{className:`text-left py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.status`)}),(0,K.jsx)(`th`,{className:`text-right py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.duration`)}),(0,K.jsx)(`th`,{className:`text-right py-1.5 pr-2 font-medium`,children:t(`archives.runLog.col.filament`)}),(0,K.jsx)(`th`,{className:`text-right py-1.5 font-medium`,children:t(`archives.runLog.col.cost`)})]})}),(0,K.jsx)(`tbody`,{children:i.map(e=>{let n=e.status===`completed`?`text-bambu-green`:e.status===`failed`?`text-red-700 dark:text-red-400`:`text-bambu-gray`;return(0,K.jsxs)(`tr`,{className:`border-b border-bambu-dark-tertiary/40 last:border-0`,children:[(0,K.jsx)(`td`,{className:`py-1.5 pr-2 text-bambu-gray-light`,children:xje(e.started_at||e.created_at)}),(0,K.jsxs)(`td`,{className:`py-1.5 pr-2 font-medium ${n}`,children:[t(`archives.runLog.status.${e.status}`,{defaultValue:e.status}),e.failure_reason&&(0,K.jsx)(`span`,{className:`block text-[10px] text-bambu-gray font-normal`,children:t(`editArchive.failureReasons.${e.failure_reason}`,{defaultValue:e.failure_reason})})]}),(0,K.jsx)(`td`,{className:`py-1.5 pr-2 text-right text-bambu-gray-light`,children:bje(e.duration_seconds)}),(0,K.jsx)(`td`,{className:`py-1.5 pr-2 text-right text-bambu-gray-light`,children:e.filament_used_grams==null?`—`:`${e.filament_used_grams.toFixed(1)} g`}),(0,K.jsx)(`td`,{className:`py-1.5 text-right text-bambu-gray-light`,children:e.cost==null?`—`:e.cost.toFixed(2)})]},e.id)})})]})})}var iG=[`adhesionFailure`,`spaghettiDetached`,`layerShift`,`cloggedNozzle`,`filamentRunout`,`warping`,`stringing`,`underExtrusion`,`powerFailure`,`userCancelled`,`other`],Sje=[`completed`,`failed`,`aborted`,`printing`];function aG({archive:e,onClose:t,existingTags:n=[]}){let{t:r}=$e();(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let i=ao(),[a,o]=(0,y.useState)(e.print_name||``),[s,c]=(0,y.useState)(e.printer_id),[l,u]=(0,y.useState)(e.project_id??null),[d,f]=(0,y.useState)(e.notes||``),[p,m]=(0,y.useState)(e.tags||``),[h,g]=(0,y.useState)(()=>{let t=e.failure_reason||``;return t?iG.includes(t)?t:iG.find(e=>r(`editArchive.failureReasons.${e}`)===t)||``:``}),[_,v]=(0,y.useState)(e.status),[b,x]=(0,y.useState)(e.quantity??1),[S,C]=(0,y.useState)(e.photos||[]),[w,T]=(0,y.useState)(e.external_url||``),[E,D]=(0,y.useState)(!1),[O,k]=(0,y.useState)(!1),A=(0,y.useRef)(null),j=(0,y.useRef)(null),M=(0,y.useRef)(null),{data:N}=q({queryKey:[`printers`],queryFn:Q.getPrinters}),{data:P}=q({queryKey:[`projects`],queryFn:()=>Q.getProjects(),select:e=>[...e].sort((e,t)=>e.name.localeCompare(t.name))}),{data:F}=q({queryKey:[`tags`],queryFn:Q.getTags,enabled:n.length===0}),I=n.length>0?n:F?.map(e=>e.name)||[],L=p.split(`,`).map(e=>e.trim()).filter(Boolean),R=p.includes(`,`)?p.substring(p.lastIndexOf(`,`)+1).trim().toLowerCase():p.trim().toLowerCase(),z=I.filter(e=>!L.includes(e)&&(R===``||e.toLowerCase().includes(R))),B=e=>{let t;t=R&&!I.includes(R)?p.includes(`,`)?p.substring(0,p.lastIndexOf(`,`)).split(`,`).map(e=>e.trim()).filter(Boolean):[]:L,t.includes(e)||m([...t,e].join(`, `)),M.current!==null&&clearTimeout(M.current),A.current?.focus()},V=e=>{m(L.filter(t=>t!==e).join(`, `))},ee=J({mutationFn:t=>Q.updateArchive(e.id,t),onSuccess:()=>{tG(i),t()}}),te=async t=>{let n=t.target.files?.[0];if(n){D(!0);try{C((await Q.uploadArchivePhoto(e.id,n)).photos),i.invalidateQueries({queryKey:[`archives`]})}catch(e){console.error(`Failed to upload photo:`,e)}finally{D(!1),j.current&&(j.current.value=``)}}},H=async t=>{try{C((await Q.deleteArchivePhoto(e.id,t)).photos||[]),i.invalidateQueries({queryKey:[`archives`]})}catch(e){console.error(`Failed to delete photo:`,e)}};return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4`,onClick:t,children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-md max-h-[90vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:r(`editArchive.title`)}),(0,K.jsx)(`button`,{onClick:t,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`form`,{onSubmit:t=>{t.preventDefault();let n={print_name:a||void 0,printer_id:s,project_id:l,notes:d||void 0,tags:p||void 0,quantity:b,external_url:w||null};_!==e.status&&(n.status=_),_===`failed`||_===`aborted`?n.failure_reason=h||void 0:(e.status===`failed`||e.status===`aborted`)&&(n.failure_reason=null),ee.mutate(n)},className:`p-6 space-y-4 overflow-y-auto flex-1`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`archives.runLog.title`)}),(0,K.jsx)(rG,{archiveId:e.id})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.name`)}),(0,K.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:r(`editArchive.namePlaceholder`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.printer`)}),(0,K.jsxs)(`select`,{value:s??``,onChange:e=>c(e.target.value?Number(e.target.value):null),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:[(0,K.jsx)(`option`,{value:``,children:r(`editArchive.noPrinter`)}),N?.map(e=>(0,K.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(dc,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.project`)]}),(0,K.jsxs)(`select`,{value:l??``,onChange:e=>u(e.target.value?Number(e.target.value):null),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:[(0,K.jsx)(`option`,{value:``,children:r(`editArchive.noProject`)}),P?.map(e=>(0,K.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(kc,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.itemsPrinted`)]}),(0,K.jsx)(`input`,{type:`number`,min:1,value:b,onChange:e=>x(Math.max(1,parseInt(e.target.value)||1)),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:`1`}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`editArchive.itemsPrintedHelp`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.notes`)}),(0,K.jsx)(`textarea`,{value:d,onChange:e=>f(e.target.value),rows:3,className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none resize-none`,placeholder:r(`editArchive.notesPlaceholder`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(Kc,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.externalLink`)]}),(0,K.jsx)(`input`,{type:`url`,value:w,onChange:e=>T(e.target.value),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:`https://printables.com/model/...`}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mt-1`,children:r(`editArchive.externalLinkHelp`)})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.tags`)}),L.length>0&&(0,K.jsx)(`div`,{className:`flex flex-wrap gap-1.5 mb-2`,children:L.map(e=>(0,K.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-0.5 bg-bambu-dark-tertiary rounded text-sm text-white`,children:[(0,K.jsx)(yu,{className:`w-3 h-3`}),e,(0,K.jsx)(`button`,{type:`button`,onClick:()=>V(e),className:`ml-0.5 text-bambu-gray hover:text-white`,children:(0,K.jsx)(Ju,{className:`w-3 h-3`})})]},e))}),(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(`input`,{ref:A,type:`text`,value:p,onChange:e=>m(e.target.value),onFocus:()=>{M.current!==null&&clearTimeout(M.current),k(!0)},onBlur:()=>{M.current=window.setTimeout(()=>k(!1),200)},className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,placeholder:L.length>0?r(`editArchive.addMoreTags`):r(`editArchive.tagsPlaceholder`)}),O&&z.length>0&&(0,K.jsxs)(`div`,{className:`absolute top-full left-0 right-0 mt-1 bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-lg z-10 max-h-40 overflow-y-auto`,children:[(0,K.jsxs)(`div`,{className:`p-2 text-xs text-bambu-gray border-b border-bambu-dark-tertiary`,children:[R?r(`editArchive.matchingTags`,{query:R}):r(`editArchive.existingTags`),` `,r(`editArchive.clickToAdd`)]}),(0,K.jsx)(`div`,{className:`p-2 flex flex-wrap gap-1.5`,children:z.map(e=>(0,K.jsx)(`button`,{type:`button`,onClick:()=>B(e),className:`px-2 py-0.5 bg-bambu-dark-tertiary hover:bg-bambu-green/20 rounded text-sm text-bambu-gray hover:text-white transition-colors`,children:e},e))})]})]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.status`)}),(0,K.jsx)(`select`,{value:_,onChange:e=>{v(e.target.value),e.target.value===`completed`&&g(``)},className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:Sje.map(e=>(0,K.jsx)(`option`,{value:e,children:r(`editArchive.statuses.${e}`)},e))})]}),(_===`failed`||_===`aborted`)&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`label`,{htmlFor:`failure-reason-select`,className:`block text-sm text-bambu-gray mb-1`,children:r(`editArchive.failureReason`)}),(0,K.jsxs)(`select`,{id:`failure-reason-select`,value:h,onChange:e=>g(e.target.value),className:`w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none`,children:[(0,K.jsx)(`option`,{value:``,children:r(`editArchive.selectReason`)}),iG.map(e=>(0,K.jsx)(`option`,{value:e,children:r(`editArchive.failureReasons.${e}`)},e))]})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`label`,{className:`block text-sm text-bambu-gray mb-1`,children:[(0,K.jsx)(ts,{className:`w-4 h-4 inline mr-1`}),r(`editArchive.photos`)]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap gap-2 mb-2`,children:[S.map(t=>(0,K.jsxs)(`div`,{className:`relative group`,children:[(0,K.jsx)(`img`,{src:Q.getArchivePhotoUrl(e.id,t),alt:r(`editArchive.printResult`),className:`w-20 h-20 object-cover rounded-lg border border-bambu-dark-tertiary`}),(0,K.jsx)(`button`,{type:`button`,onClick:()=>H(t),className:`absolute -top-1 -right-1 p-1 bg-red-500 rounded-full opacity-0 group-hover:opacity-100 transition-opacity`,children:(0,K.jsx)(Du,{className:`w-3 h-3 text-white`})})]},t)),(0,K.jsxs)(`label`,{className:`w-20 h-20 flex items-center justify-center border-2 border-dashed border-bambu-dark-tertiary rounded-lg cursor-pointer hover:border-bambu-green transition-colors`,children:[(0,K.jsx)(`input`,{ref:j,type:`file`,accept:`image/jpeg,image/png,image/webp`,onChange:te,className:`hidden`,disabled:E}),E?(0,K.jsx)(X,{className:`w-6 h-6 text-bambu-gray animate-spin`}):(0,K.jsx)(kl,{className:`w-6 h-6 text-bambu-gray`})]})]}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray`,children:r(`editArchive.photosHelp`)})]}),(0,K.jsxs)(`div`,{className:`flex gap-3 pt-2`,children:[(0,K.jsx)($,{type:`button`,variant:`secondary`,onClick:t,className:`flex-1`,children:r(`common.cancel`)}),(0,K.jsxs)($,{type:`submit`,disabled:ee.isPending,className:`flex-1`,children:[(0,K.jsx)(Bl,{className:`w-4 h-4`}),ee.isPending?r(`common.saving`):r(`common.save`)]})]})]})]})})}function oG({archiveId:e,archiveName:t,onClose:n}){let{t:r}=$e();return(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4`,onClick:n,children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-2xl max-h-[85vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,K.jsx)(Nc,{className:`w-5 h-5 text-bambu-green flex-shrink-0`}),(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white truncate`,title:t||``,children:r(`archives.runLog.modalTitle`,{name:t||r(`archives.runLog.modalTitleFallback`)})})]}),(0,K.jsx)(`button`,{onClick:n,className:`text-bambu-gray hover:text-white transition-colors`,title:r(`common.close`),children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsx)(`div`,{className:`p-6 overflow-y-auto flex-1`,children:(0,K.jsx)(rG,{archiveId:e})})]})})}function sG({isOpen:e,onClose:t,columns:n,defaultColumns:r,onSave:i}){let{t:a}=$e(),[o,s]=(0,y.useState)(n),[c,l]=(0,y.useState)(null),u=(0,y.useRef)(null);if((0,y.useEffect)(()=>{e&&s(n.map(e=>({...e})))},[e,n]),(0,y.useEffect)(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,n),()=>window.removeEventListener(`keydown`,n)},[e,t]),!e)return null;let d=e=>{s(t=>t.map((t,n)=>n===e?{...t,visible:!t.visible}:t))},f=(e,t)=>{t<0||t>=o.length||s(n=>{let r=[...n],[i]=r.splice(e,1);return r.splice(t,0,i),r})},p=(e,t)=>{u.current=t,l(t),e.dataTransfer.effectAllowed=`move`},m=(e,t)=>{e.preventDefault(),e.dataTransfer.dropEffect=`move`;let n=u.current;n!==null&&n!==t&&(f(n,t),u.current=t,l(t))},h=e=>{e.preventDefault()},g=()=>{u.current=null,l(null)},_=()=>{s(r.map(e=>({...e})))},v=()=>{i(o),t()},b=o.filter(e=>e.visible).length;return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,onClick:t,children:(0,K.jsx)(Dd,{className:`w-full max-w-md max-h-[80vh] flex flex-col`,onClick:e=>e.stopPropagation(),children:(0,K.jsxs)(kd,{className:`p-6 flex flex-col min-h-0`,children:[(0,K.jsx)(`h3`,{className:`text-lg font-semibold text-white mb-2`,children:a(`inventory.configureColumns`)}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray mb-4`,children:[a(`inventory.configureColumnsDesc`),(0,K.jsxs)(`span`,{className:`ml-2 text-bambu-gray/60`,children:[`(`,b,` `,a(`inventory.of`),` `,o.length,` `,a(`inventory.visible`),`)`]})]}),(0,K.jsx)(`div`,{className:`space-y-1 overflow-y-auto flex-1 min-h-0 pr-1`,children:o.map((e,t)=>(0,K.jsxs)(`div`,{className:`flex items-center gap-2 p-2 rounded-lg border transition-colors ${c===t?`border-bambu-green bg-bambu-green/10`:`border-bambu-dark-tertiary bg-bambu-dark-tertiary/50`} ${e.visible?``:`opacity-50`}`,draggable:!0,onDragStart:e=>p(e,t),onDragOver:e=>m(e,t),onDrop:h,onDragEnd:g,children:[(0,K.jsx)(`div`,{className:`cursor-grab text-bambu-gray/50 hover:text-bambu-gray`,children:(0,K.jsx)(Tc,{className:`w-4 h-4`})}),(0,K.jsx)(`span`,{className:`flex-1 font-medium text-sm text-white`,children:e.label}),(0,K.jsxs)(`div`,{className:`flex items-center gap-0.5`,children:[(0,K.jsx)(`button`,{onClick:()=>f(t,t-1),disabled:t===0,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:a(`inventory.moveUp`),children:(0,K.jsx)(ds,{className:`w-4 h-4`})}),(0,K.jsx)(`button`,{onClick:()=>f(t,t+1),disabled:t===o.length-1,className:`p-1 rounded text-bambu-gray hover:bg-bambu-dark-secondary disabled:opacity-30 disabled:cursor-not-allowed`,title:a(`inventory.moveDown`),children:(0,K.jsx)(cs,{className:`w-4 h-4`})})]}),(0,K.jsx)(`button`,{onClick:()=>d(t),className:`p-1.5 rounded transition-colors ${e.visible?`text-bambu-green hover:bg-bambu-green/10`:`text-bambu-gray/50 hover:bg-bambu-dark-secondary`}`,title:e.visible?a(`inventory.hideColumn`):a(`inventory.showColumn`),children:e.visible?(0,K.jsx)(ec,{className:`w-4 h-4`}):(0,K.jsx)($s,{className:`w-4 h-4`})})]},e.id))}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3 mt-4 pt-4 border-t border-bambu-dark-tertiary`,children:[(0,K.jsxs)($,{variant:`secondary`,onClick:_,className:`mr-auto`,children:[(0,K.jsx)(Ll,{className:`w-4 h-4`}),a(`inventory.reset`)]}),(0,K.jsx)($,{variant:`secondary`,onClick:t,children:a(`inventory.cancel`)}),(0,K.jsx)($,{onClick:v,children:a(`inventory.applyChanges`)})]})]})})})}function Cje({items:e,searchPlaceholder:t,onClose:n,className:r,onMouseEnter:i,onMouseLeave:a}){let[o,s]=(0,y.useState)(``),c=(0,y.useRef)(null);(0,y.useEffect)(()=>{if(t){let e=window.setTimeout(()=>c.current?.focus(),0);return()=>window.clearTimeout(e)}},[t]);let l=o.trim().toLowerCase(),u=t&&l?e.filter(e=>e.label.toLowerCase().includes(l)):e;return(0,K.jsxs)(`div`,{className:r,onMouseEnter:i,onMouseLeave:a,children:[t&&(0,K.jsx)(`div`,{className:`sticky top-0 z-[1] px-2 py-1.5 bg-bambu-dark-secondary border-b border-bambu-dark-tertiary`,children:(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(Gl,{className:`absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-bambu-gray pointer-events-none`}),(0,K.jsx)(`input`,{ref:c,type:`text`,value:o,onChange:e=>s(e.target.value),onKeyDown:e=>{if(e.key===`Enter`){let e=u.find(e=>!e.disabled);e&&(e.onClick(),n())}},placeholder:t,className:`w-full pl-7 pr-2 py-1 text-sm bg-bambu-dark border border-bambu-dark-tertiary rounded text-white placeholder-bambu-gray focus:border-bambu-green focus:outline-none`})]})}),u.map((e,t)=>(0,K.jsxs)(`button`,{onClick:()=>{e.disabled||(e.onClick(),n())},disabled:e.disabled,className:`w-full flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${e.disabled?`text-bambu-gray cursor-not-allowed`:e.danger?`text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-400/10`:`text-white hover:bg-bambu-dark-tertiary`}`,children:[e.icon&&(0,K.jsx)(`span`,{className:`w-4 h-4 flex-shrink-0 flex items-center justify-center`,children:e.icon}),(0,K.jsx)(`span`,{className:`flex-1 truncate`,children:e.label})]},t)),t&&u.length===0&&(0,K.jsx)(`div`,{className:`px-3 py-2 text-sm text-bambu-gray text-center italic`,children:`—`})]})}function cG({x:e,y:t,items:n,onClose:r}){let i=(0,y.useRef)(null),[a,o]=(0,y.useState)(null),s=(0,y.useRef)(null),[c,l]=(0,y.useState)({x:e,y:t,visible:!1}),[u,d]=(0,y.useState)(!1),[f,p]=(0,y.useState)({});(0,y.useEffect)(()=>{let e=e=>{i.current&&!i.current.contains(e.target)&&r()},t=e=>{e.key===`Escape`&&r()},n=e=>{i.current&&i.current.contains(e.target)||r()};return document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t),document.addEventListener(`scroll`,n,!0),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t),document.removeEventListener(`scroll`,n,!0),s.current&&clearTimeout(s.current)}},[r]),(0,y.useLayoutEffect)(()=>{if(i.current){i.current.style.visibility=`hidden`,i.current.style.display=`block`;let n=i.current.getBoundingClientRect(),r=window.innerWidth,a=window.innerHeight,o=e,s=t;e+n.width>r-8&&(o=Math.max(8,r-n.width-8)),o<8&&(o=8),t+n.height>a-8&&(s=Math.max(8,a-n.height-8)),s<8&&(s=8),d(r-o-n.width<180&&o>180),l({x:o,y:s,visible:!0})}},[e,t]);let m=(e,t)=>{s.current&&=(clearTimeout(s.current),null);let n=t.getBoundingClientRect(),r=window.innerHeight-n.top-8<300&&n.top>300;p(t=>({...t,[e]:r?`bottom`:`top`})),o(e)},h=()=>{s.current=window.setTimeout(()=>{o(null)},150)};return(0,K.jsx)(`div`,{ref:i,className:`fixed z-50 min-w-[180px] max-w-[280px] bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-xl py-1`,style:{left:c.x,top:c.y,visibility:c.visible?`visible`:`hidden`},children:n.map((e,t)=>{if(e.divider)return(0,K.jsx)(`div`,{className:`my-1 border-t border-bambu-dark-tertiary`},t);let n=e.submenu&&e.submenu.length>0;return(0,K.jsxs)(`div`,{className:`relative`,onMouseEnter:e=>n&&m(t,e.currentTarget),onMouseLeave:()=>n&&h(),children:[(0,K.jsxs)(`button`,{onMouseEnter:e=>n&&m(t,e.currentTarget.parentElement),onClick:()=>{n?o(a===t?null:t):e.disabled||(e.onClick(),r())},disabled:e.disabled,title:e.title,className:`w-full flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${e.disabled?`text-bambu-gray cursor-not-allowed`:e.danger?`text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-400/10`:`text-white hover:bg-bambu-dark-tertiary`} ${n&&a===t?`bg-bambu-dark-tertiary`:``}`,children:[e.icon&&(0,K.jsx)(`span`,{className:`w-4 h-4 flex-shrink-0 flex items-center justify-center`,children:e.icon}),(0,K.jsx)(`span`,{className:`flex-1`,children:e.label}),n&&(0,K.jsx)(ls,{className:`w-4 h-4 text-bambu-gray`})]}),n&&a===t&&(0,K.jsx)(Cje,{items:e.submenu,searchPlaceholder:e.submenuSearchPlaceholder,onClose:r,className:`absolute min-w-[200px] bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg shadow-xl py-1 overflow-hidden max-h-[300px] overflow-y-auto z-[60] ${u?`right-full mr-1`:`left-full ml-1`} ${f[t]===`bottom`?`bottom-0`:`top-0`}`,onMouseEnter:()=>{s.current&&=(clearTimeout(s.current),null)},onMouseLeave:()=>h()})]},t)})})}function wje({selectedIds:e,existingTags:t,onClose:n}){let r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(``),[s,c]=(0,y.useState)(new Set),[l,u]=(0,y.useState)(`add`);(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]);let d=J({mutationFn:async()=>{let t=Array.from(s),n=0;for(let r of e)try{let e=await Q.getArchive(r),i=e.tags?e.tags.split(`,`).map(e=>e.trim()).filter(Boolean):[],a;a=l===`add`?[...new Set([...i,...t])]:i.filter(e=>!s.has(e)),await Q.updateArchive(r,{tags:a.join(`, `)}),n++}catch(e){throw console.error(`Failed to update archive ${r}:`,e),Error(`Failed on archive ${r}: ${e instanceof Error?e.message:`Unknown error`}`)}return{count:n,mode:l,tags:t}},onSuccess:({count:e,mode:t,tags:a})=>{r.invalidateQueries({queryKey:[`archives`]}),i(`${t===`add`?`Added`:`Removed`} ${a.length} tag${a.length===1?``:`s`} ${t===`add`?`to`:`from`} ${e} archive${e===1?``:`s`}`),n()},onError:e=>{i(e.message||`Failed to update tags`,`error`)}}),f=e=>{c(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},p=()=>{a.trim()&&!s.has(a.trim())&&(c(e=>new Set([...e,a.trim()])),o(``))};return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,children:(0,K.jsx)(Dd,{className:`w-full max-w-md`,children:(0,K.jsxs)(kd,{className:`p-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(yu,{className:`w-5 h-5 text-bambu-green`}),(0,K.jsx)(`h2`,{className:`text-xl font-semibold text-white`,children:l===`add`?`Add Tags`:`Remove Tags`})]}),(0,K.jsx)(`button`,{onClick:n,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-4`,children:[(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray`,children:[l===`add`?`Add`:`Remove`,` tags for `,e.length,` selected archive`,e.length===1?``:`s`]}),(0,K.jsxs)(`div`,{className:`flex gap-2`,children:[(0,K.jsx)($,{size:`sm`,variant:l===`add`?`primary`:`secondary`,onClick:()=>u(`add`),children:`Add Tags`}),(0,K.jsx)($,{size:`sm`,variant:l===`remove`?`primary`:`secondary`,onClick:()=>u(`remove`),children:`Remove Tags`})]}),l===`add`&&(0,K.jsxs)(`div`,{className:`flex gap-2`,children:[(0,K.jsx)(`input`,{type:`text`,placeholder:`Enter new tag...`,className:`flex-1 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm focus:border-bambu-green focus:outline-none`,value:a,onChange:e=>o(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),p())}}),(0,K.jsx)($,{size:`sm`,variant:`secondary`,onClick:p,disabled:!a.trim(),children:(0,K.jsx)(kl,{className:`w-4 h-4`})})]}),t.length>0&&(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mb-2`,children:`Existing tags:`}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:t.map(e=>(0,K.jsx)(`button`,{onClick:()=>f(e),className:`px-2 py-1 rounded text-sm transition-colors ${s.has(e)?`bg-bambu-green text-white`:`bg-bambu-dark-tertiary text-bambu-gray-light hover:bg-bambu-dark`}`,children:e},e))})]}),s.size>0&&(0,K.jsxs)(`div`,{children:[(0,K.jsxs)(`p`,{className:`text-xs text-bambu-gray mb-2`,children:[`Tags to `,l===`add`?`add`:`remove`,`:`]}),(0,K.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Array.from(s).map(e=>(0,K.jsxs)(`span`,{className:`px-2 py-1 rounded text-sm flex items-center gap-1 ${l===`add`?`bg-green-100 dark:bg-green-500/20 text-green-700 dark:text-green-400`:`bg-red-100 dark:bg-red-500/20 text-red-700 dark:text-red-400`}`,children:[e,(0,K.jsx)(`button`,{onClick:()=>f(e),className:`hover:opacity-70`,children:(0,K.jsx)(Ju,{className:`w-3 h-3`})})]},e))})]})]}),(0,K.jsxs)(`div`,{className:`flex gap-3 p-4 border-t border-bambu-dark-tertiary`,children:[(0,K.jsx)($,{variant:`secondary`,onClick:n,className:`flex-1`,children:`Cancel`}),(0,K.jsx)($,{onClick:()=>d.mutate(),disabled:s.size===0||d.isPending,className:`flex-1`,children:d.isPending?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(X,{className:`w-4 h-4 animate-spin`}),`Processing...`]}):(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(yu,{className:`w-4 h-4`}),l===`add`?`Add Tags`:`Remove Tags`]})})]})]})})})}function Tje({selectedIds:e,onClose:t}){let{t:n}=$e(),r=ao(),{showToast:i}=Pd(),[a,o]=(0,y.useState)(``),{data:s,isLoading:c}=q({queryKey:[`projects`],queryFn:()=>Q.getProjects()}),l=(0,y.useMemo)(()=>s?[...s].sort((e,t)=>e.name.localeCompare(t.name)):void 0,[s]),u=a.trim().toLowerCase(),d=u?l?.filter(e=>e.name.toLowerCase().includes(u)):l,f=(l?.length??0)>5;(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let p=()=>tG(r),m=J({mutationFn:async t=>(await Q.addArchivesToProject(t,e),t),onSuccess:n=>{let r=s?.find(e=>e.id===n);p(),i(`Added ${e.length} archive${e.length===1?``:`s`} to "${r?.name}"`),t()},onError:()=>{i(`Failed to assign project`,`error`)}}),h=J({mutationFn:async()=>{for(let t of e)await Q.updateArchive(t,{project_id:null});return e.length},onSuccess:e=>{p(),i(`Removed ${e} archive${e===1?``:`s`} from project`),t()},onError:()=>{i(`Failed to remove from project`,`error`)}}),g=m.isPending||h.isPending;return(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4`,children:(0,K.jsx)(Dd,{className:`w-full max-w-md max-h-[80vh] flex flex-col`,children:(0,K.jsxs)(kd,{className:`p-0 flex flex-col min-h-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between p-4 border-b border-bambu-dark-tertiary shrink-0`,children:[(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsx)(dc,{className:`w-5 h-5 text-bambu-green`}),(0,K.jsx)(`h2`,{className:`text-xl font-semibold text-white`,children:`Assign to Project`})]}),(0,K.jsx)(`button`,{onClick:t,className:`text-bambu-gray hover:text-white transition-colors`,disabled:g,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-4 space-y-3 overflow-y-auto min-h-0`,children:[(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray`,children:[`Assign `,e.length,` selected archive`,e.length===1?``:`s`,` to a project`]}),c?(0,K.jsx)(`div`,{className:`flex items-center justify-center py-8`,children:(0,K.jsx)(X,{className:`w-6 h-6 animate-spin text-bambu-gray`})}):(0,K.jsxs)(`div`,{className:`space-y-2`,children:[(0,K.jsxs)(`button`,{onClick:()=>h.mutate(),disabled:g,className:`w-full flex items-center gap-3 p-3 rounded-lg bg-bambu-dark hover:bg-bambu-dark-tertiary border border-bambu-dark-tertiary transition-colors text-left disabled:opacity-50`,children:[(0,K.jsx)(`div`,{className:`w-8 h-8 rounded-full bg-red-500/20 flex items-center justify-center shrink-0`,children:(0,K.jsx)(Ss,{className:`w-4 h-4 text-red-600 dark:text-red-400`})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`text-white font-medium`,children:`Remove from project`}),(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray truncate`,children:`Clear project assignment`})]}),h.isPending&&(0,K.jsx)(X,{className:`w-4 h-4 animate-spin text-bambu-gray shrink-0`})]}),l&&l.length>0&&(0,K.jsxs)(`div`,{className:`flex items-center gap-2 py-2`,children:[(0,K.jsx)(`div`,{className:`flex-1 h-px bg-bambu-dark-tertiary`}),(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:`or assign to`}),(0,K.jsx)(`div`,{className:`flex-1 h-px bg-bambu-dark-tertiary`})]}),f&&(0,K.jsxs)(`div`,{className:`relative`,children:[(0,K.jsx)(Gl,{className:`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none`}),(0,K.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value),placeholder:n(`archives.menu.searchProjects`),className:`w-full pl-9 pr-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white placeholder-bambu-gray text-sm focus:border-bambu-green focus:outline-none`})]}),d?.map(e=>(0,K.jsxs)(`button`,{onClick:()=>m.mutate(e.id),disabled:g,className:`w-full flex items-center gap-3 p-3 rounded-lg bg-bambu-dark hover:bg-bambu-dark-tertiary border border-bambu-dark-tertiary transition-colors text-left disabled:opacity-50`,children:[(0,K.jsx)(`div`,{className:`w-8 h-8 rounded-full flex items-center justify-center shrink-0`,style:{backgroundColor:e.color?`${e.color}20`:`rgb(var(--bambu-green) / 0.2)`},children:(0,K.jsx)(dc,{className:`w-4 h-4`,style:{color:e.color||`rgb(var(--bambu-green))`}})}),(0,K.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,K.jsx)(`p`,{className:`text-white font-medium truncate`,children:e.name}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray truncate`,children:[e.archive_count,` archive`,e.archive_count===1?``:`s`,e.status&&` • ${e.status}`]})]}),m.isPending&&m.variables===e.id&&(0,K.jsx)(X,{className:`w-4 h-4 animate-spin text-bambu-gray shrink-0`})]},e.id)),(!l||l.length===0)&&(0,K.jsx)(`p`,{className:`text-center text-bambu-gray py-4`,children:`No projects yet. Create one from the Projects page.`}),l&&l.length>0&&d?.length===0&&(0,K.jsx)(`p`,{className:`text-center text-bambu-gray text-sm py-4`,children:`—`})]})]}),(0,K.jsx)(`div`,{className:`flex gap-3 p-4 border-t border-bambu-dark-tertiary shrink-0`,children:(0,K.jsx)($,{variant:`secondary`,onClick:t,className:`flex-1`,disabled:g,children:`Cancel`})})]})})})}function Eje(e,t){return new Date(e,t+1,0).getDate()}function Dje(e,t){return new Date(e,t,1).getDay()}var Oje=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],kje=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function Aje({archives:e,onArchiveClick:t,highlightedArchiveId:n}){let r=new Date,[i,a]=(0,y.useState)(r.getMonth()),[o,s]=(0,y.useState)(r.getFullYear()),[c,l]=(0,y.useState)(null),[u,d]=(0,y.useState)(null),f=(0,y.useMemo)(()=>{let t=new Map;return e.forEach(e=>{let n=Vf(e.completed_at||e.created_at)||new Date,r=`${n.getFullYear()}-${String(n.getMonth()+1).padStart(2,`0`)}-${String(n.getDate()).padStart(2,`0`)}`,i=t.get(r)||[];i.push(e),t.set(r,i)}),t},[e]),p=Eje(o,i),m=Dje(o,i),h=()=>{i===0?(a(11),s(o-1)):a(i-1)},g=()=>{i===11?(a(0),s(o+1)):a(i+1)},_=()=>{a(r.getMonth()),s(r.getFullYear())},v=[];for(let e=0;e{e!==c&&d(null),l(e)};return(0,K.jsxs)(`div`,{className:`flex flex-col lg:flex-row gap-6`,children:[(0,K.jsxs)(`div`,{className:`flex-1`,children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between mb-4`,children:[(0,K.jsx)(`button`,{onClick:h,className:`p-2 hover:bg-bambu-dark-tertiary rounded-lg transition-colors`,children:(0,K.jsx)(us,{className:`w-5 h-5 text-bambu-gray`})}),(0,K.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,K.jsxs)(`h2`,{className:`text-lg font-semibold text-white`,children:[Oje[i],` `,o]}),(0,K.jsx)(`button`,{onClick:_,className:`px-2 py-1 text-xs bg-bambu-dark-tertiary hover:bg-bambu-green/20 text-bambu-gray hover:text-white rounded transition-colors`,children:`Today`})]}),(0,K.jsx)(`button`,{onClick:g,className:`p-2 hover:bg-bambu-dark-tertiary rounded-lg transition-colors`,children:(0,K.jsx)(ls,{className:`w-5 h-5 text-bambu-gray`})})]}),(0,K.jsx)(`div`,{className:`grid grid-cols-7 gap-1 mb-1`,children:kje.map(e=>(0,K.jsx)(`div`,{className:`text-center text-xs text-bambu-gray py-2`,children:e},e))}),(0,K.jsx)(`div`,{className:`grid grid-cols-7 gap-1`,children:v.map((e,t)=>{if(e===null)return(0,K.jsx)(`div`,{className:`aspect-square`},`empty-${t}`);let n=`${o}-${String(i+1).padStart(2,`0`)}-${String(e).padStart(2,`0`)}`,a=f.get(n)||[],s=a.length>0,l=e===r.getDate()&&i===r.getMonth()&&o===r.getFullYear(),u=n===c,d=a.filter(e=>e.status===`completed`).length,p=a.filter(e=>e.status===`failed`).length;return(0,K.jsxs)(`button`,{onClick:()=>x(u?null:n),className:`aspect-square rounded-lg p-1 flex flex-col items-center justify-center transition-colors relative ${u?`bg-bambu-green text-white`:l?`bg-bambu-green/20 text-white ring-2 ring-bambu-green`:s?`bg-bambu-dark-tertiary hover:bg-bambu-dark-tertiary/70 text-white`:`hover:bg-bambu-dark-tertiary/50 text-bambu-gray`}`,children:[(0,K.jsx)(`span`,{className:`text-sm font-medium ${l&&!u?`text-bambu-green`:``}`,children:e}),s&&(0,K.jsxs)(`div`,{className:`absolute bottom-1 left-1/2 -translate-x-1/2 flex items-center gap-1`,children:[(0,K.jsx)(`div`,{className:`w-2 h-2 rounded-full ${p>0&&d===0?`bg-red-400`:p>0?`bg-yellow-400`:`bg-green-400`}`}),(0,K.jsx)(`span`,{className:`text-xs font-medium`,children:a.length})]})]},e)})}),(0,K.jsx)(`div`,{className:`mt-4 pt-4 border-t border-bambu-dark-tertiary`,children:(0,K.jsxs)(`div`,{className:`grid grid-cols-3 gap-4 text-center`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`text-2xl font-bold text-white`,children:e.filter(e=>{let t=Vf(e.completed_at||e.created_at)||new Date;return t.getMonth()===i&&t.getFullYear()===o}).length}),(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray`,children:`Prints this month`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`text-2xl font-bold text-green-700 dark:text-green-400`,children:e.filter(e=>{let t=Vf(e.completed_at||e.created_at)||new Date;return t.getMonth()===i&&t.getFullYear()===o&&e.status===`completed`}).length}),(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray`,children:`Successful`})]}),(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`div`,{className:`text-2xl font-bold text-red-700 dark:text-red-400`,children:e.filter(e=>{let t=Vf(e.completed_at||e.created_at)||new Date;return t.getMonth()===i&&t.getFullYear()===o&&e.status===`failed`}).length}),(0,K.jsx)(`div`,{className:`text-xs text-bambu-gray`,children:`Failed`})]})]})})]}),(0,K.jsx)(`div`,{className:`lg:w-80 bg-bambu-dark rounded-xl p-4`,children:c?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsx)(`h3`,{className:`text-sm font-medium text-bambu-gray mb-3`,children:new Date(c+`T12:00:00`).toLocaleDateString(`en-US`,{weekday:`long`,month:`long`,day:`numeric`,year:`numeric`})}),b.length>0?(0,K.jsx)(`div`,{className:`calendar-scroll space-y-2 max-h-96 overflow-y-auto`,children:b.map(e=>{let r=e.id===u||e.id===n;return(0,K.jsxs)(`button`,{onClick:()=>{d(e.id),t?.(e)},className:`w-full flex items-center gap-3 p-2 rounded-lg transition-colors text-left ${r?``:`hover:bg-bambu-dark-tertiary`}`,style:r?{outline:`4px solid #facc15`,outlineOffset:`2px`}:void 0,children:[e.thumbnail_path?(0,K.jsx)(`img`,{src:Q.getArchiveThumbnail(e.id),alt:``,className:`w-12 h-12 rounded object-cover`}):(0,K.jsx)(`div`,{className:`w-12 h-12 rounded bg-bambu-dark-tertiary flex items-center justify-center`,children:(0,K.jsx)(`span`,{className:`text-xs text-bambu-gray`,children:`3MF`})}),(0,K.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,K.jsx)(`p`,{className:`text-sm text-white truncate`,children:e.print_name||e.filename}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2 text-xs`,children:[(0,K.jsx)(`span`,{className:e.status===`failed`?`text-red-700 dark:text-red-400`:`text-green-700 dark:text-green-400`,children:e.status===`failed`?`Failed`:`Completed`}),e.filament_color&&(0,K.jsx)(`div`,{className:`flex gap-0.5`,children:e.filament_color.split(`,`).map((e,t)=>(0,K.jsx)(`div`,{className:`w-3 h-3 rounded-full border border-black/20`,style:{backgroundColor:e}},t))})]})]})]},e.id)})}):(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:`No prints on this day`})]}):(0,K.jsx)(`div`,{className:`text-center py-8`,children:(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:`Select a day to see prints`})})})]})}function lG({archiveId:e,archiveName:t,onClose:n}){let r=Q.getArchiveQRCodeUrl(e,300);return(0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,K.jsx)(`div`,{className:`fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4`,onClick:n,children:(0,K.jsxs)(`div`,{className:`bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-sm`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary`,children:[(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:`QR Code`}),(0,K.jsx)(`button`,{onClick:n,className:`text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-5 h-5`})})]}),(0,K.jsxs)(`div`,{className:`p-6 flex flex-col items-center`,children:[(0,K.jsx)(`p`,{className:`text-sm text-bambu-gray mb-4 text-center truncate max-w-full`,children:t}),(0,K.jsx)(`div`,{className:`bg-white p-4 rounded-lg mb-4`,children:(0,K.jsx)(`img`,{src:r,alt:`QR Code`,className:`w-64 h-64`})}),(0,K.jsx)(`p`,{className:`text-xs text-bambu-gray mb-4 text-center`,children:`Scan to open this archive`}),(0,K.jsxs)($,{onClick:()=>{let e=document.createElement(`a`);e.href=r,e.download=`${t}_qrcode.png`,e.click()},className:`w-full`,children:[(0,K.jsx)(Gs,{className:`w-4 h-4`}),`Download QR Code`]})]})]})})}function uG({archiveId:e,archiveName:t,photos:n,onClose:r,onDelete:i}){let[a,o]=(0,y.useState)(0),[s,c]=(0,y.useState)(!1);if((0,y.useEffect)(()=>{let e=e=>{e.key===`Escape`&&r(),e.key===`ArrowLeft`&&o(e=>Math.max(0,e-1)),e.key===`ArrowRight`&&o(e=>Math.min(n.length-1,e+1))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[r,n.length]),(0,y.useEffect)(()=>{a>=n.length&&o(Math.max(0,n.length-1))},[n.length,a]),n.length===0)return r(),null;let l=n[a],u=Q.getArchivePhotoUrl(e,l);return(0,K.jsxs)(`div`,{className:`fixed inset-0 bg-black/90 flex items-center justify-center z-50`,onClick:r,children:[(0,K.jsxs)(`div`,{className:`relative w-full h-full flex flex-col`,onClick:e=>e.stopPropagation(),children:[(0,K.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 bg-black/50`,children:[(0,K.jsxs)(`div`,{children:[(0,K.jsx)(`h2`,{className:`text-lg font-semibold text-white`,children:t}),(0,K.jsxs)(`p`,{className:`text-sm text-bambu-gray`,children:[`Photo `,a+1,` of `,n.length]})]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,K.jsxs)($,{variant:`secondary`,size:`sm`,onClick:()=>{let e=document.createElement(`a`);e.href=u,e.download=`${t}_photo_${a+1}.jpg`,e.click()},children:[(0,K.jsx)(Gs,{className:`w-4 h-4`}),`Download`]}),i&&(0,K.jsx)($,{variant:`secondary`,size:`sm`,onClick:()=>{i&&c(!0)},className:`text-red-400 hover:text-red-300`,children:(0,K.jsx)(Du,{className:`w-4 h-4`})}),(0,K.jsx)(`button`,{onClick:r,className:`p-2 text-bambu-gray hover:text-white transition-colors`,children:(0,K.jsx)(Ju,{className:`w-6 h-6`})})]})]}),(0,K.jsxs)(`div`,{className:`flex-1 min-h-0 flex items-center justify-center p-4 relative overflow-hidden`,children:[a>0&&(0,K.jsx)(`button`,{onClick:()=>o(e=>e-1),className:`absolute left-4 z-10 p-3 bg-black/50 hover:bg-black/70 rounded-full transition-colors`,children:(0,K.jsx)(us,{className:`w-8 h-8 text-white`})}),(0,K.jsx)(`img`,{src:u,alt:`Photo ${a+1}`,className:`max-w-full max-h-full object-contain rounded-lg`,style:{maxHeight:`calc(100vh - 200px)`}}),ao(e=>e+1),className:`absolute right-4 z-10 p-3 bg-black/50 hover:bg-black/70 rounded-full transition-colors`,children:(0,K.jsx)(ls,{className:`w-8 h-8 text-white`})})]}),n.length>1&&(0,K.jsx)(`div`,{className:`flex justify-center gap-2 p-4 bg-black/50`,children:n.map((t,n)=>(0,K.jsx)(`button`,{onClick:()=>o(n),className:`w-16 h-16 rounded-lg overflow-hidden border-2 transition-colors ${n===a?`border-bambu-green`:`border-transparent hover:border-bambu-gray`}`,children:(0,K.jsx)(`img`,{src:Q.getArchivePhotoUrl(e,t),alt:`Thumbnail ${n+1}`,className:`w-full h-full object-cover`})},t))})]}),s&&(0,K.jsx)(Kd,{title:`Delete Photo`,message:`Delete this photo? This cannot be undone.`,confirmText:`Delete`,variant:`danger`,onConfirm:()=>{i?.(l),c(!1)},onCancel:()=>c(!1)})]})}function dG(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n`u`?null:FG(BigInt.prototype.toString),AG=typeof Symbol>`u`?null:FG(Symbol.prototype.toString),jG=FG(Object.prototype.hasOwnProperty),MG=FG(Object.prototype.toString),NG=FG(RegExp.prototype.test),PG=Wje(TypeError);function FG(e){return function(t){t instanceof RegExp&&(t.lastIndex=0);var n=[...arguments].slice(1);return vG(e,t,n)}}function Wje(e){return function(){return yG(e,[...arguments])}}function IG(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:wG;if(pG&&pG(e,null),!CG(t))return e;let r=t.length;for(;r--;){let i=t[r];if(typeof i==`string`){let e=n(i);e!==i&&(Ije(t)||(t[r]=e),i=e)}e[i]=!0}return e}function Gje(e){for(let t=0;t/g),Qje=hG(/\${[\w\W]*/g),$je=hG(/^data-[\-\w.\u00B7-\uFFFF]+$/),eMe=hG(/^aria-[\-\w]+$/),JG=hG(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),tMe=hG(/^(?:\w+script|data):/i),nMe=hG(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),rMe=hG(/^html$/i),iMe=hG(/^[a-z][.\w]*(-[.\w]+)+$/i),YG=hG(/<[/\w!]/g),XG=hG(/<[/\w]/g),aMe=hG(/<\/no(script|embed|frames)/i),oMe=hG(/\/>/i),ZG={element:1,attribute:2,text:3,cdataSection:4,entityReference:5,entityNode:6,processingInstruction:7,comment:8,document:9,documentType:10,documentFragment:11,notation:12},sMe=function(){return typeof window>`u`?null:window},cMe=function(e,t){if(typeof e!=`object`||typeof e.createPolicy!=`function`)return null;let n=null,r=`data-tt-policy-suffix`;t&&t.hasAttribute(r)&&(n=t.getAttribute(r));let i=`dompurify`+(n?`#`+n:``);try{return e.createPolicy(i,{createHTML(e){return e},createScriptURL(e){return e}})}catch{return console.warn(`TrustedTypes policy `+i+` could not be created.`),null}},QG=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},$G=function(e,t,n,r){return jG(e,t)&&CG(e[t])?IG(r.base?LG(r.base):{},e[t],r.transform):n};function eK(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:sMe(),t=e=>eK(e);if(t.version=`3.4.12`,t.removed=[],!e||!e.document||e.document.nodeType!==ZG.document||!e.Element)return t.isSupported=!1,t;let n=e.document,r=n,i=r.currentScript;e.DocumentFragment;let a=e.HTMLTemplateElement,o=e.Node,s=e.Element,c=e.NodeFilter;e.NamedNodeMap===void 0&&(e.NamedNodeMap||e.MozNamedAttrMap),e.HTMLFormElement;let l=e.DOMParser,u=e.trustedTypes,d=s.prototype,f=RG(d,`cloneNode`),p=RG(d,`remove`),m=RG(d,`nextSibling`),h=RG(d,`childNodes`),g=RG(d,`parentNode`),_=RG(d,`shadowRoot`),v=RG(d,`attributes`),y=o&&o.prototype?RG(o.prototype,`nodeType`):null,b=o&&o.prototype?RG(o.prototype,`nodeName`):null;if(typeof a==`function`){let e=n.createElement(`template`);e.content&&e.content.ownerDocument&&(n=e.content.ownerDocument)}let x,S=``,C,w=!1,T=0,E=function(){if(T>0)throw PG(`A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.`)},D=function(e){E(),T++;try{return x.createHTML(e)}finally{T--}},O=function(e){E(),T++;try{return x.createScriptURL(e)}finally{T--}},k=function(){return w||=(C=cMe(u,i),!0),C},A=n,j=A.implementation,M=A.createNodeIterator,N=A.createDocumentFragment,P=A.getElementsByTagName,F=r.importNode,I=QG();t.isSupported=typeof fG==`function`&&typeof g==`function`&&j&&j.createHTMLDocument!==void 0;let L=Xje,R=Zje,z=Qje,B=$je,V=eMe,ee=tMe,te=nMe,H=iMe,ne=JG,re=null,U=IG({},[...zG,...BG,...VG,...HG,...UG]),ie=null,ae=IG({},[...WG,...GG,...KG,...qG]),W=Object.seal(gG(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),oe=null,se=null,ce=Object.seal(gG(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}})),le=!0,ue=!0,de=!1,fe=!0,pe=!1,me=!0,he=!1,ge=!1,_e=null,ve=null,ye=!1,be=!1,xe=!1,Se=!1,Ce=!0,we=!1,Te=`user-content-`,Ee=!0,De=!1,Oe={},ke=null,Ae=IG({},`annotation-xml.audio.colgroup.desc.foreignobject.head.iframe.math.mi.mn.mo.ms.mtext.noembed.noframes.noscript.plaintext.script.selectedcontent.style.svg.template.thead.title.video.xmp`.split(`.`)),je=null,Me=IG({},[`audio`,`video`,`img`,`source`,`image`,`track`]),Ne=null,Pe=IG({},[`alt`,`class`,`for`,`id`,`label`,`name`,`pattern`,`placeholder`,`role`,`summary`,`title`,`value`,`style`,`xmlns`]),Fe=`http://www.w3.org/1998/Math/MathML`,Ie=`http://www.w3.org/2000/svg`,Le=`http://www.w3.org/1999/xhtml`,Re=Le,ze=!1,Be=null,Ve=IG({},[Fe,Ie,Le],TG),He=mG([`mi`,`mo`,`mn`,`ms`,`mtext`]),Ue=IG({},He),We=mG([`annotation-xml`]),Ge=IG({},We),Ke=IG({},[`title`,`style`,`font`,`a`,`script`]),qe=null,Je=[`application/xhtml+xml`,`text/html`],Ye=null,Xe=null,Ze=n.createElement(`form`),Qe=function(e){return e instanceof RegExp||e instanceof Function},$e=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(Xe&&Xe===e)return;(!e||typeof e!=`object`)&&(e={}),e=LG(e),qe=Je.indexOf(e.PARSER_MEDIA_TYPE)===-1?`text/html`:e.PARSER_MEDIA_TYPE,Ye=qe===`application/xhtml+xml`?TG:wG,re=$G(e,`ALLOWED_TAGS`,U,{transform:Ye}),ie=$G(e,`ALLOWED_ATTR`,ae,{transform:Ye}),Be=$G(e,`ALLOWED_NAMESPACES`,Ve,{transform:TG}),Ne=$G(e,`ADD_URI_SAFE_ATTR`,Pe,{transform:Ye,base:Pe}),je=$G(e,`ADD_DATA_URI_TAGS`,Me,{transform:Ye,base:Me}),ke=$G(e,`FORBID_CONTENTS`,Ae,{transform:Ye}),oe=$G(e,`FORBID_TAGS`,LG({}),{transform:Ye}),se=$G(e,`FORBID_ATTR`,LG({}),{transform:Ye}),Oe=jG(e,`USE_PROFILES`)?e.USE_PROFILES&&typeof e.USE_PROFILES==`object`?LG(e.USE_PROFILES):e.USE_PROFILES:!1,le=e.ALLOW_ARIA_ATTR!==!1,ue=e.ALLOW_DATA_ATTR!==!1,de=e.ALLOW_UNKNOWN_PROTOCOLS||!1,fe=e.ALLOW_SELF_CLOSE_IN_ATTR!==!1,pe=e.SAFE_FOR_TEMPLATES||!1,me=e.SAFE_FOR_XML!==!1,he=e.WHOLE_DOCUMENT||!1,be=e.RETURN_DOM||!1,xe=e.RETURN_DOM_FRAGMENT||!1,Se=e.RETURN_TRUSTED_TYPE||!1,ye=e.FORCE_BODY||!1,Ce=e.SANITIZE_DOM!==!1,we=e.SANITIZE_NAMED_PROPS||!1,Ee=e.KEEP_CONTENT!==!1,De=e.IN_PLACE||!1,ne=qje(e.ALLOWED_URI_REGEXP)?e.ALLOWED_URI_REGEXP:JG,Re=typeof e.NAMESPACE==`string`?e.NAMESPACE:Le,Ue=jG(e,`MATHML_TEXT_INTEGRATION_POINTS`)&&e.MATHML_TEXT_INTEGRATION_POINTS&&typeof e.MATHML_TEXT_INTEGRATION_POINTS==`object`?LG(e.MATHML_TEXT_INTEGRATION_POINTS):IG({},He),Ge=jG(e,`HTML_INTEGRATION_POINTS`)&&e.HTML_INTEGRATION_POINTS&&typeof e.HTML_INTEGRATION_POINTS==`object`?LG(e.HTML_INTEGRATION_POINTS):IG({},We);let t=jG(e,`CUSTOM_ELEMENT_HANDLING`)&&e.CUSTOM_ELEMENT_HANDLING&&typeof e.CUSTOM_ELEMENT_HANDLING==`object`?LG(e.CUSTOM_ELEMENT_HANDLING):gG(null);if(W=gG(null),jG(t,`tagNameCheck`)&&Qe(t.tagNameCheck)&&(W.tagNameCheck=t.tagNameCheck),jG(t,`attributeNameCheck`)&&Qe(t.attributeNameCheck)&&(W.attributeNameCheck=t.attributeNameCheck),jG(t,`allowCustomizedBuiltInElements`)&&typeof t.allowCustomizedBuiltInElements==`boolean`&&(W.allowCustomizedBuiltInElements=t.allowCustomizedBuiltInElements),hG(W),pe&&(ue=!1),xe&&(be=!0),Oe&&(re=IG({},UG),ie=gG(null),Oe.html===!0&&(IG(re,zG),IG(ie,WG)),Oe.svg===!0&&(IG(re,BG),IG(ie,GG),IG(ie,qG)),Oe.svgFilters===!0&&(IG(re,VG),IG(ie,GG),IG(ie,qG)),Oe.mathMl===!0&&(IG(re,HG),IG(ie,KG),IG(ie,qG))),ce.tagCheck=null,ce.attributeCheck=null,jG(e,`ADD_TAGS`)&&(typeof e.ADD_TAGS==`function`?ce.tagCheck=e.ADD_TAGS:CG(e.ADD_TAGS)&&(re===U&&(re=LG(re)),IG(re,e.ADD_TAGS,Ye))),jG(e,`ADD_ATTR`)&&(typeof e.ADD_ATTR==`function`?ce.attributeCheck=e.ADD_ATTR:CG(e.ADD_ATTR)&&(ie===ae&&(ie=LG(ie)),IG(ie,e.ADD_ATTR,Ye))),jG(e,`ADD_URI_SAFE_ATTR`)&&CG(e.ADD_URI_SAFE_ATTR)&&IG(Ne,e.ADD_URI_SAFE_ATTR,Ye),jG(e,`FORBID_CONTENTS`)&&CG(e.FORBID_CONTENTS)&&(ke===Ae&&(ke=LG(ke)),IG(ke,e.FORBID_CONTENTS,Ye)),jG(e,`ADD_FORBID_CONTENTS`)&&CG(e.ADD_FORBID_CONTENTS)&&(ke===Ae&&(ke=LG(ke)),IG(ke,e.ADD_FORBID_CONTENTS,Ye)),Ee&&(re[`#text`]=!0),he&&IG(re,[`html`,`head`,`body`]),re.table&&(IG(re,[`tbody`]),delete oe.tbody),e.TRUSTED_TYPES_POLICY){if(typeof e.TRUSTED_TYPES_POLICY.createHTML!=`function`)throw PG(`TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.`);if(typeof e.TRUSTED_TYPES_POLICY.createScriptURL!=`function`)throw PG(`TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.`);let t=x;x=e.TRUSTED_TYPES_POLICY;try{S=D(``)}catch(e){throw x=t,e}}else e.TRUSTED_TYPES_POLICY===null?(x=void 0,S=``):(x===void 0&&(x=k()),x&&typeof S==`string`&&(S=D(``)));mG&&mG(e),Xe=e},et=IG({},[...BG,...VG,...Jje]),tt=IG({},[...HG,...Yje]),nt=function(e,t,n){return t.namespaceURI===Le?e===`svg`:t.namespaceURI===Fe?e===`svg`&&(n===`annotation-xml`||Ue[n]):!!et[e]},rt=function(e,t,n){return t.namespaceURI===Le?e===`math`:t.namespaceURI===Ie?e===`math`&&Ge[n]:!!tt[e]},it=function(e,t,n){return t.namespaceURI===Ie&&!Ge[n]||t.namespaceURI===Fe&&!Ue[n]?!1:!tt[e]&&(Ke[e]||!et[e])},at=function(e){let t=g(e);(!t||!t.tagName)&&(t={namespaceURI:Re,tagName:`template`});let n=wG(e.tagName),r=wG(t.tagName);return Be[e.namespaceURI]?e.namespaceURI===Ie?nt(n,t,r):e.namespaceURI===Fe?rt(n,t,r):e.namespaceURI===Le?it(n,t,r):!!(qe===`application/xhtml+xml`&&Be[e.namespaceURI]):!1},ot=function(e){SG(t.removed,{element:e});try{g(e).removeChild(e)}catch{if(p(e),!g(e))throw PG(`a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place`)}},st=function(e){ut(e);let t=h(e);if(t){let e=[];bG(t,t=>{SG(e,t)}),bG(e,e=>{try{p(e)}catch{}})}let n=v(e);if(n)for(let t=n.length-1;t>=0;--t){let r=n[t],i=r&&r.name;if(typeof i==`string`)try{e.removeAttribute(i)}catch{}}},ct=function(e,n){try{SG(t.removed,{attribute:n.getAttributeNode(e),from:n})}catch{SG(t.removed,{attribute:null,from:n})}if(n.removeAttribute(e),e===`is`)if(be||xe)try{ot(n)}catch{}else try{n.setAttribute(e,``)}catch{}},lt=function(e){let t=v(e);if(t)for(let n=t.length-1;n>=0;--n){let r=t[n],i=r&&r.name;if(!(typeof i!=`string`||ie[Ye(i)]))try{e.removeAttribute(i)}catch{}}},ut=function(e){let t=[e];for(;t.length>0;){let e=t.pop();(y?y(e):e.nodeType)===ZG.element&<(e);let n=h(e);if(n)for(let e=n.length-1;e>=0;--e)t.push(n[e])}},dt=function(e){if(!me)return;let t=[e];for(;t.length>0;){let e=t.pop(),n=y?y(e):e.nodeType;if(n===ZG.processingInstruction||n===ZG.comment&&NG(XG,e.data)){try{p(e)}catch{}continue}if(n===ZG.element){let t=e,n=Ye(b?b(e):e.nodeName);try{t.hasAttribute&&t.hasAttribute(`patchsrc`)&&t.removeAttribute(`patchsrc`),t.hasAttribute&&t.hasAttribute(`for`)&&n!==`label`&&n!==`output`&&t.removeAttribute(`for`)}catch{}}let r=h(e);if(r)for(let e=r.length-1;e>=0;--e)t.push(r[e])}},ft=function(e){let t=null,r=null;if(ye)e=``+e;else{let t=EG(e,/^[\r\n\t ]+/);r=t&&t[0]}qe===`application/xhtml+xml`&&Re===Le&&(e=``+e+``);let i=x?D(e):e;if(Re===Le)try{t=new l().parseFromString(i,qe)}catch{}if(!t||!t.documentElement){t=j.createDocument(Re,`template`,null);try{t.documentElement.innerHTML=ze?S:i}catch{}}let a=t.body||t.documentElement;return e&&r&&a.insertBefore(n.createTextNode(r),a.childNodes[0]||null),Re===Le?P.call(t,he?`html`:`body`)[0]:he?t.documentElement:a},pt=function(e){return M.call(e.ownerDocument||e,e,c.SHOW_ELEMENT|c.SHOW_COMMENT|c.SHOW_TEXT|c.SHOW_PROCESSING_INSTRUCTION|c.SHOW_CDATA_SECTION,null)},mt=function(e){return e=DG(e,L,` `),e=DG(e,R,` `),e=DG(e,z,` `),e},ht=function(e){e.normalize();let t=M.call(e.ownerDocument||e,e,c.SHOW_TEXT|c.SHOW_COMMENT|c.SHOW_CDATA_SECTION|c.SHOW_PROCESSING_INSTRUCTION,null),n=t.nextNode();for(;n;)n.data=mt(n.data),n=t.nextNode();let r=e.querySelectorAll?.call(e,`template`);r&&bG(r,e=>{_t(e.content)&&ht(e.content)})},gt=function(e){let t=b?b(e):null;return typeof t!=`string`||Ye(t)!==`form`?!1:typeof e.nodeName!=`string`||typeof e.textContent!=`string`||typeof e.removeChild!=`function`||e.attributes!==v(e)||typeof e.removeAttribute!=`function`||typeof e.setAttribute!=`function`||typeof e.namespaceURI!=`string`||typeof e.insertBefore!=`function`||typeof e.hasChildNodes!=`function`||e.nodeType!==y(e)||e.childNodes!==h(e)},_t=function(e){if(!y||typeof e!=`object`||!e)return!1;try{return y(e)===ZG.documentFragment}catch{return!1}},vt=function(e){if(!y||typeof e!=`object`||!e)return!1;try{return typeof y(e)==`number`}catch{return!1}};function yt(e,n,r){e.length!==0&&bG(e,e=>{e.call(t,n,r,Xe)})}let bt=function(e,t){return!!(me&&e.hasChildNodes()&&!vt(e.firstElementChild)&&NG(YG,e.textContent)&&NG(YG,e.innerHTML)||me&&e.namespaceURI===Le&&t===`style`&&vt(e.firstElementChild)||e.nodeType===ZG.processingInstruction||me&&e.nodeType===ZG.comment&&NG(XG,e.data))},xt=function(e,t){if(!oe[t]&&Tt(t)&&(W.tagNameCheck instanceof RegExp&&NG(W.tagNameCheck,t)||W.tagNameCheck instanceof Function&&W.tagNameCheck(t)))return!1;if(Ee&&!ke[t]){let t=g(e),n=h(e);if(n&&t){let r=n.length;for(let i=r-1;i>=0;--i){let r=De?n[i]:f(n[i],!0);t.insertBefore(r,m(e))}}}return ot(e),!0},St=function(e,n){if(yt(I.beforeSanitizeElements,e,null),e!==n&&g(e)===null)return!0;if(gt(e))return ot(e),!0;let r=Ye(b?b(e):e.nodeName);if(yt(I.uponSanitizeElement,e,{tagName:r,allowedTags:re}),e!==n&&g(e)===null)return!0;if(bt(e,r))return ot(e),!0;if(oe[r]||!(ce.tagCheck instanceof Function&&ce.tagCheck(r))&&!re[r]){let t=xt(e,r);return t===!1&&yt(I.afterSanitizeElements,e,null),t}if((y?y(e):e.nodeType)===ZG.element&&!at(e)||(r===`noscript`||r===`noembed`||r===`noframes`)&&NG(aMe,e.innerHTML))return ot(e),!0;if(pe&&e.nodeType===ZG.text){let n=mt(e.textContent);e.textContent!==n&&(SG(t.removed,{element:e.cloneNode()}),e.textContent=n)}return yt(I.afterSanitizeElements,e,null),!1},Ct=function(e,t,r){if(se[t]||me&&t===`patchsrc`||me&&t===`for`&&e!==`label`&&e!==`output`||Ce&&(t===`id`||t===`name`)&&(r in n||r in Ze))return!1;let i=ie[t]||ce.attributeCheck instanceof Function&&ce.attributeCheck(t,e);if(!(ue&&NG(B,t))&&!(le&&NG(V,t))){if(!i){if(!(Tt(e)&&(W.tagNameCheck instanceof RegExp&&NG(W.tagNameCheck,e)||W.tagNameCheck instanceof Function&&W.tagNameCheck(e))&&(W.attributeNameCheck instanceof RegExp&&NG(W.attributeNameCheck,t)||W.attributeNameCheck instanceof Function&&W.attributeNameCheck(t,e))||t===`is`&&W.allowCustomizedBuiltInElements&&(W.tagNameCheck instanceof RegExp&&NG(W.tagNameCheck,r)||W.tagNameCheck instanceof Function&&W.tagNameCheck(r))))return!1}else if(!Ne[t]&&!NG(ne,DG(r,te,``))&&!((t===`src`||t===`xlink:href`||t===`href`)&&e!==`script`&&OG(r,`data:`)===0&&je[e])&&!(de&&!NG(ee,DG(r,te,``)))&&r)return!1}return!0},wt=IG({},[`annotation-xml`,`color-profile`,`font-face`,`font-face-format`,`font-face-name`,`font-face-src`,`font-face-uri`,`missing-glyph`]),Tt=function(e){return!wt[wG(e)]&&NG(H,e)},Et=function(e,t,n,r){if(x&&typeof u==`object`&&typeof u.getAttributeType==`function`&&!n)switch(u.getAttributeType(e,t)){case`TrustedHTML`:return D(r);case`TrustedScriptURL`:return O(r)}return r},Dt=function(e,n,r,i){try{r?e.setAttributeNS(r,n,i):e.setAttribute(n,i),gt(e)?ot(e):xG(t.removed)}catch{ct(n,e)}},Ot=function(e){yt(I.beforeSanitizeAttributes,e,null);let t=e.attributes;if(!t||gt(e))return;let n={attrName:``,attrValue:``,keepAttr:!0,allowedAttributes:ie,forceKeepAttr:void 0},r=t.length,i=Ye(e.nodeName);for(;r--;){let a=t[r],o=a.name,s=a.namespaceURI,c=a.value,l=Ye(o),u=c,d=o===`value`?u:Vje(u);if(n.attrName=l,n.attrValue=d,n.keepAttr=!0,n.forceKeepAttr=void 0,yt(I.uponSanitizeAttribute,e,n),d=n.attrValue,we&&(l===`id`||l===`name`)&&OG(d,Te)!==0&&(ct(o,e),d=Te+d),me&&NG(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,d)){ct(o,e);continue}if(l===`attributename`&&EG(d,`href`)){ct(o,e);continue}if(!n.forceKeepAttr){if(!n.keepAttr){ct(o,e);continue}if(!fe&&NG(oMe,d)){ct(o,e);continue}if(pe&&(d=mt(d)),!Ct(i,l,d)){ct(o,e);continue}d=Et(i,l,s,d),d!==u&&Dt(e,o,s,d)}}yt(I.afterSanitizeAttributes,e,null)},kt=function(e){let t=null,n=pt(e);for(yt(I.beforeSanitizeShadowDOM,e,null);t=n.nextNode();)if(yt(I.uponSanitizeShadowNode,t,null),St(t,e),Ot(t),_t(t.content)&&kt(t.content),(y?y(t):t.nodeType)===ZG.element){let e=_(t);_t(e)&&(At(e),kt(e))}yt(I.afterSanitizeShadowDOM,e,null)},At=function(e){let t=[{node:e,shadow:null}];for(;t.length>0;){let e=t.pop();if(e.shadow){kt(e.shadow);continue}let n=e.node,r=(y?y(n):n.nodeType)===ZG.element,i=h(n);if(i)for(let e=i.length-1;e>=0;--e)t.push({node:i[e],shadow:null});if(r){let e=b?b(n):null;if(typeof e==`string`&&Ye(e)===`template`){let e=n.content;_t(e)&&t.push({node:e,shadow:null})}}if(r){let e=_(n);_t(e)&&t.push({node:null,shadow:e},{node:e,shadow:null})}}};return t.sanitize=function(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},i=null,a=null,o=null,s=null;if(ze=!e,ze&&(e=``),typeof e!=`string`&&!vt(e)&&(e=Kje(e),typeof e!=`string`))throw PG(`dirty is not a string, aborting`);if(!t.isSupported)return e;ge?(re=_e,ie=ve):$e(n),(I.uponSanitizeElement.length>0||I.uponSanitizeAttribute.length>0)&&(re=LG(re)),I.uponSanitizeAttribute.length>0&&(ie=LG(ie)),t.removed=[];let c=De&&typeof e!=`string`&&vt(e);if(c){dt(e);let t=b?b(e):e.nodeName;if(typeof t==`string`){let n=Ye(t);if(!re[n]||oe[n])throw st(e),PG(`root node is forbidden and cannot be sanitized in-place`)}if(gt(e))throw st(e),PG(`root node is clobbered and cannot be sanitized in-place`);try{At(e)}catch(t){throw st(e),t}}else if(vt(e))i=ft(``),a=i.ownerDocument.importNode(e,!0),a.nodeType===ZG.element&&a.nodeName===`BODY`||a.nodeName===`HTML`?i=a:i.appendChild(a),At(a);else{if(!be&&!pe&&!he&&e.indexOf(`<`)===-1)return x&&Se?D(e):e;if(i=ft(e),!i)return be?null:Se?S:``}i&&ye&&ot(i.firstChild);let l=c?e:i,u=pt(l);try{for(;o=u.nextNode();)St(o,l),Ot(o),_t(o.content)&&kt(o.content)}catch(n){throw c&&(st(e),bG(t.removed,e=>{e.element&&ut(e.element)})),n}if(c)return bG(t.removed,e=>{e.element&&ut(e.element)}),pe&&ht(e),e;if(be){if(pe&&ht(i),xe)for(s=N.call(i.ownerDocument);i.firstChild;)s.appendChild(i.firstChild);else s=i;return(ie.shadowroot||ie.shadowrootmode)&&(s=F.call(r,s,!0)),s}let d=he?i.outerHTML:i.innerHTML;return he&&re[`!doctype`]&&i.ownerDocument&&i.ownerDocument.doctype&&i.ownerDocument.doctype.name&&NG(rMe,i.ownerDocument.doctype.name)&&(d=` `+d),pe&&(d=mt(d)),x&&Se?D(d):d},t.setConfig=function(){$e(arguments.length>0&&arguments[0]!==void 0?arguments[0]:{}),ge=!0,_e=re,ve=ie},t.clearConfig=function(){Xe=null,ge=!1,_e=null,ve=null,x=C,S=``},t.isValidAttribute=function(e,t,n){return Xe||$e({}),Ct(Ye(e),Ye(t),n)},t.addHook=function(e,t){typeof t==`function`&&jG(I,e)&&SG(I[e],t)},t.removeHook=function(e,t){if(jG(I,e)){if(t!==void 0){let n=zje(I[e],t);return n===-1?void 0:Bje(I[e],n,1)[0]}return xG(I[e])}},t.removeHooks=function(e){jG(I,e)&&(I[e]=[])},t.removeAllHooks=function(){I=QG()},t}var tK=eK();function nK(e){this.content=e}nK.prototype={constructor:nK,find:function(e){for(var t=0;t>1}},nK.from=function(e){if(e instanceof nK)return e;var t=[];if(e)for(var n in e)t.push(n,e[n]);return new nK(t)};function rK(e,t,n){for(let r=0;;r++){if(r==e.childCount||r==t.childCount)return e.childCount==t.childCount?null:n;let i=e.child(r),a=t.child(r);if(i==a){n+=i.nodeSize;continue}if(!i.sameMarkup(a))return n;if(i.isText&&i.text!=a.text){for(let e=0;i.text[e]==a.text[e];e++)n++;return n}if(i.content.size||a.content.size){let e=rK(i.content,a.content,n+1);if(e!=null)return e}n+=i.nodeSize}}function iK(e,t,n,r){for(let i=e.childCount,a=t.childCount;;){if(i==0||a==0)return i==a?null:{a:n,b:r};let o=e.child(--i),s=t.child(--a),c=o.nodeSize;if(o==s){n-=c,r-=c;continue}if(!o.sameMarkup(s))return{a:n,b:r};if(o.isText&&o.text!=s.text){let e=0,t=Math.min(o.text.length,s.text.length);for(;ee&&n(s,r+o,i||null,a)!==!1&&s.content.size){let i=o+1;s.nodesBetween(Math.max(0,e-i),Math.min(s.content.size,t-i),n,r+i)}o=c}}descendants(e){this.nodesBetween(0,this.size,e)}textBetween(e,t,n,r){let i=``,a=!0;return this.nodesBetween(e,t,(o,s)=>{let c=o.isText?o.text.slice(Math.max(e,s)-s,t-s):o.isLeaf?r?typeof r==`function`?r(o):r:o.type.spec.leafText?o.type.spec.leafText(o):``:``;o.isBlock&&(o.isLeaf&&c||o.isTextblock)&&n&&(a?a=!1:i+=n),i+=c},0),i}append(t){if(!t.size)return this;if(!this.size)return t;let n=this.lastChild,r=t.firstChild,i=this.content.slice(),a=0;for(n.isText&&n.sameMarkup(r)&&(i[i.length-1]=n.withText(n.text+r.text),a=1);at)for(let e=0,a=0;at&&((an)&&(o=o.isText?o.cut(Math.max(0,t-a),Math.min(o.text.length,n-a)):o.cut(Math.max(0,t-a-1),Math.min(o.content.size,n-a-1))),r.push(o),i+=o.nodeSize),a=s}return new e(r,i)}cutByIndex(t,n){return t==n?e.empty:t==0&&n==this.content.length?this:new e(this.content.slice(t,n))}replaceChild(t,n){let r=this.content[t];if(r==n)return this;let i=this.content.slice(),a=this.size+n.nodeSize-r.nodeSize;return i[t]=n,new e(i,a)}addToStart(t){return new e([t].concat(this.content),this.size+t.nodeSize)}addToEnd(t){return new e(this.content.concat(t),this.size+t.nodeSize)}eq(e){if(this.content.length!=e.content.length)return!1;for(let t=0;tthis.size||e<0)throw RangeError(`Position ${e} outside of fragment (${this})`);for(let t=0,n=0;;t++){let r=this.child(t),i=n+r.nodeSize;if(i>=e)return i==e?sK(t+1,i):sK(t,n);n=i}}toString(){return`<`+this.toStringInner()+`>`}toStringInner(){return this.content.join(`, `)}toJSON(){return this.content.length?this.content.map(e=>e.toJSON()):null}static fromJSON(t,n){if(!n)return e.empty;if(!Array.isArray(n))throw RangeError(`Invalid input for Fragment.fromJSON`);return new e(n.map(t.nodeFromJSON))}static fromArray(t){if(!t.length)return e.empty;let n,r=0;for(let e=0;ethis.type.rank&&(t||=e.slice(0,r),t.push(this),n=!0),t&&t.push(i)}return t||=e.slice(),n||t.push(this),t}removeFromSet(e){for(let t=0;te.type.rank-t.type.rank),n}};lK.none=[];var uK=class extends Error{},dK=class e{constructor(e,t,n){this.content=e,this.openStart=t,this.openEnd=n}get size(){return this.content.size-this.openStart-this.openEnd}insertAt(t,n){let r=pK(this.content,t+this.openStart,n);return r&&new e(r,this.openStart,this.openEnd)}removeBetween(t,n){return new e(fK(this.content,t+this.openStart,n+this.openStart),this.openStart,this.openEnd)}eq(e){return this.content.eq(e.content)&&this.openStart==e.openStart&&this.openEnd==e.openEnd}toString(){return this.content+`(`+this.openStart+`,`+this.openEnd+`)`}toJSON(){if(!this.content.size)return null;let e={content:this.content.toJSON()};return this.openStart>0&&(e.openStart=this.openStart),this.openEnd>0&&(e.openEnd=this.openEnd),e}static fromJSON(t,n){if(!n)return e.empty;let r=n.openStart||0,i=n.openEnd||0;if(typeof r!=`number`||typeof i!=`number`)throw RangeError(`Invalid input for Slice.fromJSON`);return new e(aK.fromJSON(t,n.content),r,i)}static maxOpen(t,n=!0){let r=0,i=0;for(let e=t.firstChild;e&&!e.isLeaf&&(n||!e.type.spec.isolating);e=e.firstChild)r++;for(let e=t.lastChild;e&&!e.isLeaf&&(n||!e.type.spec.isolating);e=e.lastChild)i++;return new e(t,r,i)}};dK.empty=new dK(aK.empty,0,0);function fK(e,t,n){let{index:r,offset:i}=e.findIndex(t),a=e.maybeChild(r),{index:o,offset:s}=e.findIndex(n);if(i==t||a.isText){if(s!=n&&!e.child(o).isText)throw RangeError(`Removing non-flat range`);return e.cut(0,t).append(e.cut(n))}if(r!=o)throw RangeError(`Removing non-flat range`);return e.replaceChild(r,a.copy(fK(a.content,t-i-1,n-i-1)))}function pK(e,t,n,r){let{index:i,offset:a}=e.findIndex(t),o=e.maybeChild(i);if(a==t||o.isText)return r&&!r.canReplace(i,i,n)?null:e.cut(0,t).append(n).append(e.cut(t));let s=pK(o.content,t-a-1,n,o);return s&&e.replaceChild(i,o.copy(s))}function lMe(e,t,n){if(n.openStart>e.depth)throw new uK(`Inserted content deeper than insertion position`);if(e.depth-n.openStart!=t.depth-n.openEnd)throw new uK(`Inconsistent open depths`);return mK(e,t,n,0)}function mK(e,t,n,r){let i=e.index(r),a=e.node(r);if(i==t.index(r)&&r=0&&e.isText&&e.sameMarkup(t[n])?t[n]=e.withText(t[n].text+e.text):t.push(e)}function vK(e,t,n,r){let i=(t||e).node(n),a=0,o=t?t.index(n):i.childCount;e&&(a=e.index(n),e.depth>n?a++:e.textOffset&&(_K(e.nodeAfter,r),a++));for(let e=a;ei&&gK(e,t,i+1),o=r.depth>i&&gK(n,r,i+1),s=[];return vK(null,e,i,s),a&&o&&t.index(i)==n.index(i)?(hK(a,o),_K(yK(a,bK(e,t,n,r,i+1)),s)):(a&&_K(yK(a,xK(e,t,i+1)),s),vK(t,n,i,s),o&&_K(yK(o,xK(n,r,i+1)),s)),vK(r,null,i,s),new aK(s)}function xK(e,t,n){let r=[];return vK(null,e,n,r),e.depth>n&&_K(yK(gK(e,t,n+1),xK(e,t,n+1)),r),vK(t,null,n,r),new aK(r)}function uMe(e,t){let n=t.depth-e.openStart,r=t.node(n).copy(e.content);for(let e=n-1;e>=0;e--)r=t.node(e).copy(aK.from(r));return{start:r.resolveNoCache(e.openStart+n),end:r.resolveNoCache(r.content.size-e.openEnd-n)}}var SK=class e{constructor(e,t,n){this.pos=e,this.path=t,this.parentOffset=n,this.depth=t.length/3-1}resolveDepth(e){return e==null?this.depth:e<0?this.depth+e:e}get parent(){return this.node(this.depth)}get doc(){return this.node(0)}node(e){return this.path[this.resolveDepth(e)*3]}index(e){return this.path[this.resolveDepth(e)*3+1]}indexAfter(e){return e=this.resolveDepth(e),this.index(e)+(e==this.depth&&!this.textOffset?0:1)}start(e){return e=this.resolveDepth(e),e==0?0:this.path[e*3-1]+1}end(e){return e=this.resolveDepth(e),this.start(e)+this.node(e).content.size}before(e){if(e=this.resolveDepth(e),!e)throw RangeError(`There is no position before the top-level node`);return e==this.depth+1?this.pos:this.path[e*3-1]}after(e){if(e=this.resolveDepth(e),!e)throw RangeError(`There is no position after the top-level node`);return e==this.depth+1?this.pos:this.path[e*3-1]+this.path[e*3].nodeSize}get textOffset(){return this.pos-this.path[this.path.length-1]}get nodeAfter(){let e=this.parent,t=this.index(this.depth);if(t==e.childCount)return null;let n=this.pos-this.path[this.path.length-1],r=e.child(t);return n?e.child(t).cut(n):r}get nodeBefore(){let e=this.index(this.depth),t=this.pos-this.path[this.path.length-1];return t?this.parent.child(e).cut(0,t):e==0?null:this.parent.child(e-1)}posAtIndex(e,t){t=this.resolveDepth(t);let n=this.path[t*3],r=t==0?0:this.path[t*3-1]+1;for(let t=0;t0;t--)if(this.start(t)<=e&&this.end(t)>=e)return t;return 0}blockRange(e=this,t){if(e.pos=0;n--)if(e.pos<=this.end(n)&&(!t||t(this.node(n))))return new wK(this,e,n);return null}sameParent(e){return this.pos-this.parentOffset==e.pos-e.parentOffset}max(e){return e.pos>this.pos?e:this}min(e){return e.pos=0&&n<=t.content.size))throw RangeError(`Position `+n+` out of range`);let r=[],i=0,a=n;for(let e=t;;){let{index:t,offset:n}=e.content.findIndex(a),o=a-n;if(r.push(e,t,i+n),!o||(e=e.child(t),e.isText))break;a=o-1,i+=n+1}return new e(n,r,a)}static resolveCached(t,n){let r=CK.get(t);if(r)for(let e=0;ee&&this.nodesBetween(e,t,e=>(n.isInSet(e.marks)&&(r=!0),!r)),r}get isBlock(){return this.type.isBlock}get isTextblock(){return this.type.isTextblock}get inlineContent(){return this.type.inlineContent}get isInline(){return this.type.isInline}get isText(){return this.type.isText}get isLeaf(){return this.type.isLeaf}get isAtom(){return this.type.isAtom}toString(){if(this.type.spec.toDebugString)return this.type.spec.toDebugString(this);let e=this.type.name;return this.content.size&&(e+=`(`+this.content.toStringInner()+`)`),EK(this.marks,e)}contentMatchAt(e){let t=this.type.contentMatch.matchFragment(this.content,0,e);if(!t)throw Error(`Called contentMatchAt on a node with invalid content`);return t}canReplace(e,t,n=aK.empty,r=0,i=n.childCount){let a=this.contentMatchAt(e).matchFragment(n,r,i),o=a&&a.matchFragment(this.content,t);if(!o||!o.validEnd)return!1;for(let e=r;ee.type.name)}`);this.content.forEach(e=>e.check())}toJSON(){let e={type:this.type.name};for(let t in this.attrs){e.attrs=this.attrs;break}return this.content.size&&(e.content=this.content.toJSON()),this.marks.length&&(e.marks=this.marks.map(e=>e.toJSON())),e}static fromJSON(e,t){if(!t)throw RangeError(`Invalid input for Node.fromJSON`);let n;if(t.marks){if(!Array.isArray(t.marks))throw RangeError(`Invalid mark data for Node.fromJSON`);n=t.marks.map(e.markFromJSON)}if(t.type==`text`){if(typeof t.text!=`string`)throw RangeError(`Invalid text node in JSON`);return e.text(t.text,n)}let r=aK.fromJSON(e,t.content),i=e.nodeType(t.type).create(t.attrs,r,n);return i.type.checkAttrs(i.attrs),i}};TK.prototype.text=void 0;var mMe=class e extends TK{constructor(e,t,n,r){if(super(e,t,null,r),!n)throw RangeError(`Empty text nodes are not allowed`);this.text=n}toString(){return this.type.spec.toDebugString?this.type.spec.toDebugString(this):EK(this.marks,JSON.stringify(this.text))}get textContent(){return this.text}textBetween(e,t){return this.text.slice(e,t)}get nodeSize(){return this.text.length}mark(t){return t==this.marks?this:new e(this.type,this.attrs,this.text,t)}withText(t){return t==this.text?this:new e(this.type,this.attrs,t,this.marks)}cut(e=0,t=this.text.length){return e==0&&t==this.text.length?this:this.withText(this.text.slice(e,t))}eq(e){return this.sameMarkup(e)&&this.text==e.text}toJSON(){let e=super.toJSON();return e.text=this.text,e}};function EK(e,t){for(let n=e.length-1;n>=0;n--)t=e[n].type.name+`(`+t+`)`;return t}var DK=class e{constructor(e){this.validEnd=e,this.next=[],this.wrapCache=[]}static parse(t,n){let r=new hMe(t,n);if(r.next==null)return e.empty;let i=OK(r);r.next&&r.err(`Unexpected trailing text`);let a=SMe(xMe(i));return CMe(a,r),a}matchType(e){for(let t=0;te.createAndFill()));for(let e=0;e=this.next.length)throw RangeError(`There's no ${e}th edge in this content match`);return this.next[e]}toString(){let e=[];function t(n){e.push(n);for(let r=0;r{let r=n+(t.validEnd?`*`:` `)+` `;for(let n=0;n`+e.indexOf(t.next[n].next);return r}).join(` `)}};DK.empty=new DK(!0);var hMe=class{constructor(e,t){this.string=e,this.nodeTypes=t,this.inline=null,this.pos=0,this.tokens=e.split(/\s*(?=\b|\W|$)/),this.tokens[this.tokens.length-1]==``&&this.tokens.pop(),this.tokens[0]==``&&this.tokens.shift()}get next(){return this.tokens[this.pos]}eat(e){return this.next==e&&(this.pos++||!0)}err(e){throw SyntaxError(e+` (in content expression '`+this.string+`')`)}};function OK(e){let t=[];do t.push(gMe(e));while(e.eat(`|`));return t.length==1?t[0]:{type:`choice`,exprs:t}}function gMe(e){let t=[];do t.push(_Me(e));while(e.next&&e.next!=`)`&&e.next!=`|`);return t.length==1?t[0]:{type:`seq`,exprs:t}}function _Me(e){let t=bMe(e);for(;;)if(e.eat(`+`))t={type:`plus`,expr:t};else if(e.eat(`*`))t={type:`star`,expr:t};else if(e.eat(`?`))t={type:`opt`,expr:t};else if(e.eat(`{`))t=vMe(e,t);else break;return t}function kK(e){/\D/.test(e.next)&&e.err(`Expected number, got '`+e.next+`'`);let t=Number(e.next);return e.pos++,t}function vMe(e,t){let n=kK(e),r=n;return e.eat(`,`)&&(r=e.next==`}`?-1:kK(e)),e.eat(`}`)||e.err(`Unclosed braced range`),{type:`range`,min:n,max:r,expr:t}}function yMe(e,t){let n=e.nodeTypes,r=n[t];if(r)return[r];let i=[];for(let e in n){let r=n[e];r.isInGroup(t)&&i.push(r)}return i.length==0&&e.err(`No node type or group '`+t+`' found`),i}function bMe(e){if(e.eat(`(`)){let t=OK(e);return e.eat(`)`)||e.err(`Missing closing paren`),t}else if(/\W/.test(e.next))e.err(`Unexpected token '`+e.next+`'`);else{let t=yMe(e,e.next).map(t=>(e.inline==null?e.inline=t.isInline:e.inline!=t.isInline&&e.err(`Mixing inline and block content`),{type:`name`,value:t}));return e.pos++,t.length==1?t[0]:{type:`choice`,exprs:t}}}function xMe(e){let t=[[]];return i(a(e,0),n()),t;function n(){return t.push([])-1}function r(e,n,r){let i={term:r,to:n};return t[e].push(i),i}function i(e,t){e.forEach(e=>e.to=t)}function a(e,t){if(e.type==`choice`)return e.exprs.reduce((e,n)=>e.concat(a(n,t)),[]);if(e.type==`seq`)for(let r=0;;r++){let o=a(e.exprs[r],t);if(r==e.exprs.length-1)return o;i(o,t=n())}else if(e.type==`star`){let o=n();return r(t,o),i(a(e.expr,o),o),[r(o)]}else if(e.type==`plus`){let o=n();return i(a(e.expr,t),o),i(a(e.expr,o),o),[r(o)]}else if(e.type==`opt`)return[r(t)].concat(a(e.expr,t));else if(e.type==`range`){let o=t;for(let t=0;t{e[t].forEach(({term:t,to:n})=>{if(!t)return;let r;for(let e=0;e{r||i.push([t,r=[]]),r.indexOf(e)==-1&&r.push(e)})})});let a=t[r.join(`,`)]=new DK(r.indexOf(e.length-1)>-1);for(let e=0;e-1}get whitespace(){return this.spec.whitespace||(this.spec.code?`pre`:`normal`)}hasRequiredAttrs(){for(let e in this.attrs)if(this.attrs[e].isRequired)return!0;return!1}compatibleContent(e){return this==e||this.contentMatch.compatible(e.contentMatch)}computeAttrs(e){return!e&&this.defaultAttrs?this.defaultAttrs:NK(this.attrs,e)}create(e=null,t,n){if(this.isText)throw Error(`NodeType.create can't construct text nodes`);return new TK(this,this.computeAttrs(e),aK.from(t),lK.setFrom(n))}createChecked(e=null,t,n){return t=aK.from(t),this.checkContent(t),new TK(this,this.computeAttrs(e),t,lK.setFrom(n))}createAndFill(e=null,t,n){if(e=this.computeAttrs(e),t=aK.from(t),t.size){let e=this.contentMatch.fillBefore(t);if(!e)return null;t=e.append(t)}let r=this.contentMatch.matchFragment(t),i=r&&r.fillBefore(aK.empty,!0);return i?new TK(this,e,t.append(i),lK.setFrom(n)):null}validContent(e){let t=this.contentMatch.matchFragment(e);if(!t||!t.validEnd)return!1;for(let t=0;t-1}allowsMarks(e){if(this.markSet==null)return!0;for(let t=0;tr[t]=new e(t,n,i));let i=n.spec.topNode||`doc`;if(!r[i])throw RangeError(`Schema is missing its top node type ('`+i+`')`);if(!r.text)throw RangeError(`Every schema needs a 'text' type`);for(let e in r.text.attrs)throw RangeError(`The text node type should not have attributes`);return r}};function wMe(e,t,n){let r=n.split(`|`);return n=>{let i=n===null?`null`:typeof n;if(r.indexOf(i)<0)throw RangeError(`Expected value of type ${r} for attribute ${t} on type ${e}, got ${i}`)}}var TMe=class{constructor(e,t,n){this.hasDefault=Object.prototype.hasOwnProperty.call(n,`default`),this.default=n.default,this.validate=typeof n.validate==`string`?wMe(e,t,n.validate):n.validate}get isRequired(){return!this.hasDefault}},LK=class e{constructor(e,t,n,r){this.name=e,this.rank=t,this.schema=n,this.spec=r,this.attrs=FK(e,r.attrs),this.excluded=null;let i=MK(this.attrs);this.instance=i?new lK(this,i):null}create(e=null){return!e&&this.instance?this.instance:new lK(this,NK(this.attrs,e))}static compile(t,n){let r=Object.create(null),i=0;return t.forEach((t,a)=>r[t]=new e(t,i++,n,a)),r}removeFromSet(e){for(var t=0;t-1}},RK=class{constructor(e){this.linebreakReplacement=null,this.cached=Object.create(null);let t=this.spec={};for(let n in e)t[n]=e[n];t.nodes=nK.from(e.nodes),t.marks=nK.from(e.marks||{}),this.nodes=IK.compile(this.spec.nodes,this),this.marks=LK.compile(this.spec.marks,this);let n=Object.create(null);for(let e in this.nodes){if(e in this.marks)throw RangeError(e+` can not be both a node and a mark`);let t=this.nodes[e],r=t.spec.content||``,i=t.spec.marks;if(t.contentMatch=n[r]||(n[r]=DK.parse(r,this.nodes)),t.inlineContent=t.contentMatch.inlineContent,t.spec.linebreakReplacement){if(this.linebreakReplacement)throw RangeError(`Multiple linebreak nodes defined`);if(!t.isInline||!t.isLeaf)throw RangeError(`Linebreak replacement nodes must be inline leaf nodes`);this.linebreakReplacement=t}t.markSet=i==`_`?null:i?zK(this,i.split(` `)):i==``||!t.inlineContent?[]:null}for(let e in this.marks){let t=this.marks[e],n=t.spec.excludes;t.excluded=n==null?[t]:n==``?[]:zK(this,n.split(` `))}this.nodeFromJSON=e=>TK.fromJSON(this,e),this.markFromJSON=e=>lK.fromJSON(this,e),this.topNodeType=this.nodes[this.spec.topNode||`doc`],this.cached.wrappings=Object.create(null)}node(e,t=null,n,r){if(typeof e==`string`)e=this.nodeType(e);else if(!(e instanceof IK))throw RangeError(`Invalid node type: `+e);else if(e.schema!=this)throw RangeError(`Node type from different schema used (`+e.name+`)`);return e.createChecked(t,n,r)}text(e,t){let n=this.nodes.text;return new mMe(n,n.defaultAttrs,e,lK.setFrom(t))}mark(e,t){return typeof e==`string`&&(e=this.marks[e]),e.create(t)}nodeType(e){let t=this.nodes[e];if(!t)throw RangeError(`Unknown node type: `+e);return t}};function zK(e,t){let n=[];for(let r=0;r-1)&&n.push(o=r)}if(!o)throw SyntaxError(`Unknown mark type: '`+t[r]+`'`)}return n}function EMe(e){return e.tag!=null}function DMe(e){return e.style!=null}var BK=class e{constructor(e,t){this.schema=e,this.rules=t,this.tags=[],this.styles=[];let n=this.matchedStyles=[];t.forEach(e=>{if(EMe(e))this.tags.push(e);else if(DMe(e)){let t=/[^=]*/.exec(e.style)[0];n.indexOf(t)<0&&n.push(t),this.styles.push(e)}}),this.normalizeLists=!this.tags.some(t=>{if(!/^(ul|ol)\b/.test(t.tag)||!t.node)return!1;let n=e.nodes[t.node];return n.contentMatch.matchType(n)})}parse(e,t={}){let n=new JK(this,t,!1);return n.addAll(e,lK.none,t.from,t.to),n.finish()}parseSlice(e,t={}){let n=new JK(this,t,!0);return n.addAll(e,lK.none,t.from,t.to),dK.maxOpen(n.finish())}matchTag(e,t,n){for(let r=n?this.tags.indexOf(n)+1:0;re.length&&(a.charCodeAt(e.length)!=61||a.slice(e.length+1)!=t))){if(r.getAttrs){let e=r.getAttrs(t);if(e===!1)continue;r.attrs=e||void 0}return r}}}static schemaRules(e){let t=[];function n(e){let n=e.priority==null?50:e.priority,r=0;for(;r{n(e=YK(e)),e.mark||e.ignore||e.clearMark||(e.mark=t)})}for(let t in e.nodes){let r=e.nodes[t].spec.parseDOM;r&&r.forEach(e=>{n(e=YK(e)),e.node||e.ignore||e.mark||(e.node=t)})}return t}static fromSchema(t){return t.cached.domParser||(t.cached.domParser=new e(t,e.schemaRules(t)))}},VK={address:!0,article:!0,aside:!0,blockquote:!0,canvas:!0,dd:!0,div:!0,dl:!0,fieldset:!0,figcaption:!0,figure:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,li:!0,noscript:!0,ol:!0,output:!0,p:!0,pre:!0,section:!0,table:!0,tfoot:!0,ul:!0},OMe={head:!0,noscript:!0,object:!0,script:!0,style:!0,title:!0},HK={ol:!0,ul:!0},UK=1,WK=2,GK=4;function KK(e,t,n){return t==null?e&&e.whitespace==`pre`?3:n&-5:(t?UK:0)|(t===`full`?WK:0)}var qK=class{constructor(e,t,n,r,i,a){this.type=e,this.attrs=t,this.marks=n,this.solid=r,this.options=a,this.content=[],this.activeMarks=lK.none,this.match=i||(a&GK?null:e.contentMatch)}findWrapping(e){if(!this.match){if(!this.type)return[];let t=this.type.contentMatch.fillBefore(aK.from(e));if(t)this.match=this.type.contentMatch.matchFragment(t);else{let t=this.type.contentMatch,n;return(n=t.findWrapping(e.type))?(this.match=t,n):null}}return this.match.findWrapping(e.type)}finish(e){if(!(this.options&UK)){let e=this.content[this.content.length-1],t;if(e&&e.isText&&(t=/[ \t\r\n\u000c]+$/.exec(e.text))){let n=e;e.text.length==t[0].length?this.content.pop():this.content[this.content.length-1]=n.withText(n.text.slice(0,n.text.length-t[0].length))}}let t=aK.from(this.content);return!e&&this.match&&(t=t.append(this.match.fillBefore(aK.empty,!0))),this.type?this.type.create(this.attrs,t,this.marks):t}inlineContext(e){return this.type?this.type.inlineContent:this.content.length?this.content[0].isInline:e.parentNode&&!VK.hasOwnProperty(e.parentNode.nodeName.toLowerCase())}},JK=class{constructor(e,t,n){this.parser=e,this.options=t,this.isOpen=n,this.open=0,this.localPreserveWS=!1;let r=t.topNode,i,a=KK(null,t.preserveWhitespace,0)|(n?GK:0);i=r?new qK(r.type,r.attrs,lK.none,!0,t.topMatch||r.type.contentMatch,a):n?new qK(null,null,lK.none,!0,null,a):new qK(e.schema.topNodeType,null,lK.none,!0,null,a),this.nodes=[i],this.find=t.findPositions,this.needsBlock=!1}get top(){return this.nodes[this.open]}addDOM(e,t){e.nodeType==3?this.addTextNode(e,t):e.nodeType==1&&this.addElement(e,t)}addTextNode(e,t){let n=e.nodeValue,r=this.top,i=r.options&WK?`full`:this.localPreserveWS||(r.options&UK)>0,{schema:a}=this.parser;if(i===`full`||r.inlineContext(e)||/[^ \t\r\n\u000c]/.test(n)){if(!i){if(n=n.replace(/[ \t\r\n\u000c]+/g,` `),/^[ \t\r\n\u000c]/.test(n)&&this.open==this.nodes.length-1){let t=r.content[r.content.length-1],i=e.previousSibling;(!t||i&&i.nodeName==`BR`||t.isText&&/[ \t\r\n\u000c]$/.test(t.text))&&(n=n.slice(1))}}else if(i===`full`)n=n.replace(/\r\n?/g,` diff --git a/static/index.html b/static/index.html index b8789cc56..b9c7dfac9 100644 --- a/static/index.html +++ b/static/index.html @@ -26,7 +26,7 @@ - + From 6fb6b845e79be768d335ecfba5798f42d8083f80 Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 5 Aug 2026 11:04:59 +0200 Subject: [PATCH 3/4] Read the printer's own slot mapping when Spoolman has none (#2768) A sliced file numbers its filaments 1..4; which AMS tray each came from is a separate decision made when the job is sent. store_print_data learns it from one of two sources, both of which require the print command to pass through us: the mapping Bambuddy chose itself, or the one it intercepted on the printer's local request topic. A job dispatched from Bambu Studio while the printer is cloud-bound satisfies neither -- the command travels through Bambu's broker and never reaches the topic we subscribe to. slot_to_tray is then NULL and _resolve_global_tray_id guesses by position: filament 1 from the first loaded tray, filament 2 from the second. The reporter's X1C was loaded in the order 2, 4, 1, AMS-HT, so all four slots were charged to the wrong spool. Their log carries the printer's own answer, mapping=[1, 3, 0, 32768], sitting unread. usage_tracker has consulted that field since it started resolving mappings at completion, along with a colour match against the loaded trays for the models that never publish it (A1, A1 Mini, P1S, P2S). Only the Spoolman writer, which resolves at print start, never learned to -- and main.py gates usage_tracker behind Spoolman being off, so enabling Spoolman is what costs you the better resolver. _resolve_slot_to_tray_fallback gives it both, at completion rather than at print start: a printer keeps publishing the last job's mapping while it sits idle, so reading it early would risk stamping the previous print's mapping onto this one. A mapping we or the slicer actually recorded is never second-guessed. Applied in _report_partial_usage too. Cancelled and failed prints feed the same slot_to_tray to the same resolver and mis-charged just as readily. The resolved mapping and its source are now logged at print start and at completion. "source: none" at start is the signal that completion will have to fall back, and it was the one line that would have turned this report into a five-minute triage. Not addressed: editing the mapping after the fact, which the reporter also asked for. ArchiveUpdate exposes neither filament field and there is no way to re-run an attribution, so that is a feature rather than a fix. --- CHANGELOG.md | 1 + backend/app/services/spoolman_tracking.py | 96 ++++++- .../test_spoolman_slot_mapping_fallback.py | 243 ++++++++++++++++++ 3 files changed, 338 insertions(+), 2 deletions(-) create mode 100644 backend/tests/unit/services/test_spoolman_slot_mapping_fallback.py diff --git a/CHANGELOG.md b/CHANGELOG.md index bcfe40548..fdf941264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to Bambuddy will be documented in this file. - **Error and warning toasts now stay up twice as long** — Every pop-up notification disappeared after three seconds regardless of what it said. That is about right for "Settings saved", which confirms something you just did and is skimmed rather than read, but errors and warnings are a different kind of message: they carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not long enough to finish reading one, and a missed error message is gone for good — there is no notification history to go back to. Errors and warnings now hold for six seconds. Success and informational toasts keep the three-second default, so the common case of clicking something and seeing it confirmed is unchanged, and the close button and the manual dismiss work exactly as before on all of them. The background print-dispatch toast is unaffected: it stays up while it has work in progress and clears itself shortly after the last job settles. Covered by frontend tests. ### Fixed +- **Spoolman no longer charges a Bambu Studio print to the wrong spool (#2768)** — A sliced file numbers its filaments 1, 2, 3, 4, and which AMS tray each of those came from is a separate decision made when the job is sent. Bambuddy learns that decision one of two ways: it made the choice itself, for a print started from Bambuddy, or it read the print command as it crossed the local network, for a print sent from a slicer. A job dispatched from Bambu Studio while the printer is signed in to Bambu's cloud satisfies neither — the command travels through Bambu's own broker and never appears on the network Bambuddy is listening to. With nothing recorded, the Spoolman writer fell back to assuming the AMS was loaded in slicer order: filament 1 from the first loaded tray, filament 2 from the second. The reporter's X1C was loaded in the order 2, 4, 1, AMS-HT, so every one of the four was deducted from the wrong spool. It also changed what the print looked like afterwards: on completion Bambuddy stamps the archive with the material and colour of the spools it charged, so the print showed the right filament while it ran and switched to a different one the moment it finished — which is how the reporter noticed. The printer knew the answer all along. It publishes the running job's slot-to-tray assignment in its own status, and Bambuddy's built-in filament inventory has read that field for as long as it has resolved mappings at completion; only the Spoolman writer, which resolves at print start instead, never learned to. It now consults the same two fallbacks at the same moment: the printer's report first, and failing that a colour match of the sliced filaments against the loaded trays, which covers the A1, A1 Mini, P1S and P2S — those models publish no such field, so their owners were on the positional guess no matter how the print was sent. Reading the field at completion rather than at print start is deliberate: a printer keeps publishing the last job's mapping while it sits idle, so consulting it early risks stamping the previous print's mapping onto this one. A mapping Bambuddy or the slicer actually recorded is never second-guessed, so nothing changes for prints started from Bambuddy, from the queue, or over LAN. Cancelled and failed prints take the same correction, since partial usage is charged through the same mapping. The resolved mapping and where it came from are now logged at both print start and completion, so the next report of a wrong deduction can be read straight out of a support bundle. Wiki updated. Covered by backend tests. - **A drying cycle no longer reports itself finished a minute after it starts (#2759)** — Starting the dryer on an AMS 2 Pro holding two PETG and two PLA spools and picking PLA showed "PLA @ 45°C" for about a minute, then switched to "PETG @ 65°C" for the remaining twelve hours. Bambu never echoes back which filament or temperature a cycle is running, so the badge reads the target Bambuddy cached when it sent the command — and that cache had been thrown away. Between accepting the command and settling its countdown the firmware publishes one update with the remaining time at zero while the unit is still in its Checking phase; the reporter's log caught 720 minutes, then 0, then 719. Bambuddy read the zero as the cycle ending. Losing the cached target left the badge to guess the filament from the first loaded slot, which happened to be PETG, and its RFID-recommended 65°C — a confident wrong answer for a cycle running PLA at 45. The same false ending also armed smart-plug auto-off-after-drying, so anyone with that switched on had power scheduled to cut one minute into a twelve-hour dry. A remaining time of zero is now only treated as the end of a cycle when the AMS also reports an idle phase, which the firmware already publishes alongside it; stopping a dry early still ends it immediately, and a unit that reports no phase at all still ends its cycles as before. The fallback guess has been tightened to match, in both directions. It names a filament only when every loaded spool agrees on one — on a mixed unit the badge shows the countdown alone rather than naming a spool the cycle isn't drying — and it no longer guesses a temperature at all. A unit loaded entirely with PLA does tell you what is being dried, but not at what temperature: that is picked freely when the cycle is started, so the spools' RFID-recommended value is never evidence of it, and a second AMS loaded only with PLA and drying at 45°C still read "PLA @ 55°C" whenever the cached target went missing. The badge now names a temperature only when Bambuddy sent it, and shows the filament and countdown without one otherwise. Covered by backend and frontend tests. - **A print that never starts now says AMS drying was running, instead of blaming the SD card (#2758)** — Sending a job to an X2D with two AMS units mid-drying failed silently: the file uploaded, the printer accepted it and then simply stayed idle. Bambuddy waited out the start watchdog, re-uploaded the whole 3MF, waited again, and after three attempts gave up with advice to check the printer's screen and the SD card — while Bambu Studio, asked directly, said it could not start the job because of the drying. Bambuddy now watches the AMS drying telemetry it already receives across the dispatch window and, when a job never starts while a unit was drying, names the units in the failure message and records the correlation in the log from the first attempt rather than only after the retries are spent. This is deliberately a diagnosis and not a rule: the printers concerned support drying *continuing* through a print, so drying and printing are not in conflict as such, and the report also involved one AMS drying without its external power supply — which would make the start-of-print calibration a power problem rather than a drying one. Stopping the cycle automatically would therefore be acting on a guess, and could tear down drying the hardware was happy to continue. Until it is known which of the two is the real obstacle, Bambuddy tells you what it saw and leaves the call to you. The message for a stalled dispatch with no drying involved is unchanged. Wiki updated. Covered by backend tests. - **A hand-written systemd service left the Virtual Printer unable to start, with nothing obvious to blame (#2549, reporter @Ru3ck3)** — The Virtual Printer binds ports 990 and 322, both below 1024, which a service running as a normal user may not do without the `CAP_NET_BIND_SERVICE` capability. Without it the rest of Bambuddy works perfectly and only the Virtual Printer is dead: its sockets never open, the slicer never finds the printer, and the sole trace is one line in the journal. The reporter lost days to this before someone on Discord spotted the missing line. The install script has carried it since March, but the three other places that define the same service did not — the manual-install template, the combined Bambuddy plus SpoolBuddy installer, and the unit the wiki tells you to paste. All three have it now, and the wiki no longer claims the capability is always included when its own instructions omitted it. Bambuddy also diagnoses this itself: **Diagnose** on the virtual printer card previously reported only that nothing was listening on port 990, which reads identically to an ordinary port conflict. It now checks whether the process actually holds the capability and, when that is what is wrong, says so and gives the line to add. The check stays quiet when the port is answering, since fronting it another way (an iptables redirect is the documented alternative) is a legitimate setup, and it stays quiet when the capability is held, so a port that failed for some other reason is not misattributed. Existing installs are unaffected until reinstalled; the diagnostic tells you whether yours needs the line. Translated in all locales; wiki updated. Covered by backend tests. diff --git a/backend/app/services/spoolman_tracking.py b/backend/app/services/spoolman_tracking.py index 714654f9d..af5a328a5 100644 --- a/backend/app/services/spoolman_tracking.py +++ b/backend/app/services/spoolman_tracking.py @@ -150,6 +150,62 @@ def _resolve_global_tray_id(slot_id: int, slot_to_tray: list | None, ams_trays: return slot_id - 1 +def _resolve_slot_to_tray_fallback(printer_id: int, filament_usage: list[dict]) -> tuple[list[int] | None, str]: + """Recover a slot-to-tray mapping at completion when print start captured none. + + ``store_print_data`` can only learn the mapping from two sources: the + ``ams_mapping`` Bambuddy intercepts on the printer's local request topic, and + a queue item's stored mapping. Neither exists for a print dispatched from + Bambu Studio while the printer is cloud-bound — the command travels through + Bambu's broker and never appears on the local topic we subscribe to. With + ``slot_to_tray`` left NULL, ``_resolve_global_tray_id`` guesses by position: + slicer slot 1 to the first loaded tray, slot 2 to the second, and so on. An + AMS that isn't loaded in slicer order then charges every slot to the wrong + spool, and the archive's filament is rewritten to match, so the print + silently changes colour when it finishes (#2768). + + The printer knows the real answer. Its ``mapping`` field carries the actual + slot-to-tray assignment for the running job, and for the models that never + publish it (A1, P1S, P2S) the 3MF's per-slot colours can be matched against + the loaded trays instead. The built-in inventory writer has consulted both + for as long as it has resolved mappings at completion; this gives the + Spoolman writer the same two fallbacks at the same moment. + + Deliberately at completion rather than inside ``store_print_data``: the + printer keeps publishing ``mapping`` long after a job ends — it is still in + the status payload while the printer sits idle — so reading it at print start + risks stamping the *previous* job's mapping onto this one before the printer + has pushed the update. At completion the field unambiguously describes the + job that just ran. + + Args: + printer_id: Printer whose live state is consulted. + filament_usage: The 3MF's per-slot estimates, needed by the colour + match. Only the ``slot_id``/``color`` keys are read. + + Returns: + ``(mapping, source)``, or ``(None, "none")`` when neither fallback + produced anything and the positional default stands. + """ + from backend.app.services.printer_manager import printer_manager + from backend.app.services.usage_tracker import _decode_mqtt_mapping, _match_slots_by_color + + state = printer_manager.get_status(printer_id) + raw_data = getattr(state, "raw_data", None) if state else None + if not raw_data: + return None, "none" + + decoded = _decode_mqtt_mapping(raw_data.get("mapping")) + if decoded: + return decoded, "mqtt" + + matched = _match_slots_by_color(filament_usage, raw_data.get("ams")) + if matched: + return matched, "color_match" + + return None, "none" + + def build_ams_tray_lookup(raw_data: dict) -> dict[int, dict]: """Build lookup of global_tray_id -> tray info from printer state. @@ -327,9 +383,11 @@ async def store_print_data( # Prefer the explicit mapping captured from the print command, then fall back # to any queue mapping stored for scheduled/reprint jobs. slot_to_tray = ams_mapping if ams_mapping is not None else None + mapping_source = "print_cmd" if slot_to_tray else None if not slot_to_tray and queue_item and queue_item.ams_mapping: try: slot_to_tray = json.loads(queue_item.ams_mapping) + mapping_source = "queue" except json.JSONDecodeError: pass # Ignore malformed AMS mapping; fall back to default slot assignment @@ -364,8 +422,15 @@ async def store_print_data( ) logger.debug("[SPOOLMAN] Filament usage: %s", filament_usage) logger.debug("[SPOOLMAN] AMS trays: %s", list(ams_trays.keys())) - if slot_to_tray: - logger.debug("[SPOOLMAN] Custom slot mapping: %s", slot_to_tray) + # Logged at info even when there is no mapping: "source: none" here is the + # signal that completion will have to fall back, which is the single most + # useful line in the log when a print is charged to the wrong spool (#2768). + logger.info( + "[SPOOLMAN] Print start: archive %s slot_to_tray=%s (source: %s)", + archive_id, + slot_to_tray, + mapping_source or "none", + ) if layer_usage_json: logger.debug("[SPOOLMAN] Layer usage data available for partial tracking") @@ -819,6 +884,19 @@ async def _report_partial_usage( ) return + # Same recovery the completion path does, for the same reason: a print + # dispatched from Studio over the cloud left print start with no mapping to + # store, and both paths below feed ``slot_to_tray`` to + # ``_resolve_global_tray_id`` (#2768). An aborted print charges the wrong + # spool just as readily as a finished one. + if not slot_to_tray: + slot_to_tray, _partial_mapping_source = _resolve_slot_to_tray_fallback(printer_id, filament_usage) + logger.info( + "[SPOOLMAN] Partial usage: slot_to_tray=%s (source: %s)", + slot_to_tray, + _partial_mapping_source, + ) + # Try to use accurate G-code parsed data if layer_usage: layer_usage_int = { @@ -1000,6 +1078,20 @@ async def report_usage(printer_id: int, archive_id: int): # is the print's last valid layer. _layer_denom_hint = _total_layers or _current_layer + # Recover the mapping when print start had nothing to store — the + # cloud-dispatched Studio print of #2768. Only the 3MF path consumes + # ``slot_to_tray``; the remain-delta path below resolves spools from the + # AMS slot directly, so there is nothing to recover for it. + mapping_source = "stored" if slot_to_tray else "none" + if filament_usage and not slot_to_tray: + slot_to_tray, mapping_source = _resolve_slot_to_tray_fallback(printer_id, filament_usage) + logger.info( + "[SPOOLMAN] Archive %s: slot_to_tray=%s (source: %s)", + archive_id, + slot_to_tray, + mapping_source, + ) + slot_colors: dict[int, str] = {} slot_materials: dict[int, str] = {} handled_global_tray_ids: set[int] = set() diff --git a/backend/tests/unit/services/test_spoolman_slot_mapping_fallback.py b/backend/tests/unit/services/test_spoolman_slot_mapping_fallback.py new file mode 100644 index 000000000..e4723e540 --- /dev/null +++ b/backend/tests/unit/services/test_spoolman_slot_mapping_fallback.py @@ -0,0 +1,243 @@ +"""Slot-to-tray mapping fallbacks on the Spoolman path (#2768). + +Bambuddy only learns a print's slot-to-tray mapping at print start when it can +intercept the command on the printer's local MQTT request topic, or when the +print came from its own queue. A print dispatched from Bambu Studio while the +printer is cloud-bound satisfies neither: the command travels through Bambu's +broker, so ``ActivePrintSpoolman.slot_to_tray`` is NULL and every slot falls +through to a positional guess (slicer slot 1 to the first loaded tray, and so +on). The reporter's X1C was loaded out of slicer order, so all four slots were +charged to the wrong spool and the archive's filament was rewritten to match. + +The internal-inventory writer never had this problem because it resolves the +mapping at completion, where it can read the printer's own ``mapping`` field or +colour-match the 3MF slots against the loaded trays. These tests cover giving +the Spoolman writer the same two fallbacks. +""" + +from types import SimpleNamespace +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest + +from backend.app.services.spoolman_tracking import _resolve_slot_to_tray_fallback + + +class _AsyncCtx: + """Minimal async context manager yielding a stub db session.""" + + def __init__(self, db): + self._db = db + + async def __aenter__(self): + return self._db + + async def __aexit__(self, *exc): + return False + + +def _state(**raw): + return SimpleNamespace(raw_data=raw, layer_num=0, total_layers=0, tray_change_log=[]) + + +def _patched_pm(state): + pm = MagicMock() + pm.get_status.return_value = state + return pm + + +class TestResolveSlotToTrayFallback: + def test_decodes_the_printers_own_mapping_field(self): + """The reporter's X1C published mapping=[1, 3, 0, 32768] while their + AMS was loaded out of slicer order. Snow-encoded, that is AMS 0 slot 2, + AMS 0 slot 4, AMS 0 slot 1, and the AMS-HT — nothing like the + positional [0, 1, 2, 3] the fallback-free path assumed.""" + pm = _patched_pm(_state(mapping=[1, 3, 0, 32768])) + + with patch("backend.app.services.printer_manager.printer_manager", pm): + mapping, source = _resolve_slot_to_tray_fallback(1, [{"slot_id": 1, "color": "#FF0000"}]) + + assert mapping == [1, 3, 0, 128] + assert source == "mqtt" + + def test_colour_matches_when_the_printer_publishes_no_mapping(self): + """A1/P1S/P2S never publish the mapping field. The 3MF's per-slot + colours still identify the trays when each one is unambiguous.""" + pm = _patched_pm( + _state( + ams=[ + { + "id": 0, + "tray": [ + {"id": 0, "tray_color": "00FF00FF", "tray_type": "PLA"}, + {"id": 1, "tray_color": "FF0000FF", "tray_type": "PLA"}, + ], + } + ] + ) + ) + usage = [{"slot_id": 1, "color": "#FF0000"}, {"slot_id": 2, "color": "#00FF00"}] + + with patch("backend.app.services.printer_manager.printer_manager", pm): + mapping, source = _resolve_slot_to_tray_fallback(1, usage) + + assert mapping == [1, 0] + assert source == "color_match" + + def test_mapping_field_wins_over_colour_matching(self): + """The printer's own field is direct evidence; colour matching is + inference. When both are available the field decides.""" + pm = _patched_pm( + _state( + mapping=[3], + ams=[{"id": 0, "tray": [{"id": 0, "tray_color": "FF0000FF", "tray_type": "PLA"}]}], + ) + ) + + with patch("backend.app.services.printer_manager.printer_manager", pm): + mapping, source = _resolve_slot_to_tray_fallback(1, [{"slot_id": 1, "color": "#FF0000"}]) + + assert mapping == [3] + assert source == "mqtt" + + def test_reports_none_when_neither_fallback_answers(self): + """Ambiguous colours and no mapping field: say so rather than invent + one. The caller keeps the positional default, which is no worse than + before, and the log names the reason.""" + pm = _patched_pm( + _state( + ams=[ + { + "id": 0, + "tray": [ + {"id": 0, "tray_color": "FF0000FF", "tray_type": "PLA"}, + {"id": 1, "tray_color": "FF0000FF", "tray_type": "PLA"}, + ], + } + ] + ) + ) + + with patch("backend.app.services.printer_manager.printer_manager", pm): + mapping, source = _resolve_slot_to_tray_fallback(1, [{"slot_id": 1, "color": "#FF0000"}]) + + assert mapping is None + assert source == "none" + + def test_reports_none_when_the_printer_is_offline(self): + """No live state at completion — the printer dropped off after the + print. Nothing to read, and no crash.""" + with patch("backend.app.services.printer_manager.printer_manager", _patched_pm(None)): + mapping, source = _resolve_slot_to_tray_fallback(1, [{"slot_id": 1, "color": "#FF0000"}]) + + assert mapping is None + assert source == "none" + + +class TestReportUsageUsesTheFallback: + """End-to-end through report_usage: the fallback has to reach + ``_resolve_global_tray_id`` and change which spool is charged.""" + + @staticmethod + def _run(tracking, state, spool_by_tag, archive): + # The first SELECT fetches the tracking row; every later one fetches the + # archive for the colour / type rewrites (#1494, #2563). + rows = iter([tracking]) + + def _next_row(*_args, **_kwargs): + result = MagicMock() + result.scalar_one_or_none.return_value = next(rows, archive) + return result + + db = AsyncMock() + db.execute = AsyncMock(side_effect=_next_row) + db.delete = AsyncMock() + db.commit = AsyncMock() + + client = AsyncMock() + client.find_spool_by_tag = AsyncMock(side_effect=lambda tag: spool_by_tag.get(tag)) + client.use_spool = AsyncMock() + + pm = _patched_pm(state) + + async def _go(): + from backend.app.services.spoolman_tracking import report_usage + + with ( + patch("backend.app.services.spoolman_tracking.async_session", lambda: _AsyncCtx(db)), + patch("backend.app.api.routes.settings.get_setting", AsyncMock(return_value="true")), + patch( + "backend.app.services.spoolman_tracking._get_spoolman_client_with_fallback", + AsyncMock(return_value=client), + ), + patch("backend.app.services.spoolman_tracking._get_printer_serial", AsyncMock(return_value="SER")), + patch( + "backend.app.services.spoolman_tracking._resolve_spool_id_via_slot_assignment", + AsyncMock(return_value=None), + ), + patch("backend.app.services.printer_manager.printer_manager", pm), + ): + await report_usage(printer_id=1, archive_id=42) + + return _go, client + + @pytest.mark.asyncio + async def test_mqtt_mapping_charges_the_tray_the_printer_named(self): + """One-slot print whose filament actually came from AMS slot 4 + (global tray 3). With no stored mapping the positional default charges + global tray 0 — the wrong spool, and the archive is then rewritten to + that spool's colour. The printer's mapping field says otherwise.""" + tracking = SimpleNamespace( + filament_usage=[{"slot_id": 1, "used_g": 25.0, "type": "PLA", "color": "#FF0000"}], + ams_trays={ + "0": {"tray_uuid": "TRAY0UUID", "tag_uid": "", "tray_type": "PLA"}, + "3": {"tray_uuid": "TRAY3UUID", "tag_uid": "", "tray_type": "PLA"}, + }, + slot_to_tray=None, + tray_remain_start=None, + layer_usage=None, + filament_properties=None, + ) + state = _state(mapping=[3]) + spools = { + "TRAY0UUID": {"id": 100, "filament": {"color_hex": "FFFFFF", "material": "PLA"}}, + "TRAY3UUID": {"id": 300, "filament": {"color_hex": "FF0000", "material": "PLA"}}, + } + archive = SimpleNamespace(filament_color="#FF0000", filament_type="PLA") + + run, client = self._run(tracking, state, spools, archive) + await run() + + client.use_spool.assert_awaited_once_with(300, 25.0) + # And the visible half of the bug: the archive keeps the red it was + # printed in instead of being rewritten to the wrong spool's white. + assert archive.filament_color == "#FF0000" + + @pytest.mark.asyncio + async def test_a_stored_mapping_is_never_second_guessed(self): + """Print start captured the real ams_mapping (LAN print, or a Bambuddy + queue job). That is the slicer's own instruction and outranks anything + read back off the printer, whose mapping field may still describe an + earlier job.""" + tracking = SimpleNamespace( + filament_usage=[{"slot_id": 1, "used_g": 25.0, "type": "PLA", "color": "#FF0000"}], + ams_trays={ + "0": {"tray_uuid": "TRAY0UUID", "tag_uid": "", "tray_type": "PLA"}, + "3": {"tray_uuid": "TRAY3UUID", "tag_uid": "", "tray_type": "PLA"}, + }, + slot_to_tray=[0], + tray_remain_start=None, + layer_usage=None, + filament_properties=None, + ) + state = _state(mapping=[3]) + spools = { + "TRAY0UUID": {"id": 100, "filament": {"color_hex": "FFFFFF", "material": "PLA"}}, + "TRAY3UUID": {"id": 300, "filament": {"color_hex": "FF0000", "material": "PLA"}}, + } + archive = SimpleNamespace(filament_color="#FF0000", filament_type="PLA") + + run, client = self._run(tracking, state, spools, archive) + await run() + + client.use_spool.assert_awaited_once_with(100, 25.0) From 5efbd353ed54e572e8ec51c8b57a7622c939df02 Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 5 Aug 2026 11:14:57 +0200 Subject: [PATCH 4/4] Survive a directory that defines no posixGroup class (#2769) Every LDAP user on an lldap directory was rejected with "Incorrect username or password", on an install where Test Connection passed and where the same bind DN, filter and group membership all checked out under ldapsearch. The directory never saw the request. _extract_user_info searches for POSIX groups alongside the memberOf ones, and both of those filters name the posixGroup object class. ldap3 fetches the schema at connect time (get_info=ALL) and validates class names in a filter against it while building the request, raising LDAPObjectClassError before anything is sent. lldap marks every account it creates as posixAccount -- which is what makes us look for POSIX groups at all -- but defines no group class beyond groupOfNames. The exception escaped authenticate_ldap_user, and the login route reports any LDAP failure as bad credentials. A directory with no posixGroup class has no posixGroup entries, which is exactly the answer those searches would have returned. Catch it, log it once, and carry on with the memberOf groups collected above. Both searches sit inside the one try: they name the same class, so once one is rejected the other cannot succeed, and attempting it would only produce a second identical exception to swallow. Not a regression from 848f55810. The memberUid filter has named the class since b6599dd41 and runs for every user whether or not they have a gidNumber, so a directory of this shape has never been able to log in; the primary-group lookup only added a second trigger. Test Connection was unaffected throughout because (objectClass=*) is a presence filter and never reaches the value validator. The mock connection gained a hook that raises on a filter substring, standing in for that client-side validation. Reset in the fixture and default None, so existing tests are unchanged. --- CHANGELOG.md | 1 + backend/app/services/ldap_service.py | 60 +++++++++---- .../tests/unit/services/test_ldap_service.py | 88 +++++++++++++++++++ 3 files changed, 131 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdf941264..7a66cbfc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to Bambuddy will be documented in this file. - **Error and warning toasts now stay up twice as long** — Every pop-up notification disappeared after three seconds regardless of what it said. That is about right for "Settings saved", which confirms something you just did and is skimmed rather than read, but errors and warnings are a different kind of message: they carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not long enough to finish reading one, and a missed error message is gone for good — there is no notification history to go back to. Errors and warnings now hold for six seconds. Success and informational toasts keep the three-second default, so the common case of clicking something and seeing it confirmed is unchanged, and the close button and the manual dismiss work exactly as before on all of them. The background print-dispatch toast is unaffected: it stays up while it has work in progress and clears itself shortly after the last job settles. Covered by frontend tests. ### Fixed +- **LDAP login works again on directories that define no POSIX group class (#2769, reporter @peterskotte)** — Every LDAP user on an lldap directory was rejected with "Incorrect username or password", including users whose credentials, search filter and group membership all checked out when tested by hand with `ldapsearch`, and on an install where **Test Connection** reported success. The password was never the problem and the directory never saw the request. When resolving a user's groups Bambuddy looks for POSIX groups alongside the usual `memberOf` ones, and both of those searches name the `posixGroup` object class. The LDAP client validates class names in a filter against the schema the server publishes, and rejects an unknown one while building the request, before anything is sent. lldap marks every account it creates as `posixAccount`, which is what makes Bambuddy look for POSIX groups in the first place, but defines no group class beyond `groupOfNames` — so the search was refused, the refusal travelled all the way out of the login routine, and the login route reports any LDAP failure as bad credentials. A directory with no `posixGroup` class has no `posixGroup` entries, which is precisely the answer those searches would have returned, so Bambuddy now treats the refusal as the empty result it stands for, notes it once in the log and carries on with the `memberOf` groups. The reporter's mapped group is one of those, so it resolves as configured. This is not a regression from the recent primary-group work, though that is the natural suspect: the `memberUid` search has named the same class since LDAP support first shipped, and it runs for every user whether or not they have a `gidNumber`, so login has never worked against a directory of this shape. **Test Connection** passed throughout because it asks only whether any entry exists, a form of filter that carries no class name to validate. Nothing changes for Active Directory or for an OpenLDAP that loads the standard NIS schema — both define the class, and their POSIX groups are still read. Wiki updated. Covered by backend tests. - **Spoolman no longer charges a Bambu Studio print to the wrong spool (#2768)** — A sliced file numbers its filaments 1, 2, 3, 4, and which AMS tray each of those came from is a separate decision made when the job is sent. Bambuddy learns that decision one of two ways: it made the choice itself, for a print started from Bambuddy, or it read the print command as it crossed the local network, for a print sent from a slicer. A job dispatched from Bambu Studio while the printer is signed in to Bambu's cloud satisfies neither — the command travels through Bambu's own broker and never appears on the network Bambuddy is listening to. With nothing recorded, the Spoolman writer fell back to assuming the AMS was loaded in slicer order: filament 1 from the first loaded tray, filament 2 from the second. The reporter's X1C was loaded in the order 2, 4, 1, AMS-HT, so every one of the four was deducted from the wrong spool. It also changed what the print looked like afterwards: on completion Bambuddy stamps the archive with the material and colour of the spools it charged, so the print showed the right filament while it ran and switched to a different one the moment it finished — which is how the reporter noticed. The printer knew the answer all along. It publishes the running job's slot-to-tray assignment in its own status, and Bambuddy's built-in filament inventory has read that field for as long as it has resolved mappings at completion; only the Spoolman writer, which resolves at print start instead, never learned to. It now consults the same two fallbacks at the same moment: the printer's report first, and failing that a colour match of the sliced filaments against the loaded trays, which covers the A1, A1 Mini, P1S and P2S — those models publish no such field, so their owners were on the positional guess no matter how the print was sent. Reading the field at completion rather than at print start is deliberate: a printer keeps publishing the last job's mapping while it sits idle, so consulting it early risks stamping the previous print's mapping onto this one. A mapping Bambuddy or the slicer actually recorded is never second-guessed, so nothing changes for prints started from Bambuddy, from the queue, or over LAN. Cancelled and failed prints take the same correction, since partial usage is charged through the same mapping. The resolved mapping and where it came from are now logged at both print start and completion, so the next report of a wrong deduction can be read straight out of a support bundle. Wiki updated. Covered by backend tests. - **A drying cycle no longer reports itself finished a minute after it starts (#2759)** — Starting the dryer on an AMS 2 Pro holding two PETG and two PLA spools and picking PLA showed "PLA @ 45°C" for about a minute, then switched to "PETG @ 65°C" for the remaining twelve hours. Bambu never echoes back which filament or temperature a cycle is running, so the badge reads the target Bambuddy cached when it sent the command — and that cache had been thrown away. Between accepting the command and settling its countdown the firmware publishes one update with the remaining time at zero while the unit is still in its Checking phase; the reporter's log caught 720 minutes, then 0, then 719. Bambuddy read the zero as the cycle ending. Losing the cached target left the badge to guess the filament from the first loaded slot, which happened to be PETG, and its RFID-recommended 65°C — a confident wrong answer for a cycle running PLA at 45. The same false ending also armed smart-plug auto-off-after-drying, so anyone with that switched on had power scheduled to cut one minute into a twelve-hour dry. A remaining time of zero is now only treated as the end of a cycle when the AMS also reports an idle phase, which the firmware already publishes alongside it; stopping a dry early still ends it immediately, and a unit that reports no phase at all still ends its cycles as before. The fallback guess has been tightened to match, in both directions. It names a filament only when every loaded spool agrees on one — on a mixed unit the badge shows the countdown alone rather than naming a spool the cycle isn't drying — and it no longer guesses a temperature at all. A unit loaded entirely with PLA does tell you what is being dried, but not at what temperature: that is picked freely when the cycle is started, so the spools' RFID-recommended value is never evidence of it, and a second AMS loaded only with PLA and drying at 45°C still read "PLA @ 55°C" whenever the cached target went missing. The badge now names a temperature only when Bambuddy sent it, and shows the filament and countdown without one otherwise. Covered by backend and frontend tests. - **A print that never starts now says AMS drying was running, instead of blaming the SD card (#2758)** — Sending a job to an X2D with two AMS units mid-drying failed silently: the file uploaded, the printer accepted it and then simply stayed idle. Bambuddy waited out the start watchdog, re-uploaded the whole 3MF, waited again, and after three attempts gave up with advice to check the printer's screen and the SD card — while Bambu Studio, asked directly, said it could not start the job because of the drying. Bambuddy now watches the AMS drying telemetry it already receives across the dispatch window and, when a job never starts while a unit was drying, names the units in the failure message and records the correlation in the log from the first attempt rather than only after the retries are spent. This is deliberately a diagnosis and not a rule: the printers concerned support drying *continuing* through a print, so drying and printing are not in conflict as such, and the report also involved one AMS drying without its external power supply — which would make the start-of-print calibration a power problem rather than a drying one. Stopping the cycle automatically would therefore be acting on a guess, and could tear down drying the hardware was happy to continue. Until it is known which of the two is the real obstacle, Bambuddy tells you what it saw and leaves the call to you. The message for a stalled dispatch with no drying involved is unchanged. Wiki updated. Covered by backend tests. diff --git a/backend/app/services/ldap_service.py b/backend/app/services/ldap_service.py index 8f45fef84..710338c36 100644 --- a/backend/app/services/ldap_service.py +++ b/backend/app/services/ldap_service.py @@ -14,6 +14,7 @@ import logging from dataclasses import dataclass from ldap3 import ALL, SUBTREE, Connection, Server, Tls +from ldap3.core.exceptions import LDAPObjectClassError logger = logging.getLogger(__name__) @@ -155,32 +156,55 @@ def _extract_user_info( canonical_username = _pick_canonical_username(user_entry, fallback_username) - # Also search for POSIX groups (memberUid-based) using the service account - posix_filter = f"(&(objectClass=posixGroup)(memberUid={_ldap_escape(canonical_username)}))" - service_conn.search( - search_base=config.search_base, - search_filter=posix_filter, - search_scope=SUBTREE, - attributes=["cn"], - ) - for entry in service_conn.entries: - groups.append(str(entry.entry_dn)) - - # POSIX primary group: user's gidNumber matches a posixGroup's gidNumber. - # Standard Unix semantics treat this as full group membership, so we need - # to resolve it to a group DN alongside the memberUid results. - if hasattr(user_entry, "gidNumber") and user_entry.gidNumber: - primary_gid = str(user_entry.gidNumber) - primary_filter = f"(&(objectClass=posixGroup)(gidNumber={_ldap_escape(primary_gid)}))" + # Also search for POSIX groups, both the memberUid kind and the primary + # gidNumber kind. Both filters name the posixGroup object class, and ldap3 + # validates that name against the schema it fetched at connect time + # (get_info=ALL) before it builds the request — so on a directory that + # publishes a schema without posixGroup it raises client-side and nothing is + # ever sent. A directory with no posixGroup class has no posixGroup entries, + # which is exactly the answer the searches would have returned, so the + # correct response is to carry on with the memberOf groups collected above. + # + # Left uncaught, that exception escaped authenticate_ldap_user, and the login + # route reports any LDAP error as "Incorrect username or password" — so an + # lldap user, whose accounts carry posixAccount but whose directory defines + # no group classes beyond groupOfNames, could never log in and had nothing + # but a wrong-password message to go on (#2769). This predates the primary + # gidNumber lookup: the memberUid filter has named the class since #794. + try: + posix_filter = f"(&(objectClass=posixGroup)(memberUid={_ldap_escape(canonical_username)}))" service_conn.search( search_base=config.search_base, - search_filter=primary_filter, + search_filter=posix_filter, search_scope=SUBTREE, attributes=["cn"], ) for entry in service_conn.entries: groups.append(str(entry.entry_dn)) + # POSIX primary group: user's gidNumber matches a posixGroup's gidNumber. + # Standard Unix semantics treat this as full group membership, so we need + # to resolve it to a group DN alongside the memberUid results. + if hasattr(user_entry, "gidNumber") and user_entry.gidNumber: + primary_gid = str(user_entry.gidNumber) + primary_filter = f"(&(objectClass=posixGroup)(gidNumber={_ldap_escape(primary_gid)}))" + service_conn.search( + search_base=config.search_base, + search_filter=primary_filter, + search_scope=SUBTREE, + attributes=["cn"], + ) + for entry in service_conn.entries: + groups.append(str(entry.entry_dn)) + except LDAPObjectClassError: + # Logged once per authentication, at info: it is the explanation for a + # user's POSIX groups being absent from their mapping, and it is not an + # error the operator can or should act on. + logger.info( + "Directory publishes no posixGroup object class; skipping POSIX group lookup " + "(memberOf groups are unaffected)" + ) + # Dedupe group DNs (user may be in a group via both memberUid and primary gidNumber). # Case-insensitive comparison — LDAP DNs are case-insensitive by spec. seen_lower: set[str] = set() diff --git a/backend/tests/unit/services/test_ldap_service.py b/backend/tests/unit/services/test_ldap_service.py index 33ad167a8..f6b85ee8e 100644 --- a/backend/tests/unit/services/test_ldap_service.py +++ b/backend/tests/unit/services/test_ldap_service.py @@ -11,6 +11,7 @@ are not tested here — they require a live LDAP server. """ import pytest +from ldap3.core.exceptions import LDAPObjectClassError from backend.app.services.ldap_service import ( LDAPConfig, @@ -297,6 +298,11 @@ class _MockConnection: _search_fixture: dict[str, list] = {} _instances: list["_MockConnection"] = [] + # Filter substring that should raise LDAPObjectClassError instead of + # searching, standing in for ldap3's client-side schema validation — it + # rejects an object class the server's published schema doesn't define + # before the request is ever built (#2769). + _raise_object_class_error_on: str | None = None def __init__(self, *args, **kwargs): self.entries: list = [] @@ -320,6 +326,9 @@ class _MockConnection: # **kwargs absorbs ldap3 options like size_limit that the real client supports self.search_calls.append(search_filter or "") self.last_attrs = list(attributes) if attributes is not None else None + needle = _MockConnection._raise_object_class_error_on + if needle and needle in (search_filter or ""): + raise LDAPObjectClassError(f"invalid class in objectClass attribute: {needle}") for needle, entries in _MockConnection._search_fixture.items(): if needle in (search_filter or ""): self.entries = entries @@ -333,6 +342,7 @@ def mock_ldap(monkeypatch): """Patch Connection + _create_server in ldap_service so authenticate_ldap_user can run offline.""" _MockConnection._search_fixture = {} _MockConnection._instances = [] + _MockConnection._raise_object_class_error_on = None monkeypatch.setattr("backend.app.services.ldap_service.Connection", _MockConnection) monkeypatch.setattr("backend.app.services.ldap_service._create_server", lambda config: None) return _MockConnection @@ -433,6 +443,84 @@ class TestAuthenticateLdapUserGroups: assert gidnumber_searches == [] +class TestDirectoryWithoutPosixGroupClass: + """A directory whose published schema defines no posixGroup class (#2769). + + ldap3 fetches the schema at connect time (get_info=ALL) and validates object + class names in a filter against it before building the request, so both POSIX + group searches raise client-side and nothing reaches the server. lldap is the + case in the wild: it puts posixAccount on every account it creates, which + gives each user a gidNumber, but defines no group class beyond groupOfNames. + Left uncaught the exception escaped authenticate_ldap_user and the login route + reported it as "Incorrect username or password", so LDAP login was impossible. + """ + + def test_authenticates_and_keeps_memberof_groups(self, mock_ldap): + """The reporter's setup: the mapped membership comes from memberOf, which + is read off the user entry and never touches a posixGroup filter.""" + user_entry = _MockEntry( + "uid=peter,ou=people,dc=fablab,dc=test", + uid="peter", + gidNumber=1001, # lldap gives every account one + memberOf=["cn=AAUStudents,ou=groups,dc=fablab,dc=test"], + ) + mock_ldap._search_fixture = {"(uid=peter)": [user_entry]} + mock_ldap._raise_object_class_error_on = "objectClass=posixGroup" + + info = authenticate_ldap_user(_base_config(), "peter", "password") + + assert info is not None + assert info.groups == ["cn=AAUStudents,ou=groups,dc=fablab,dc=test"] + + def test_authenticates_with_no_groups_at_all(self, mock_ldap): + """No memberOf either. The user still gets in — auto-provisioning assigns + the configured default group, which is the whole point of that setting.""" + user_entry = _MockEntry("uid=peter,ou=people,dc=fablab,dc=test", uid="peter", gidNumber=1001) + mock_ldap._search_fixture = {"(uid=peter)": [user_entry]} + mock_ldap._raise_object_class_error_on = "objectClass=posixGroup" + + info = authenticate_ldap_user(_base_config(), "peter", "password") + + assert info is not None + assert info.username == "peter" + assert info.groups == [] + + def test_abandons_the_primary_gid_search_after_the_first_rejection(self, mock_ldap): + """Both filters name the same class, so once one is rejected the other + cannot succeed. Attempting it would only produce a second identical + exception to swallow.""" + user_entry = _MockEntry("uid=peter,ou=people,dc=fablab,dc=test", uid="peter", gidNumber=1001) + mock_ldap._search_fixture = {"(uid=peter)": [user_entry]} + mock_ldap._raise_object_class_error_on = "objectClass=posixGroup" + + authenticate_ldap_user(_base_config(), "peter", "password") + + service_conn = _MockConnection._instances[0] + posix_searches = [call for call in service_conn.search_calls if "posixGroup" in call] + assert len(posix_searches) == 1 + assert "memberUid=peter" in posix_searches[0] + + def test_a_directory_that_defines_the_class_is_untouched(self, mock_ldap): + """The guard must not cost a normal directory its POSIX groups — both + searches still run and both results still land.""" + user_entry = _MockEntry("cn=mz,dc=test,dc=com", uid="mz", gidNumber=10002) + supplementary = _MockEntry("cn=bambuddy-viewers,ou=groups,dc=test,dc=com") + primary = _MockEntry("cn=bambuddy-operators,ou=groups,dc=test,dc=com") + + mock_ldap._search_fixture = { + "(uid=mz)": [user_entry], + "memberUid=mz": [supplementary], + "gidNumber=10002": [primary], + } + + info = authenticate_ldap_user(_base_config(), "mz", "password") + + assert info.groups == [ + "cn=bambuddy-viewers,ou=groups,dc=test,dc=com", + "cn=bambuddy-operators,ou=groups,dc=test,dc=com", + ] + + # --------------------------------------------------------------------------- # Manual provisioning helpers — search_ldap_users + lookup_ldap_user (#1298) # ---------------------------------------------------------------------------