From c2e7f8eb4b6c92eb88890ebcc2378d8ecf9ac7f8 Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 29 Apr 2026 06:54:08 +0200 Subject: [PATCH] feat(vp): add archive name source toggle (metadata/filename) (#1152) Slicer-uploaded archives picked up their display name from the 3MF's embedded print_name (the creator-baked title); users who renamed a job in BambuStudio's "Send to printer" dialog never saw that name surface because the FTP filename was only used as a fallback when metadata was empty. Settings -> Virtual Printer now exposes an Archive name source toggle (Metadata / Filename, default Metadata) that flips precedence in ArchiveService.archive_print via a new prefer_filename_for_name param. All four VP-sourced archive paths read the new virtual_printer_archive_name_source setting and forward the flag: _archive_file, _add_to_print_queue, POST /pending-uploads/archive-all, POST /pending-uploads/{id}/archive. --- CHANGELOG.md | 1 + backend/app/api/routes/pending_uploads.py | 8 + backend/app/api/routes/settings.py | 12 + backend/app/schemas/settings.py | 5 + backend/app/services/archive.py | 8 +- .../app/services/virtual_printer/manager.py | 8 + .../unit/services/test_virtual_printer.py | 95 ++++++- frontend/src/api/client.ts | 3 + .../src/components/VirtualPrinterList.tsx | 61 ++++- frontend/src/i18n/locales/de.ts | 6 + frontend/src/i18n/locales/en.ts | 6 + frontend/src/i18n/locales/zh-CN.ts | 6 + frontend/src/i18n/locales/zh-TW.ts | 6 + .../{index-bqAa7OcX.js => index-5P0GaR3D.js} | 244 +++++++++--------- static/index.html | 2 +- 15 files changed, 336 insertions(+), 135 deletions(-) rename static/assets/{index-bqAa7OcX.js => index-5P0GaR3D.js} (79%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d328405d6..2f7f3bcf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to Bambuddy will be documented in this file. ## [0.2.4b1] - Unreleased ### Added +- **Virtual-printer archive name source toggle** ([#1152](https://github.com/maziggy/bambuddy/issues/1152)) — Slicer-uploaded archives picked up their display name from the 3MF's embedded `print_name` metadata, which is whatever the original creator set; users who renamed a job in BambuStudio's "Send to printer" dialog never saw that name surface in Bambuddy because the FTP-uploaded filename was only ever used as a fallback when the metadata was empty. Settings → Virtual Printer now exposes an **Archive name source** toggle (Metadata / Filename, default Metadata, preserves existing behaviour) at the top of the page that flips precedence in `ArchiveService.archive_print` for every VP-sourced archive — `_archive_file`, `_add_to_print_queue`, `POST /pending-uploads/archive-all`, and `POST /pending-uploads/{id}/archive` all read the new `virtual_printer_archive_name_source` setting and forward `prefer_filename_for_name` accordingly. Backend validates the value to `metadata`/`filename` only. Strict locales (en/de/zh-CN/zh-TW) get full translations; 4 unit tests parametrised over `filename` / `metadata` / unset / empty-string pin the precedence rule end-to-end through `_archive_file`. Existing post-archive `PATCH /archives/{id}` rename path is unchanged. - **Multi-color slicing in the Slice modal, with per-plate filament discovery for unsliced project files** — Initial slice support assumed a single filament profile per slice; multi-color 3MFs were silently truncated to the first slot, producing wrong colours on every non-trivial print. The Slice modal now (1) opens a plate-picker step first when the source is a multi-plate 3MF, (2) renders one filament dropdown per AMS slot the picked plate actually uses, with each dropdown auto-populated against the user's local + standard presets by `(filament_type, filament_colour)` match, and (3) submits the user's picks as an ordered `filament_presets: PresetRef[]` array which is forwarded as repeated `filamentProfile` multipart parts to the slicer sidecar (the CLI joins them with `;` for `--load-filaments`). **Per-plate filament list source-of-truth chain**: for a sliced archive the modal reads `Metadata/slice_info.config` directly (existing path); for an unsliced project file (where `slice_info.config` is empty until Bambu Studio actually slices), the new `slice_preview` service runs a fast preview-slice via the sidecar's `slice_without_profiles` (the project's embedded settings drive the slice; we throw away the gcode and only parse the resulting slice_info), and the result is cached by `(kind, source_id, plate_id, content_hash)` with LRU eviction at 256 entries — repeat opens of the same plate are instant. If the sidecar isn't reachable the modal falls back to a heuristic that reads `Metadata/project_settings.config` for the AMS slot config and intersects it with the plate's painted-face data (`paint_color` quadtree leaves on per-object .model files, scanned with a 5% noise threshold to drop single-leaf edit accidents). **SliceModal-only tier priority is now `local → cloud → standard`** (was `cloud → local → standard`): imported profiles win because they carry parsed type/colour metadata in the response, while cloud entries don't (the per-preset detail endpoint rate-limits at ~10/sec per token and 50+ parallel fetches returned 429 on every request). The unified-listing endpoint's dedup pass now backfills metadata cross-tier — if a cloud entry wins dedup over a same-named local entry, the cloud entry inherits the local's `filament_type` / `filament_colour` so the Slice modal's metadata-aware pre-pick keeps working for users who have presets both cloud-synced and locally imported. Other consumers of `/slicer/presets` (Profiles page, etc.) retain the existing cloud-first dedup. **Sidecar** (orca-slicer-api fork, `bambuddy/profile-resolver` branch): `/slice` now accepts up to 16 repeated `filamentProfile` parts (was hard-capped at 1), the slicing service materializes each as `filament_N.json` and joins paths into a single `--load-filaments "a.json;b.json;c.json"` invocation; `/profiles/bundled` listing was extended with `filament_type` and `filament_colour` per leaf so the bundled tier carries metadata into the modal. **Sliced-archive card now reflects the actually-used filament list, not the project-wide AMS config**: `slice_and_persist_as_archive` previously copied `filament_type` and `filament_color` from the unsliced source archive verbatim, which inherited every project-wide AMS slot (16+ swatches on the card for a 2-color print). The new archive now reads those fields from the sliced output's `slice_info.config` via `ThreeMFParser` (which already gates on `used_g > 0`), falling back to the source archive's values only if parsing failed. **Backwards compatibility**: `SliceRequest` schema accepts three shapes — legacy `filament_preset_id: int`, source-aware singular `filament_preset: PresetRef`, multi-color array `filament_presets: list[PresetRef]` — the validator promotes any of them into a populated `filament_presets` list before the route handler runs, and stale browser tabs from before this change keep working unchanged. **Permissions**: no new endpoint paths added; the preview-slice runs inside `/filament-requirements` (gated on `LIBRARY_READ` / `ARCHIVES_READ`) and the multi-filament dispatch runs inside `POST /slice` (gated on `LIBRARY_UPLOAD`) — no auth surface widened. **Tests**: 6 schema tests for `SliceRequest` covering the multi-filament list shape and legacy-vs-new precedence; 9 unit tests for `slice_preview` covering happy path, content-hash invalidation, sidecar-failure no-cache-poison, concurrent-call thundering-herd guard via per-key `asyncio.Lock`, and LRU eviction-with-lock-cleanup; 15 unit tests for `extract_project_filaments_from_3mf` (5 cases) and `extract_plate_extruder_set_from_3mf` (10 cases including the 60/40 painted-threshold pin); a multi-filament wire-format test on `slice_with_profiles` pinning that N filament profiles produce N repeated multipart parts in submission order; 22 frontend SliceModal tests covering the plate picker step, multi-color rendering, metadata-aware pre-pick, manual slot override, archive-vs-library routing, and the new tier order. Localised across all 8 UI languages (English + German fully translated, the six others seeded with English copies pending native translation per the project's existing flow). - **Slicer presets now span Cloud, imported, and slicer-bundled tiers, end-to-end** — Initial slicer integration only saw DB-backed local imports, so a user without imported profiles got an empty Slice modal even when their Bambu Cloud account or the slicer sidecar carried perfectly usable presets. The Slice modal now pulls from three tiers in priority order — **cloud** (the user's own Bambu Cloud presets), **local** (DB-backed imports), **standard** (slicer-bundled stock profiles) — with name-based dedup so a preset that exists in multiple tiers only renders in the highest-priority one (cloud > local > standard) and within-tier order is preserved exactly. **Listing** (`GET /api/v1/slicer/presets`): cloud branch is per-user with a 5-minute cache keyed on `(user_id, sha256(token)[:16])` so a logout/login or token rotation auto-invalidates without callback wiring from the cloud-auth routes. Bundled branch is global with a 1-hour cache (sidecar's read-only filesystem only changes across image rebuilds). `cloud_status` (`ok` / `not_authenticated` / `expired` / `unreachable`) drives a precise modal banner instead of an unexplained empty list. **Slicing** (`POST /library/files/{id}/slice`, `POST /archives/{id}/slice`): request body now accepts source-aware `{source, id}` triplets per slot (cloud / local / standard) alongside the legacy `*_preset_id` fields for full backwards-compatibility — the schema validator normalises bare integer ids into `PresetRef(source='local', id=str(int))` so the dispatcher only deals with one shape. New `preset_resolver` service fetches the preset content per source: cloud via `BambuCloudService.get_setting_detail` (unwraps the `setting` envelope, falls back to top-level on minor shape variants), local from the DB (existing path), standard via a minimal `{inherits: , from: "system"}` stub that the sidecar's `bambuddy/profile-resolver` branch flattens against `BUNDLED_PROFILES_PATH//.json` — no preset-content round-trip needed for the standard tier. **Permissions**: the listing route gate matches the slice action itself (`LIBRARY_UPLOAD`) so any user who can slice can populate the dropdowns; the cloud branch has an independent `CLOUD_AUTH` check inside the fetch helper — a user holding `LIBRARY_UPLOAD` but not `CLOUD_AUTH` doesn't see the cloud tier (and can't slice with a cloud preset, returns 403) even if a leftover `User.cloud_token` survived a permission revocation. **SliceModal** (frontend): grouped `` per tier with localised section headers, default-selection follows the cloud > local > standard priority on first load, cloud-status banner with three variants (sign-in / expired / unreachable) only when the status isn't `ok`. **Sidecar** (orca-slicer-api fork, `bambuddy/profile-resolver` branch): new `GET /profiles/bundled` walks `BUNDLED_PROFILES_PATH/{machine,process,filament}` and returns instantiable presets only (`instantiation: "true"`), filtering out abstract bases like `fdm_filament_pla` so the dropdowns only offer things a user can actually pick. **Tests**: 17 unit tests for the listing endpoint helpers (dedup priority + per-slot scoping + order preservation, all four `cloud_status` states, `CLOUD_AUTH` defence-in-depth with token lookup short-circuit, per-user cache isolation, token-change cache invalidation, sidecar-unreachable fallback), 11 unit tests for the source-aware resolver (standard inherits-stub shape, local DB lookup with `preset_type` validation, cloud envelope unwrapping with both standard and top-level shapes, cloud auth-error → 401, cloud `CLOUD_AUTH` defence, slot dispatch routing), 6 schema tests for `SliceRequest` covering legacy bare-int normalisation and new source-aware refs and explicit-ref-wins-over-legacy precedence, 12 frontend tests for SliceModal covering tier-priority auto-selection, `` grouping, fallback when higher tiers are empty, source-aware payload on submit, manual override across tiers, archive-vs-library routing, error display, and all three banner variants. All 3391 backend + 1531 frontend tests pass. diff --git a/backend/app/api/routes/pending_uploads.py b/backend/app/api/routes/pending_uploads.py index 52ba7e90e..9d092c2bb 100644 --- a/backend/app/api/routes/pending_uploads.py +++ b/backend/app/api/routes/pending_uploads.py @@ -78,6 +78,8 @@ async def archive_all_pending( _: User | None = RequirePermissionIfAuthEnabled(Permission.QUEUE_CREATE), ): """Archive all pending uploads.""" + from backend.app.api.routes.settings import get_setting + result = await db.execute(select(PendingUpload).where(PendingUpload.status == "pending")) pending_uploads = result.scalars().all() @@ -85,6 +87,7 @@ async def archive_all_pending( failed = 0 service = ArchiveService(db) + prefer_filename = (await get_setting(db, "virtual_printer_archive_name_source")) == "filename" for pending in pending_uploads: file_path = Path(pending.file_path) @@ -102,6 +105,7 @@ async def archive_all_pending( "source": "virtual_printer", "source_ip": pending.source_ip, }, + prefer_filename_for_name=prefer_filename, ) if archive: @@ -193,6 +197,9 @@ async def archive_pending_upload( raise HTTPException(status_code=404, detail="Upload file not found on disk") # Archive the file + from backend.app.api.routes.settings import get_setting + + prefer_filename = (await get_setting(db, "virtual_printer_archive_name_source")) == "filename" service = ArchiveService(db) archive = await service.archive_print( printer_id=None, @@ -202,6 +209,7 @@ async def archive_pending_upload( "source": "virtual_printer", "source_ip": pending.source_ip, }, + prefer_filename_for_name=prefer_filename, ) if not archive: diff --git a/backend/app/api/routes/settings.py b/backend/app/api/routes/settings.py index d04ed1a87..9fb27d355 100644 --- a/backend/app/api/routes/settings.py +++ b/backend/app/api/routes/settings.py @@ -845,6 +845,7 @@ async def get_virtual_printer_settings( target_printer_id = await get_setting(db, "virtual_printer_target_printer_id") remote_interface_ip = await get_setting(db, "virtual_printer_remote_interface_ip") tailscale_disabled_raw = await get_setting(db, "virtual_printer_tailscale_disabled") + archive_name_source = await get_setting(db, "virtual_printer_archive_name_source") return { "enabled": enabled == "true" if enabled else False, @@ -854,6 +855,7 @@ async def get_virtual_printer_settings( "target_printer_id": int(target_printer_id) if target_printer_id else None, "remote_interface_ip": remote_interface_ip or "", "tailscale_disabled": tailscale_disabled_raw == "true" if tailscale_disabled_raw else True, + "archive_name_source": archive_name_source if archive_name_source in ("metadata", "filename") else "metadata", "status": virtual_printer_manager.get_status(), } @@ -867,6 +869,7 @@ async def update_virtual_printer_settings( target_printer_id: int = None, remote_interface_ip: str = None, tailscale_disabled: bool = None, + archive_name_source: str = None, db: AsyncSession = Depends(get_db), _: User | None = RequirePermissionIfAuthEnabled(Permission.SETTINGS_UPDATE), ): @@ -930,6 +933,13 @@ async def update_virtual_printer_settings( status_code=400, content={"detail": "Mode must be 'immediate', 'review', 'print_queue', or 'proxy'"}, ) + + # Validate archive_name_source + if archive_name_source is not None and archive_name_source not in ("metadata", "filename"): + return JSONResponse( + status_code=400, + content={"detail": "archive_name_source must be 'metadata' or 'filename'"}, + ) # Normalize legacy "queue" to "review" for storage if new_mode == "queue": new_mode = "review" @@ -1000,6 +1010,8 @@ async def update_virtual_printer_settings( await set_setting(db, "virtual_printer_remote_interface_ip", remote_interface_ip) if tailscale_disabled is not None: await set_setting(db, "virtual_printer_tailscale_disabled", "true" if tailscale_disabled else "false") + if archive_name_source is not None: + await set_setting(db, "virtual_printer_archive_name_source", archive_name_source) # Propagate tailscale_disabled to the first VirtualPrinter row so sync_from_db() picks it up if tailscale_disabled is not None: diff --git a/backend/app/schemas/settings.py b/backend/app/schemas/settings.py index 7df5d6279..96d4f4b80 100644 --- a/backend/app/schemas/settings.py +++ b/backend/app/schemas/settings.py @@ -116,6 +116,10 @@ class AppSettings(BaseModel): default="immediate", description="Mode: 'immediate' (archive now), 'review' (pending review), or 'print_queue' (add to print queue)", ) + virtual_printer_archive_name_source: str = Field( + default="metadata", + description="Source for the archive's display name on virtual-printer uploads: 'metadata' uses the 3MF's embedded print_name (default, matches Bambu's behavior), 'filename' uses the filename Bambu Studio sent over FTP (lets users rename via the slicer's 'send to printer' dialog).", + ) # Dark mode theme settings dark_style: str = Field(default="classic", description="Dark mode style: classic, glow, vibrant") @@ -349,6 +353,7 @@ class AppSettingsUpdate(BaseModel): virtual_printer_enabled: bool | None = None virtual_printer_access_code: str | None = None virtual_printer_mode: str | None = None + virtual_printer_archive_name_source: str | None = None dark_style: str | None = None dark_background: str | None = None dark_accent: str | None = None diff --git a/backend/app/services/archive.py b/backend/app/services/archive.py index 889c7a58c..95709dbcc 100644 --- a/backend/app/services/archive.py +++ b/backend/app/services/archive.py @@ -886,6 +886,7 @@ class ArchiveService: original_filename: str | None = None, project_id: int | None = None, subtask_id: str | None = None, + prefer_filename_for_name: bool = False, ) -> PrintArchive | None: """Archive a 3MF file with metadata. @@ -901,6 +902,11 @@ class ArchiveService: subtask_id: MQTT-provided task identifier (optional). Used to match an existing archive across a backend restart mid-print so the original row can be resumed instead of cancelled (#972). + prefer_filename_for_name: When True, use the uploaded filename stem as the + archive's display name even if the 3MF embeds a `print_name` in its + metadata. Used by virtual-printer flows so users who rename a job in + BambuStudio's "send to printer" dialog see that name instead of the + creator-baked title (#1152). """ # Verify printer exists if specified if printer_id is not None: @@ -1028,7 +1034,7 @@ class ArchiveService: file_size=dest_file.stat().st_size, content_hash=content_hash, thumbnail_path=thumbnail_path, - print_name=metadata.get("print_name") or display_stem, + print_name=display_stem if prefer_filename_for_name else (metadata.get("print_name") or display_stem), print_time_seconds=metadata.get("print_time_seconds"), filament_used_grams=metadata.get("filament_used_grams"), filament_type=metadata.get("filament_type"), diff --git a/backend/app/services/virtual_printer/manager.py b/backend/app/services/virtual_printer/manager.py index 30eeff7a8..b6b2844d2 100644 --- a/backend/app/services/virtual_printer/manager.py +++ b/backend/app/services/virtual_printer/manager.py @@ -236,9 +236,12 @@ class VirtualPrinterInstance: return try: + from backend.app.api.routes.settings import get_setting from backend.app.services.archive import ArchiveService async with self._session_factory() as db: + name_source = await get_setting(db, "virtual_printer_archive_name_source") + prefer_filename = name_source == "filename" service = ArchiveService(db) archive = await service.archive_print( printer_id=None, @@ -248,6 +251,7 @@ class VirtualPrinterInstance: "source": "virtual_printer", "source_ip": source_ip, }, + prefer_filename_for_name=prefer_filename, ) if archive: logger.info("[VP %s] Archived: %s - %s", self.name, archive.id, archive.print_name) @@ -309,10 +313,13 @@ class VirtualPrinterInstance: return try: + from backend.app.api.routes.settings import get_setting from backend.app.models.print_queue import PrintQueueItem from backend.app.services.archive import ArchiveService async with self._session_factory() as db: + name_source = await get_setting(db, "virtual_printer_archive_name_source") + prefer_filename = name_source == "filename" service = ArchiveService(db) archive = await service.archive_print( printer_id=None, @@ -322,6 +329,7 @@ class VirtualPrinterInstance: "source": "virtual_printer", "source_ip": source_ip, }, + prefer_filename_for_name=prefer_filename, ) if archive: logger.info("[VP %s] Archived: %s - %s", self.name, archive.id, archive.print_name) diff --git a/backend/tests/unit/services/test_virtual_printer.py b/backend/tests/unit/services/test_virtual_printer.py index 862281d73..c062d15e3 100644 --- a/backend/tests/unit/services/test_virtual_printer.py +++ b/backend/tests/unit/services/test_virtual_printer.py @@ -215,10 +215,17 @@ class TestVirtualPrinterInstance: mock_archive.id = 1 mock_archive.print_name = "test" - with patch( - "backend.app.services.archive.ArchiveService.archive_print", - new_callable=AsyncMock, - return_value=mock_archive, + with ( + patch( + "backend.app.api.routes.settings.get_setting", + new_callable=AsyncMock, + return_value=None, + ), + patch( + "backend.app.services.archive.ArchiveService.archive_print", + new_callable=AsyncMock, + return_value=mock_archive, + ), ): await inst._add_to_print_queue(file_path, "192.168.1.100") @@ -266,10 +273,17 @@ class TestVirtualPrinterInstance: mock_archive.id = 1 mock_archive.print_name = "test" - with patch( - "backend.app.services.archive.ArchiveService.archive_print", - new_callable=AsyncMock, - return_value=mock_archive, + with ( + patch( + "backend.app.api.routes.settings.get_setting", + new_callable=AsyncMock, + return_value=None, + ), + patch( + "backend.app.services.archive.ArchiveService.archive_print", + new_callable=AsyncMock, + return_value=mock_archive, + ), ): await inst._add_to_print_queue(file_path, "192.168.1.100") @@ -277,6 +291,71 @@ class TestVirtualPrinterInstance: queue_item = added_items[0] assert queue_item.manual_start is True + # ======================================================================== + # Tests for archive_name_source setting (#1152) + # ======================================================================== + + @pytest.mark.asyncio + @pytest.mark.parametrize( + ("setting_value", "expected_prefer_filename"), + [ + ("filename", True), + ("metadata", False), + (None, False), # Default when setting unset + ("", False), # Defensive: empty string is not "filename" + ], + ) + async def test_archive_file_passes_prefer_filename_per_setting( + self, tmp_path, setting_value, expected_prefer_filename + ): + """_archive_file reads `virtual_printer_archive_name_source` and forwards + prefer_filename_for_name=True only when it equals 'filename' (#1152).""" + from backend.app.services.virtual_printer.manager import VirtualPrinterInstance + + mock_db = AsyncMock() + mock_session_factory = MagicMock() + mock_session_ctx = AsyncMock() + mock_session_ctx.__aenter__ = AsyncMock(return_value=mock_db) + mock_session_ctx.__aexit__ = AsyncMock(return_value=False) + mock_session_factory.return_value = mock_session_ctx + + inst = VirtualPrinterInstance( + vp_id=20, + name="NameSource", + mode="immediate", + model="C11", + access_code="12345678", + serial_suffix="391800020", + base_dir=tmp_path, + session_factory=mock_session_factory, + ) + + file_path = tmp_path / "user-renamed-job.3mf" + file_path.write_bytes(b"fake3mf") + + mock_archive = MagicMock() + mock_archive.id = 1 + mock_archive.print_name = "user-renamed-job" + + archive_print_mock = AsyncMock(return_value=mock_archive) + + with ( + patch( + "backend.app.api.routes.settings.get_setting", + new_callable=AsyncMock, + return_value=setting_value, + ), + patch( + "backend.app.services.archive.ArchiveService.archive_print", + archive_print_mock, + ), + ): + await inst._archive_file(file_path, "192.168.1.100") + + assert archive_print_mock.await_count == 1 + kwargs = archive_print_mock.await_args.kwargs + assert kwargs.get("prefer_filename_for_name") is expected_prefer_filename + class TestVirtualPrinterManager: """Tests for VirtualPrinterManager orchestrator.""" diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 39152a12e..c9e0a454c 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -5554,6 +5554,7 @@ export interface VirtualPrinterSettings { target_printer_id: number | null; // For proxy mode remote_interface_ip: string | null; // For SSDP proxy across networks tailscale_disabled: boolean; + archive_name_source: 'metadata' | 'filename'; // Source for archive's display name status: VirtualPrinterStatus; } @@ -5597,6 +5598,7 @@ export const virtualPrinterApi = { target_printer_id?: number; remote_interface_ip?: string; tailscale_disabled?: boolean; + archive_name_source?: 'metadata' | 'filename'; }) => { const params = new URLSearchParams(); if (data.enabled !== undefined) params.set('enabled', String(data.enabled)); @@ -5606,6 +5608,7 @@ export const virtualPrinterApi = { if (data.target_printer_id !== undefined) params.set('target_printer_id', String(data.target_printer_id)); if (data.remote_interface_ip !== undefined) params.set('remote_interface_ip', data.remote_interface_ip); if (data.tailscale_disabled !== undefined) params.set('tailscale_disabled', String(data.tailscale_disabled)); + if (data.archive_name_source !== undefined) params.set('archive_name_source', data.archive_name_source); return request(`/settings/virtual-printer?${params.toString()}`, { method: 'PUT', diff --git a/frontend/src/components/VirtualPrinterList.tsx b/frontend/src/components/VirtualPrinterList.tsx index 4eadffc79..70ed8f1ca 100644 --- a/frontend/src/components/VirtualPrinterList.tsx +++ b/frontend/src/components/VirtualPrinterList.tsx @@ -1,15 +1,19 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useQuery } from '@tanstack/react-query'; -import { Loader2, Plus, Printer, ExternalLink, AlertTriangle, Info } from 'lucide-react'; -import { multiVirtualPrinterApi } from '../api/client'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { Loader2, Plus, Printer, ExternalLink, AlertTriangle, Info, FileText } from 'lucide-react'; +import { multiVirtualPrinterApi, virtualPrinterApi } from '../api/client'; import { Card, CardContent } from './Card'; import { Button } from './Button'; +import { Toggle } from './Toggle'; +import { useToast } from '../contexts/ToastContext'; import { VirtualPrinterCard } from './VirtualPrinterCard'; import { VirtualPrinterAddDialog } from './VirtualPrinterAddDialog'; export function VirtualPrinterList() { const { t } = useTranslation(); + const queryClient = useQueryClient(); + const { showToast } = useToast(); const [showAddDialog, setShowAddDialog] = useState(false); const { data, isLoading } = useQuery({ @@ -18,6 +22,25 @@ export function VirtualPrinterList() { refetchInterval: 10000, }); + const { data: globalSettings } = useQuery({ + queryKey: ['virtual-printer-settings'], + queryFn: virtualPrinterApi.getSettings, + }); + + const archiveNameSourceMutation = useMutation({ + mutationFn: (source: 'metadata' | 'filename') => + virtualPrinterApi.updateSettings({ archive_name_source: source }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['virtual-printer-settings'] }); + showToast(t('virtualPrinter.toast.updated')); + }, + onError: (error: Error) => { + showToast(error.message || t('virtualPrinter.toast.failedToUpdate'), 'error'); + }, + }); + + const useFilename = globalSettings?.archive_name_source === 'filename'; + if (isLoading) { return ( @@ -73,6 +96,38 @@ export function VirtualPrinterList() { + {/* Global VP behavior settings */} + + +
+ +
+
+

+ {t('virtualPrinter.archiveNameSource.title')} +

+
+ + {t('virtualPrinter.archiveNameSource.metadata')} + + archiveNameSourceMutation.mutate(checked ? 'filename' : 'metadata')} + disabled={archiveNameSourceMutation.isPending} + /> + + {t('virtualPrinter.archiveNameSource.filename')} + +
+
+

+ {t('virtualPrinter.archiveNameSource.description')} +

+
+
+
+
+ {/* Header with add button */}
diff --git a/frontend/src/i18n/locales/de.ts b/frontend/src/i18n/locales/de.ts index 0c0efef8f..81e05ea14 100644 --- a/frontend/src/i18n/locales/de.ts +++ b/frontend/src/i18n/locales/de.ts @@ -4022,6 +4022,12 @@ export default { description: 'Die virtuelle Druckerfunktion erfordert zusätzliche Systemkonfiguration, bevor sie funktioniert. Dies beinhaltet Portweiterleitung, Firewall-Regeln und plattformspezifische Einstellungen.', readGuide: 'Lese die Einrichtungsanleitung vor dem Aktivieren', }, + archiveNameSource: { + title: 'Quelle des Archivnamens', + description: 'Lege fest, wie neue Archive benannt werden, wenn Dateien über den virtuellen Drucker eintreffen. "Metadaten" verwendet den im 3MF eingebetteten Titel des Slicers (Standard). "Dateiname" nutzt den Dateinamen, den Bambu Studio per FTP gesendet hat — praktisch, wenn der Job im Dialog "Zum Drucker senden" umbenannt wurde.', + metadata: 'Metadaten', + filename: 'Dateiname', + }, howItWorks: { title: 'So funktioniert es', step1: 'Im selben LAN erscheinen virtuelle Drucker automatisch in deinem Slicer (Bambu Studio / OrcaSlicer). Aus anderen Netzwerken füge sie manuell per IP-Adresse und Zugangscode hinzu.', diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index f3928a3aa..869a79a19 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -4031,6 +4031,12 @@ export default { description: 'The virtual printer feature requires additional system configuration before it will work. This includes port forwarding, firewall rules, and platform-specific settings.', readGuide: 'Read the setup guide before enabling', }, + archiveNameSource: { + title: 'Archive name source', + description: 'Choose how new archives are named when files arrive via the virtual printer. "Metadata" uses the slicer-embedded title from the 3MF (default). "Filename" uses the filename Bambu Studio sent over FTP — handy if you renamed the job in the "send to printer" dialog.', + metadata: 'Metadata', + filename: 'Filename', + }, howItWorks: { title: 'How it works', step1: 'On the same LAN, virtual printers appear in your slicer (Bambu Studio / OrcaSlicer) automatically via discovery. From other networks, add them manually by IP address and access code.', diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index 938ee4454..0117c190d 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -4013,6 +4013,12 @@ export default { description: '虚拟打印机功能需要额外的系统配置才能工作。包括端口转发、防火墙规则和平台特定设置。', readGuide: '启用前请阅读设置指南', }, + archiveNameSource: { + title: '存档名称来源', + description: '选择通过虚拟打印机接收文件时新存档的命名方式。"元数据"使用 3MF 中嵌入的切片标题(默认)。"文件名"使用 Bambu Studio 通过 FTP 发送的文件名 — 当您在"发送到打印机"对话框中重命名作业时非常有用。', + metadata: '元数据', + filename: '文件名', + }, howItWorks: { title: '工作原理', step1: '在同一局域网中,虚拟打印机会通过发现机制自动出现在您的切片软件(Bambu Studio / OrcaSlicer)中。从其他网络,通过 IP 地址和访问码手动添加。', diff --git a/frontend/src/i18n/locales/zh-TW.ts b/frontend/src/i18n/locales/zh-TW.ts index edbce28a6..a9e7b01c6 100644 --- a/frontend/src/i18n/locales/zh-TW.ts +++ b/frontend/src/i18n/locales/zh-TW.ts @@ -4013,6 +4013,12 @@ export default { description: '虛擬印表機功能需要額外的系統設定才能工作。包括埠轉發、防火牆規則和平臺特定設定。', readGuide: '啟用前請閱讀設定指南', }, + archiveNameSource: { + title: '存檔名稱來源', + description: '選擇透過虛擬印表機接收檔案時新存檔的命名方式。"元資料"使用 3MF 中嵌入的切片標題(預設)。"檔名"使用 Bambu Studio 透過 FTP 傳送的檔案名稱 — 當您在"傳送到印表機"對話方塊中重新命名工作時非常有用。', + metadata: '元資料', + filename: '檔名', + }, howItWorks: { title: '工作原理', step1: '在同一區域網路中,虛擬印表機會透過發現機制自動出現在您的切片軟體(Bambu Studio / OrcaSlicer)中。從其他網路,透過 IP 位址和存取碼手動新增。', diff --git a/static/assets/index-bqAa7OcX.js b/static/assets/index-5P0GaR3D.js similarity index 79% rename from static/assets/index-bqAa7OcX.js rename to static/assets/index-5P0GaR3D.js index d2ccafb7d..f58888ce5 100644 --- a/static/assets/index-bqAa7OcX.js +++ b/static/assets/index-5P0GaR3D.js @@ -1,42 +1,42 @@ -function eue(t,e){for(var n=0;nr[i]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();var Z_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function gc(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var _M={exports:{}},Ev={};var $8;function tue(){if($8)return Ev;$8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,i,s){var o=null;if(s!==void 0&&(o=""+s),i.key!==void 0&&(o=""+i.key),"key"in i){s={};for(var l in i)l!=="key"&&(s[l]=i[l])}else s=i;return i=s.ref,{$$typeof:t,type:r,key:o,ref:i!==void 0?i:null,props:s}}return Ev.Fragment=e,Ev.jsx=n,Ev.jsxs=n,Ev}var V8;function nue(){return V8||(V8=1,_M.exports=tue()),_M.exports}var a=nue(),kM={exports:{}},Wn={};var G8;function rue(){if(G8)return Wn;G8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),o=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),u=Symbol.for("react.lazy"),m=Symbol.for("react.activity"),p=Symbol.iterator;function f(K){return K===null||typeof K!="object"?null:(K=p&&K[p]||K["@@iterator"],typeof K=="function"?K:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},v=Object.assign,b={};function g(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}g.prototype.isReactComponent={},g.prototype.setState=function(K,ae){if(typeof K!="object"&&typeof K!="function"&&K!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,K,ae,"setState")},g.prototype.forceUpdate=function(K){this.updater.enqueueForceUpdate(this,K,"forceUpdate")};function S(){}S.prototype=g.prototype;function N(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}var P=N.prototype=new S;P.constructor=N,v(P,g.prototype),P.isPureReactComponent=!0;var C=Array.isArray;function A(){}var T={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function k(K,ae,me){var xe=me.ref;return{$$typeof:t,type:K,key:ae,ref:xe!==void 0?xe:null,props:me}}function E(K,ae){return k(K.type,ae,K.props)}function $(K){return typeof K=="object"&&K!==null&&K.$$typeof===t}function z(K){var ae={"=":"=0",":":"=2"};return"$"+K.replace(/[=:]/g,function(me){return ae[me]})}var X=/\/+/g;function L(K,ae){return typeof K=="object"&&K!==null&&K.key!=null?z(""+K.key):ae.toString(36)}function ne(K){switch(K.status){case"fulfilled":return K.value;case"rejected":throw K.reason;default:switch(typeof K.status=="string"?K.then(A,A):(K.status="pending",K.then(function(ae){K.status==="pending"&&(K.status="fulfilled",K.value=ae)},function(ae){K.status==="pending"&&(K.status="rejected",K.reason=ae)})),K.status){case"fulfilled":return K.value;case"rejected":throw K.reason}}throw K}function re(K,ae,me,xe,be){var B=typeof K;(B==="undefined"||B==="boolean")&&(K=null);var Q=!1;if(K===null)Q=!0;else switch(B){case"bigint":case"string":case"number":Q=!0;break;case"object":switch(K.$$typeof){case t:case e:Q=!0;break;case u:return Q=K._init,re(Q(K._payload),ae,me,xe,be)}}if(Q)return be=be(K),Q=xe===""?"."+L(K,0):xe,C(be)?(me="",Q!=null&&(me=Q.replace(X,"$&/")+"/"),re(be,ae,me,"",function(U){return U})):be!=null&&($(be)&&(be=E(be,me+(be.key==null||K&&K.key===be.key?"":(""+be.key).replace(X,"$&/")+"/")+Q)),ae.push(be)),1;Q=0;var D=xe===""?".":xe+":";if(C(K))for(var M=0;M>>1,oe=re[se];if(0>>1;sei(me,ue))xei(be,me)?(re[se]=be,re[xe]=ue,se=xe):(re[se]=me,re[ae]=ue,se=ae);else if(xei(be,ue))re[se]=be,re[xe]=ue,se=xe;else break e}}return ee}function i(re,ee){var ue=re.sortIndex-ee.sortIndex;return ue!==0?ue:re.id-ee.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var s=performance;t.unstable_now=function(){return s.now()}}else{var o=Date,l=o.now();t.unstable_now=function(){return o.now()-l}}var c=[],d=[],u=1,m=null,p=3,f=!1,x=!1,v=!1,b=!1,g=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,N=typeof setImmediate<"u"?setImmediate:null;function P(re){for(var ee=n(d);ee!==null;){if(ee.callback===null)r(d);else if(ee.startTime<=re)r(d),ee.sortIndex=ee.expirationTime,e(c,ee);else break;ee=n(d)}}function C(re){if(v=!1,P(re),!x)if(n(c)!==null)x=!0,A||(A=!0,z());else{var ee=n(d);ee!==null&&ne(C,ee.startTime-re)}}var A=!1,T=-1,F=5,k=-1;function E(){return b?!0:!(t.unstable_now()-kre&&E());){var se=m.callback;if(typeof se=="function"){m.callback=null,p=m.priorityLevel;var oe=se(m.expirationTime<=re);if(re=t.unstable_now(),typeof oe=="function"){m.callback=oe,P(re),ee=!0;break t}m===n(c)&&r(c),P(re)}else r(c);m=n(c)}if(m!==null)ee=!0;else{var K=n(d);K!==null&&ne(C,K.startTime-re),ee=!1}}break e}finally{m=null,p=ue,f=!1}ee=void 0}}finally{ee?z():A=!1}}}var z;if(typeof N=="function")z=function(){N($)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,L=X.port2;X.port1.onmessage=$,z=function(){L.postMessage(null)}}else z=function(){g($,0)};function ne(re,ee){T=g(function(){re(t.unstable_now())},ee)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(re){re.callback=null},t.unstable_forceFrameRate=function(re){0>re||125se?(re.sortIndex=ue,e(d,re),n(c)===null&&re===n(d)&&(v?(S(T),T=-1):v=!0,ne(C,ue-se))):(re.sortIndex=oe,e(c,re),x||f||(x=!0,A||(A=!0,z()))),re},t.unstable_shouldYield=E,t.unstable_wrapCallback=function(re){var ee=p;return function(){var ue=p;p=ee;try{return re.apply(this,arguments)}finally{p=ue}}}})(PM)),PM}var X8;function sue(){return X8||(X8=1,CM.exports=iue()),CM.exports}var TM={exports:{}},Es={};var Y8;function oue(){if(Y8)return Es;Y8=1;var t=Ug();function e(c){var d="https://react.dev/errors/"+c;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(e){console.error(e)}}return t(),TM.exports=oue(),TM.exports}var J8;function lue(){if(J8)return Dv;J8=1;var t=sue(),e=Ug(),n=iQ();function r(h){var y="https://react.dev/errors/"+h;if(1oe||(h.current=se[oe],se[oe]=null,oe--)}function me(h,y){oe++,se[oe]=h.current,h.current=y}var xe=K(null),be=K(null),B=K(null),Q=K(null);function D(h,y){switch(me(B,y),me(be,h),me(xe,null),y.nodeType){case 9:case 11:h=(h=y.documentElement)&&(h=h.namespaceURI)?h8(h):0;break;default:if(h=y.tagName,y=y.namespaceURI)y=h8(y),h=p8(y,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}ae(xe),me(xe,h)}function M(){ae(xe),ae(be),ae(B)}function U(h){h.memoizedState!==null&&me(Q,h);var y=xe.current,_=p8(y,h.type);y!==_&&(me(be,h),me(xe,_))}function Y(h){be.current===h&&(ae(xe),ae(be)),Q.current===h&&(ae(Q),Tv._currentValue=ue)}var I,ce;function O(h){if(I===void 0)try{throw Error()}catch(_){var y=_.stack.trim().match(/\n( *(at )?)/);I=y&&y[1]||"",ce=-1<_.stack.indexOf(` +function tue(t,e){for(var n=0;nr[i]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();var Z_=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function gc(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var _M={exports:{}},Ev={};var V8;function nue(){if(V8)return Ev;V8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,i,s){var o=null;if(s!==void 0&&(o=""+s),i.key!==void 0&&(o=""+i.key),"key"in i){s={};for(var l in i)l!=="key"&&(s[l]=i[l])}else s=i;return i=s.ref,{$$typeof:t,type:r,key:o,ref:i!==void 0?i:null,props:s}}return Ev.Fragment=e,Ev.jsx=n,Ev.jsxs=n,Ev}var G8;function rue(){return G8||(G8=1,_M.exports=nue()),_M.exports}var a=rue(),kM={exports:{}},Wn={};var W8;function aue(){if(W8)return Wn;W8=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),o=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),u=Symbol.for("react.lazy"),m=Symbol.for("react.activity"),p=Symbol.iterator;function f(K){return K===null||typeof K!="object"?null:(K=p&&K[p]||K["@@iterator"],typeof K=="function"?K:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},v=Object.assign,b={};function g(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}g.prototype.isReactComponent={},g.prototype.setState=function(K,ae){if(typeof K!="object"&&typeof K!="function"&&K!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,K,ae,"setState")},g.prototype.forceUpdate=function(K){this.updater.enqueueForceUpdate(this,K,"forceUpdate")};function S(){}S.prototype=g.prototype;function N(K,ae,me){this.props=K,this.context=ae,this.refs=b,this.updater=me||x}var P=N.prototype=new S;P.constructor=N,v(P,g.prototype),P.isPureReactComponent=!0;var C=Array.isArray;function A(){}var T={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function k(K,ae,me){var xe=me.ref;return{$$typeof:t,type:K,key:ae,ref:xe!==void 0?xe:null,props:me}}function E(K,ae){return k(K.type,ae,K.props)}function $(K){return typeof K=="object"&&K!==null&&K.$$typeof===t}function z(K){var ae={"=":"=0",":":"=2"};return"$"+K.replace(/[=:]/g,function(me){return ae[me]})}var X=/\/+/g;function L(K,ae){return typeof K=="object"&&K!==null&&K.key!=null?z(""+K.key):ae.toString(36)}function ne(K){switch(K.status){case"fulfilled":return K.value;case"rejected":throw K.reason;default:switch(typeof K.status=="string"?K.then(A,A):(K.status="pending",K.then(function(ae){K.status==="pending"&&(K.status="fulfilled",K.value=ae)},function(ae){K.status==="pending"&&(K.status="rejected",K.reason=ae)})),K.status){case"fulfilled":return K.value;case"rejected":throw K.reason}}throw K}function re(K,ae,me,xe,be){var B=typeof K;(B==="undefined"||B==="boolean")&&(K=null);var Q=!1;if(K===null)Q=!0;else switch(B){case"bigint":case"string":case"number":Q=!0;break;case"object":switch(K.$$typeof){case t:case e:Q=!0;break;case u:return Q=K._init,re(Q(K._payload),ae,me,xe,be)}}if(Q)return be=be(K),Q=xe===""?"."+L(K,0):xe,C(be)?(me="",Q!=null&&(me=Q.replace(X,"$&/")+"/"),re(be,ae,me,"",function(U){return U})):be!=null&&($(be)&&(be=E(be,me+(be.key==null||K&&K.key===be.key?"":(""+be.key).replace(X,"$&/")+"/")+Q)),ae.push(be)),1;Q=0;var D=xe===""?".":xe+":";if(C(K))for(var M=0;M>>1,oe=re[se];if(0>>1;sei(me,ue))xei(be,me)?(re[se]=be,re[xe]=ue,se=xe):(re[se]=me,re[ae]=ue,se=ae);else if(xei(be,ue))re[se]=be,re[xe]=ue,se=xe;else break e}}return ee}function i(re,ee){var ue=re.sortIndex-ee.sortIndex;return ue!==0?ue:re.id-ee.id}if(t.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var s=performance;t.unstable_now=function(){return s.now()}}else{var o=Date,l=o.now();t.unstable_now=function(){return o.now()-l}}var c=[],d=[],u=1,m=null,p=3,f=!1,x=!1,v=!1,b=!1,g=typeof setTimeout=="function"?setTimeout:null,S=typeof clearTimeout=="function"?clearTimeout:null,N=typeof setImmediate<"u"?setImmediate:null;function P(re){for(var ee=n(d);ee!==null;){if(ee.callback===null)r(d);else if(ee.startTime<=re)r(d),ee.sortIndex=ee.expirationTime,e(c,ee);else break;ee=n(d)}}function C(re){if(v=!1,P(re),!x)if(n(c)!==null)x=!0,A||(A=!0,z());else{var ee=n(d);ee!==null&&ne(C,ee.startTime-re)}}var A=!1,T=-1,F=5,k=-1;function E(){return b?!0:!(t.unstable_now()-kre&&E());){var se=m.callback;if(typeof se=="function"){m.callback=null,p=m.priorityLevel;var oe=se(m.expirationTime<=re);if(re=t.unstable_now(),typeof oe=="function"){m.callback=oe,P(re),ee=!0;break t}m===n(c)&&r(c),P(re)}else r(c);m=n(c)}if(m!==null)ee=!0;else{var K=n(d);K!==null&&ne(C,K.startTime-re),ee=!1}}break e}finally{m=null,p=ue,f=!1}ee=void 0}}finally{ee?z():A=!1}}}var z;if(typeof N=="function")z=function(){N($)};else if(typeof MessageChannel<"u"){var X=new MessageChannel,L=X.port2;X.port1.onmessage=$,z=function(){L.postMessage(null)}}else z=function(){g($,0)};function ne(re,ee){T=g(function(){re(t.unstable_now())},ee)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(re){re.callback=null},t.unstable_forceFrameRate=function(re){0>re||125se?(re.sortIndex=ue,e(d,re),n(c)===null&&re===n(d)&&(v?(S(T),T=-1):v=!0,ne(C,ue-se))):(re.sortIndex=oe,e(c,re),x||f||(x=!0,A||(A=!0,z()))),re},t.unstable_shouldYield=E,t.unstable_wrapCallback=function(re){var ee=p;return function(){var ue=p;p=ee;try{return re.apply(this,arguments)}finally{p=ue}}}})(PM)),PM}var Y8;function oue(){return Y8||(Y8=1,CM.exports=sue()),CM.exports}var TM={exports:{}},Ds={};var Q8;function lue(){if(Q8)return Ds;Q8=1;var t=Ug();function e(c){var d="https://react.dev/errors/"+c;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(e){console.error(e)}}return t(),TM.exports=lue(),TM.exports}var Z8;function cue(){if(Z8)return Dv;Z8=1;var t=oue(),e=Ug(),n=sQ();function r(h){var y="https://react.dev/errors/"+h;if(1oe||(h.current=se[oe],se[oe]=null,oe--)}function me(h,y){oe++,se[oe]=h.current,h.current=y}var xe=K(null),be=K(null),B=K(null),Q=K(null);function D(h,y){switch(me(B,y),me(be,h),me(xe,null),y.nodeType){case 9:case 11:h=(h=y.documentElement)&&(h=h.namespaceURI)?p8(h):0;break;default:if(h=y.tagName,y=y.namespaceURI)y=p8(y),h=f8(y,h);else switch(h){case"svg":h=1;break;case"math":h=2;break;default:h=0}}ae(xe),me(xe,h)}function M(){ae(xe),ae(be),ae(B)}function U(h){h.memoizedState!==null&&me(Q,h);var y=xe.current,_=f8(y,h.type);y!==_&&(me(be,h),me(xe,_))}function Y(h){be.current===h&&(ae(xe),ae(be)),Q.current===h&&(ae(Q),Tv._currentValue=ue)}var I,ce;function O(h){if(I===void 0)try{throw Error()}catch(_){var y=_.stack.trim().match(/\n( *(at )?)/);I=y&&y[1]||"",ce=-1<_.stack.indexOf(` at`)?" ()":-1<_.stack.indexOf("@")?"@unknown:0:0":""}return` -`+I+h+ce}var W=!1;function V(h,y){if(!h||W)return"";W=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var j={DetermineComponentFrameRoot:function(){try{if(y){var Ut=function(){throw Error()};if(Object.defineProperty(Ut.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(Ut,[])}catch(At){var _t=At}Reflect.construct(h,[],Ut)}else{try{Ut.call()}catch(At){_t=At}h.call(Ut.prototype)}}else{try{throw Error()}catch(At){_t=At}(Ut=h())&&typeof Ut.catch=="function"&&Ut.catch(function(){})}}catch(At){if(At&&_t&&typeof At.stack=="string")return[At.stack,_t.stack]}return[null,null]}};j.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var G=Object.getOwnPropertyDescriptor(j.DetermineComponentFrameRoot,"name");G&&G.configurable&&Object.defineProperty(j.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var Z=j.DetermineComponentFrameRoot(),Ne=Z[0],qe=Z[1];if(Ne&&qe){var lt=Ne.split(` +`+I+h+ce}var W=!1;function V(h,y){if(!h||W)return"";W=!0;var _=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var j={DetermineComponentFrameRoot:function(){try{if(y){var Ut=function(){throw Error()};if(Object.defineProperty(Ut.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(Ut,[])}catch(At){var kt=At}Reflect.construct(h,[],Ut)}else{try{Ut.call()}catch(At){kt=At}h.call(Ut.prototype)}}else{try{throw Error()}catch(At){kt=At}(Ut=h())&&typeof Ut.catch=="function"&&Ut.catch(function(){})}}catch(At){if(At&&kt&&typeof At.stack=="string")return[At.stack,kt.stack]}return[null,null]}};j.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var G=Object.getOwnPropertyDescriptor(j.DetermineComponentFrameRoot,"name");G&&G.configurable&&Object.defineProperty(j.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var Z=j.DetermineComponentFrameRoot(),Ne=Z[0],qe=Z[1];if(Ne&&qe){var lt=Ne.split(` `),vt=qe.split(` `);for(G=j=0;jG||lt[j]!==vt[G]){var Rt=` `+lt[j].replace(" at new "," at ");return h.displayName&&Rt.includes("")&&(Rt=Rt.replace("",h.displayName)),Rt}while(1<=j&&0<=G);break}}}finally{W=!1,Error.prepareStackTrace=_}return(_=h?h.displayName||h.name:"")?O(_):""}function H(h,y){switch(h.tag){case 26:case 27:case 5:return O(h.type);case 16:return O("Lazy");case 13:return h.child!==y&&y!==null?O("Suspense Fallback"):O("Suspense");case 19:return O("SuspenseList");case 0:case 15:return V(h.type,!1);case 11:return V(h.type.render,!1);case 1:return V(h.type,!0);case 31:return O("Activity");default:return""}}function J(h){try{var y="",_=null;do y+=H(h,_),_=h,h=h.return;while(h);return y}catch(j){return` Error generating stack: `+j.message+` -`+j.stack}}var ie=Object.prototype.hasOwnProperty,ge=t.unstable_scheduleCallback,pe=t.unstable_cancelCallback,he=t.unstable_shouldYield,q=t.unstable_requestPaint,R=t.unstable_now,te=t.unstable_getCurrentPriorityLevel,fe=t.unstable_ImmediatePriority,ke=t.unstable_UserBlockingPriority,je=t.unstable_NormalPriority,Ae=t.unstable_LowPriority,ye=t.unstable_IdlePriority,Re=t.log,Be=t.unstable_setDisableYieldValue,Ce=null,ze=null;function Me(h){if(typeof Re=="function"&&Be(h),ze&&typeof ze.setStrictMode=="function")try{ze.setStrictMode(Ce,h)}catch{}}var Ie=Math.clz32?Math.clz32:ve,Ge=Math.log,et=Math.LN2;function ve(h){return h>>>=0,h===0?32:31-(Ge(h)/et|0)|0}var Xe=256,Pe=262144,Ve=4194304;function we(h){var y=h&42;if(y!==0)return y;switch(h&-h){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return h&261888;case 262144:case 524288:case 1048576:case 2097152:return h&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return h&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return h}}function de(h,y,_){var j=h.pendingLanes;if(j===0)return 0;var G=0,Z=h.suspendedLanes,Ne=h.pingedLanes;h=h.warmLanes;var qe=j&134217727;return qe!==0?(j=qe&~Z,j!==0?G=we(j):(Ne&=qe,Ne!==0?G=we(Ne):_||(_=qe&~h,_!==0&&(G=we(_))))):(qe=j&~Z,qe!==0?G=we(qe):Ne!==0?G=we(Ne):_||(_=j&~h,_!==0&&(G=we(_)))),G===0?0:y!==0&&y!==G&&(y&Z)===0&&(Z=G&-G,_=y&-y,Z>=_||Z===32&&(_&4194048)!==0)?y:G}function Se(h,y){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&y)===0}function $e(h,y){switch(h){case 1:case 2:case 4:case 8:case 64:return y+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return y+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function st(){var h=Ve;return Ve<<=1,(Ve&62914560)===0&&(Ve=4194304),h}function He(h){for(var y=[],_=0;31>_;_++)y.push(h);return y}function rt(h,y){h.pendingLanes|=y,y!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function ht(h,y,_,j,G,Z){var Ne=h.pendingLanes;h.pendingLanes=_,h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0,h.expiredLanes&=_,h.entangledLanes&=_,h.errorRecoveryDisabledLanes&=_,h.shellSuspendCounter=0;var qe=h.entanglements,lt=h.expirationTimes,vt=h.hiddenUpdates;for(_=Ne&~_;0<_;){var Rt=31-Ie(_),Ut=1<"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var Tr=/[\n"\\]/g;function In(h){return h.replace(Tr,function(y){return"\\"+y.charCodeAt(0).toString(16)+" "})}function Da(h,y,_,j,G,Z,Ne,qe){h.name="",Ne!=null&&typeof Ne!="function"&&typeof Ne!="symbol"&&typeof Ne!="boolean"?h.type=Ne:h.removeAttribute("type"),y!=null?Ne==="number"?(y===0&&h.value===""||h.value!=y)&&(h.value=""+cn(y)):h.value!==""+cn(y)&&(h.value=""+cn(y)):Ne!=="submit"&&Ne!=="reset"||h.removeAttribute("value"),y!=null?Br(h,Ne,cn(y)):_!=null?Br(h,Ne,cn(_)):j!=null&&h.removeAttribute("value"),G==null&&Z!=null&&(h.defaultChecked=!!Z),G!=null&&(h.checked=G&&typeof G!="function"&&typeof G!="symbol"),qe!=null&&typeof qe!="function"&&typeof qe!="symbol"&&typeof qe!="boolean"?h.name=""+cn(qe):h.removeAttribute("name")}function $n(h,y,_,j,G,Z,Ne,qe){if(Z!=null&&typeof Z!="function"&&typeof Z!="symbol"&&typeof Z!="boolean"&&(h.type=Z),y!=null||_!=null){if(!(Z!=="submit"&&Z!=="reset"||y!=null)){Sn(h);return}_=_!=null?""+cn(_):"",y=y!=null?""+cn(y):_,qe||y===h.value||(h.value=y),h.defaultValue=y}j=j??G,j=typeof j!="function"&&typeof j!="symbol"&&!!j,h.checked=qe?h.checked:!!j,h.defaultChecked=!!j,Ne!=null&&typeof Ne!="function"&&typeof Ne!="symbol"&&typeof Ne!="boolean"&&(h.name=Ne),Sn(h)}function Br(h,y,_){y==="number"&&br(h.ownerDocument)===h||h.defaultValue===""+_||(h.defaultValue=""+_)}function Kr(h,y,_,j){if(h=h.options,y){y={};for(var G=0;G<_.length;G++)y["$"+_[G]]=!0;for(_=0;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),zi=!1;if($o)try{var wl={};Object.defineProperty(wl,"passive",{get:function(){zi=!0}}),window.addEventListener("test",wl,wl),window.removeEventListener("test",wl,wl)}catch{zi=!1}var wo=null,ha=null,vc=null;function Om(){if(vc)return vc;var h,y=ha,_=y.length,j,G="value"in wo?wo.value:wo.textContent,Z=G.length;for(h=0;h<_&&y[h]===G[h];h++);var Ne=_-h;for(j=1;j<=Ne&&y[_-j]===G[Z-j];j++);return vc=G.slice(h,1=it),ct=" ",Mn=!1;function xr(h,y){switch(h){case"keyup":return Fn.indexOf(y.keyCode)!==-1;case"keydown":return y.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function lr(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var Ir=!1;function Fa(h,y){switch(h){case"compositionend":return lr(y);case"keypress":return y.which!==32?null:(Mn=!0,ct);case"textInput":return h=y.data,h===ct&&Mn?null:h;default:return null}}function un(h,y){if(Ir)return h==="compositionend"||!_n&&xr(h,y)?(h=Om(),vc=ha=wo=null,Ir=!1,h):null;switch(h){case"paste":return null;case"keypress":if(!(y.ctrlKey||y.altKey||y.metaKey)||y.ctrlKey&&y.altKey){if(y.char&&1=y)return{node:_,offset:y-h};h=j}e:{for(;_;){if(_.nextSibling){_=_.nextSibling;break e}_=_.parentNode}_=void 0}_=Yp(_)}}function Jy(h,y){return h&&y?h===y?!0:h&&h.nodeType===3?!1:y&&y.nodeType===3?Jy(h,y.parentNode):"contains"in h?h.contains(y):h.compareDocumentPosition?!!(h.compareDocumentPosition(y)&16):!1:!1}function YS(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var y=br(h.document);y instanceof h.HTMLIFrameElement;){try{var _=typeof y.contentWindow.location.href=="string"}catch{_=!1}if(_)h=y.contentWindow;else break;y=br(h.document)}return y}function EA(h){var y=h&&h.nodeName&&h.nodeName.toLowerCase();return y&&(y==="input"&&(h.type==="text"||h.type==="search"||h.type==="tel"||h.type==="url"||h.type==="password")||y==="textarea"||h.contentEditable==="true")}var Dce=$o&&"documentMode"in document&&11>=document.documentMode,eb=null,DA=null,Zy=null,FA=!1;function R5(h,y,_){var j=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;FA||eb==null||eb!==br(j)||(j=eb,"selectionStart"in j&&EA(j)?j={start:j.selectionStart,end:j.selectionEnd}:(j=(j.ownerDocument&&j.ownerDocument.defaultView||window).getSelection(),j={anchorNode:j.anchorNode,anchorOffset:j.anchorOffset,focusNode:j.focusNode,focusOffset:j.focusOffset}),Zy&&Vm(Zy,j)||(Zy=j,j=I_(DA,"onSelect"),0>=Ne,G-=Ne,ld=1<<32-Ie(y)+G|_<Qn?(vr=vn,vn=null):vr=vn.sibling;var Mr=_t(gt,vn,yt[Qn],It);if(Mr===null){vn===null&&(vn=vr);break}h&&vn&&Mr.alternate===null&&y(gt,vn),pt=Z(Mr,pt,Qn),jr===null?An=Mr:jr.sibling=Mr,jr=Mr,vn=vr}if(Qn===yt.length)return _(gt,vn),Sr&&cu(gt,Qn),An;if(vn===null){for(;QnQn?(vr=vn,vn=null):vr=vn.sibling;var hh=_t(gt,vn,Mr.value,It);if(hh===null){vn===null&&(vn=vr);break}h&&vn&&hh.alternate===null&&y(gt,vn),pt=Z(hh,pt,Qn),jr===null?An=hh:jr.sibling=hh,jr=hh,vn=vr}if(Mr.done)return _(gt,vn),Sr&&cu(gt,Qn),An;if(vn===null){for(;!Mr.done;Qn++,Mr=yt.next())Mr=Ut(gt,Mr.value,It),Mr!==null&&(pt=Z(Mr,pt,Qn),jr===null?An=Mr:jr.sibling=Mr,jr=Mr);return Sr&&cu(gt,Qn),An}for(vn=j(vn);!Mr.done;Qn++,Mr=yt.next())Mr=At(vn,gt,Qn,Mr.value,It),Mr!==null&&(h&&Mr.alternate!==null&&vn.delete(Mr.key===null?Qn:Mr.key),pt=Z(Mr,pt,Qn),jr===null?An=Mr:jr.sibling=Mr,jr=Mr);return h&&vn.forEach(function(Zde){return y(gt,Zde)}),Sr&&cu(gt,Qn),An}function Qr(gt,pt,yt,It){if(typeof yt=="object"&&yt!==null&&yt.type===v&&yt.key===null&&(yt=yt.props.children),typeof yt=="object"&&yt!==null){switch(yt.$$typeof){case f:e:{for(var An=yt.key;pt!==null;){if(pt.key===An){if(An=yt.type,An===v){if(pt.tag===7){_(gt,pt.sibling),It=G(pt,yt.props.children),It.return=gt,gt=It;break e}}else if(pt.elementType===An||typeof An=="object"&&An!==null&&An.$$typeof===F&&sf(An)===pt.type){_(gt,pt.sibling),It=G(pt,yt.props),iv(It,yt),It.return=gt,gt=It;break e}_(gt,pt);break}else y(gt,pt);pt=pt.sibling}yt.type===v?(It=ef(yt.props.children,gt.mode,It,yt.key),It.return=gt,gt=It):(It=t_(yt.type,yt.key,yt.props,null,gt.mode,It),iv(It,yt),It.return=gt,gt=It)}return Ne(gt);case x:e:{for(An=yt.key;pt!==null;){if(pt.key===An)if(pt.tag===4&&pt.stateNode.containerInfo===yt.containerInfo&&pt.stateNode.implementation===yt.implementation){_(gt,pt.sibling),It=G(pt,yt.children||[]),It.return=gt,gt=It;break e}else{_(gt,pt);break}else y(gt,pt);pt=pt.sibling}It=BA(yt,gt.mode,It),It.return=gt,gt=It}return Ne(gt);case F:return yt=sf(yt),Qr(gt,pt,yt,It)}if(ne(yt))return gn(gt,pt,yt,It);if(z(yt)){if(An=z(yt),typeof An!="function")throw Error(r(150));return yt=An.call(yt),Ln(gt,pt,yt,It)}if(typeof yt.then=="function")return Qr(gt,pt,l_(yt),It);if(yt.$$typeof===N)return Qr(gt,pt,a_(gt,yt),It);c_(gt,yt)}return typeof yt=="string"&&yt!==""||typeof yt=="number"||typeof yt=="bigint"?(yt=""+yt,pt!==null&&pt.tag===6?(_(gt,pt.sibling),It=G(pt,yt),It.return=gt,gt=It):(_(gt,pt),It=UA(yt,gt.mode,It),It.return=gt,gt=It),Ne(gt)):_(gt,pt)}return function(gt,pt,yt,It){try{av=0;var An=Qr(gt,pt,yt,It);return ub=null,An}catch(vn){if(vn===db||vn===s_)throw vn;var jr=Ko(29,vn,null,gt.mode);return jr.lanes=It,jr.return=gt,jr}}}var lf=aU(!0),iU=aU(!1),Ym=!1;function ZA(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function ej(h,y){h=h.updateQueue,y.updateQueue===h&&(y.updateQueue={baseState:h.baseState,firstBaseUpdate:h.firstBaseUpdate,lastBaseUpdate:h.lastBaseUpdate,shared:h.shared,callbacks:null})}function Qm(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function Jm(h,y,_){var j=h.updateQueue;if(j===null)return null;if(j=j.shared,(Lr&2)!==0){var G=j.pending;return G===null?y.next=y:(y.next=G.next,G.next=y),j.pending=y,y=e_(h),H5(h,null,_),y}return ZS(h,j,y,_),e_(h)}function sv(h,y,_){if(y=y.updateQueue,y!==null&&(y=y.shared,(_&4194048)!==0)){var j=y.lanes;j&=h.pendingLanes,_|=j,y.lanes=_,qt(h,_)}}function tj(h,y){var _=h.updateQueue,j=h.alternate;if(j!==null&&(j=j.updateQueue,_===j)){var G=null,Z=null;if(_=_.firstBaseUpdate,_!==null){do{var Ne={lane:_.lane,tag:_.tag,payload:_.payload,callback:null,next:null};Z===null?G=Z=Ne:Z=Z.next=Ne,_=_.next}while(_!==null);Z===null?G=Z=y:Z=Z.next=y}else G=Z=y;_={baseState:j.baseState,firstBaseUpdate:G,lastBaseUpdate:Z,shared:j.shared,callbacks:j.callbacks},h.updateQueue=_;return}h=_.lastBaseUpdate,h===null?_.firstBaseUpdate=y:h.next=y,_.lastBaseUpdate=y}var nj=!1;function ov(){if(nj){var h=cb;if(h!==null)throw h}}function lv(h,y,_,j){nj=!1;var G=h.updateQueue;Ym=!1;var Z=G.firstBaseUpdate,Ne=G.lastBaseUpdate,qe=G.shared.pending;if(qe!==null){G.shared.pending=null;var lt=qe,vt=lt.next;lt.next=null,Ne===null?Z=vt:Ne.next=vt,Ne=lt;var Rt=h.alternate;Rt!==null&&(Rt=Rt.updateQueue,qe=Rt.lastBaseUpdate,qe!==Ne&&(qe===null?Rt.firstBaseUpdate=vt:qe.next=vt,Rt.lastBaseUpdate=lt))}if(Z!==null){var Ut=G.baseState;Ne=0,Rt=vt=lt=null,qe=Z;do{var _t=qe.lane&-536870913,At=_t!==qe.lane;if(At?(yr&_t)===_t:(j&_t)===_t){_t!==0&&_t===lb&&(nj=!0),Rt!==null&&(Rt=Rt.next={lane:0,tag:qe.tag,payload:qe.payload,callback:null,next:null});e:{var gn=h,Ln=qe;_t=y;var Qr=_;switch(Ln.tag){case 1:if(gn=Ln.payload,typeof gn=="function"){Ut=gn.call(Qr,Ut,_t);break e}Ut=gn;break e;case 3:gn.flags=gn.flags&-65537|128;case 0:if(gn=Ln.payload,_t=typeof gn=="function"?gn.call(Qr,Ut,_t):gn,_t==null)break e;Ut=m({},Ut,_t);break e;case 2:Ym=!0}}_t=qe.callback,_t!==null&&(h.flags|=64,At&&(h.flags|=8192),At=G.callbacks,At===null?G.callbacks=[_t]:At.push(_t))}else At={lane:_t,tag:qe.tag,payload:qe.payload,callback:qe.callback,next:null},Rt===null?(vt=Rt=At,lt=Ut):Rt=Rt.next=At,Ne|=_t;if(qe=qe.next,qe===null){if(qe=G.shared.pending,qe===null)break;At=qe,qe=At.next,At.next=null,G.lastBaseUpdate=At,G.shared.pending=null}}while(!0);Rt===null&&(lt=Ut),G.baseState=lt,G.firstBaseUpdate=vt,G.lastBaseUpdate=Rt,Z===null&&(G.shared.lanes=0),rh|=Ne,h.lanes=Ne,h.memoizedState=Ut}}function sU(h,y){if(typeof h!="function")throw Error(r(191,h));h.call(y)}function oU(h,y){var _=h.callbacks;if(_!==null)for(h.callbacks=null,h=0;h<_.length;h++)sU(_[h],y)}var mb=K(null),d_=K(0);function lU(h,y){h=vu,me(d_,h),me(mb,y),vu=h|y.baseLanes}function rj(){me(d_,vu),me(mb,mb.current)}function aj(){vu=d_.current,ae(mb),ae(d_)}var Xo=K(null),Dl=null;function Zm(h){var y=h.alternate;me(ai,ai.current&1),me(Xo,h),Dl===null&&(y===null||mb.current!==null||y.memoizedState!==null)&&(Dl=h)}function ij(h){me(ai,ai.current),me(Xo,h),Dl===null&&(Dl=h)}function cU(h){h.tag===22?(me(ai,ai.current),me(Xo,h),Dl===null&&(Dl=h)):eh()}function eh(){me(ai,ai.current),me(Xo,Xo.current)}function Yo(h){ae(Xo),Dl===h&&(Dl=null),ae(ai)}var ai=K(0);function u_(h){for(var y=h;y!==null;){if(y.tag===13){var _=y.memoizedState;if(_!==null&&(_=_.dehydrated,_===null||uM(_)||mM(_)))return y}else if(y.tag===19&&(y.memoizedProps.revealOrder==="forwards"||y.memoizedProps.revealOrder==="backwards"||y.memoizedProps.revealOrder==="unstable_legacy-backwards"||y.memoizedProps.revealOrder==="together")){if((y.flags&128)!==0)return y}else if(y.child!==null){y.child.return=y,y=y.child;continue}if(y===h)break;for(;y.sibling===null;){if(y.return===null||y.return===h)return null;y=y.return}y.sibling.return=y.return,y=y.sibling}return null}var mu=0,Xn=null,Xr=null,mi=null,m_=!1,hb=!1,cf=!1,h_=0,cv=0,pb=null,qce=0;function $a(){throw Error(r(321))}function sj(h,y){if(y===null)return!1;for(var _=0;_Z?Z:8;var Ne=re.T,qe={};re.T=qe,wj(h,!1,y,_);try{var lt=G(),vt=re.S;if(vt!==null&&vt(qe,lt),lt!==null&&typeof lt=="object"&&typeof lt.then=="function"){var Rt=Hce(lt,j);uv(h,y,Rt,Zo(h))}else uv(h,y,j,Zo(h))}catch(Ut){uv(h,y,{then:function(){},status:"rejected",reason:Ut},Zo())}finally{ee.p=Z,Ne!==null&&qe.types!==null&&(Ne.types=qe.types),re.T=Ne}}function Kce(){}function yj(h,y,_,j){if(h.tag!==5)throw Error(r(476));var G=zU(h).queue;IU(h,G,y,ue,_===null?Kce:function(){return UU(h),_(j)})}function zU(h){var y=h.memoizedState;if(y!==null)return y;y={memoizedState:ue,baseState:ue,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:hu,lastRenderedState:ue},next:null};var _={};return y.next={memoizedState:_,baseState:_,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:hu,lastRenderedState:_},next:null},h.memoizedState=y,h=h.alternate,h!==null&&(h.memoizedState=y),y}function UU(h){var y=zU(h);y.next===null&&(y=h.alternate.memoizedState),uv(h,y.next.queue,{},Zo())}function vj(){return ds(Tv)}function BU(){return ii().memoizedState}function HU(){return ii().memoizedState}function Xce(h){for(var y=h.return;y!==null;){switch(y.tag){case 24:case 3:var _=Zo();h=Qm(_);var j=Jm(y,h,_);j!==null&&(To(j,y,_),sv(j,y,_)),y={cache:XA()},h.payload=y;return}y=y.return}}function Yce(h,y,_){var j=Zo();_={lane:j,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null},y_(h)?$U(y,_):(_=IA(h,y,_,j),_!==null&&(To(_,h,j),VU(_,y,j)))}function qU(h,y,_){var j=Zo();uv(h,y,_,j)}function uv(h,y,_,j){var G={lane:j,revertLane:0,gesture:null,action:_,hasEagerState:!1,eagerState:null,next:null};if(y_(h))$U(y,G);else{var Z=h.alternate;if(h.lanes===0&&(Z===null||Z.lanes===0)&&(Z=y.lastRenderedReducer,Z!==null))try{var Ne=y.lastRenderedState,qe=Z(Ne,_);if(G.hasEagerState=!0,G.eagerState=qe,_o(qe,Ne))return ZS(h,y,G,0),oa===null&&JS(),!1}catch{}if(_=IA(h,y,G,j),_!==null)return To(_,h,j),VU(_,y,j),!0}return!1}function wj(h,y,_,j){if(j={lane:2,revertLane:Zj(),gesture:null,action:j,hasEagerState:!1,eagerState:null,next:null},y_(h)){if(y)throw Error(r(479))}else y=IA(h,_,j,2),y!==null&&To(y,h,2)}function y_(h){var y=h.alternate;return h===Xn||y!==null&&y===Xn}function $U(h,y){hb=m_=!0;var _=h.pending;_===null?y.next=y:(y.next=_.next,_.next=y),h.pending=y}function VU(h,y,_){if((_&4194048)!==0){var j=y.lanes;j&=h.pendingLanes,_|=j,y.lanes=_,qt(h,_)}}var mv={readContext:ds,use:f_,useCallback:$a,useContext:$a,useEffect:$a,useImperativeHandle:$a,useLayoutEffect:$a,useInsertionEffect:$a,useMemo:$a,useReducer:$a,useRef:$a,useState:$a,useDebugValue:$a,useDeferredValue:$a,useTransition:$a,useSyncExternalStore:$a,useId:$a,useHostTransitionStatus:$a,useFormState:$a,useActionState:$a,useOptimistic:$a,useMemoCache:$a,useCacheRefresh:$a};mv.useEffectEvent=$a;var GU={readContext:ds,use:f_,useCallback:function(h,y){return Zs().memoizedState=[h,y===void 0?null:y],h},useContext:ds,useEffect:AU,useImperativeHandle:function(h,y,_){_=_!=null?_.concat([h]):null,b_(4194308,4,DU.bind(null,y,h),_)},useLayoutEffect:function(h,y){return b_(4194308,4,h,y)},useInsertionEffect:function(h,y){b_(4,2,h,y)},useMemo:function(h,y){var _=Zs();y=y===void 0?null:y;var j=h();if(cf){Me(!0);try{h()}finally{Me(!1)}}return _.memoizedState=[j,y],j},useReducer:function(h,y,_){var j=Zs();if(_!==void 0){var G=_(y);if(cf){Me(!0);try{_(y)}finally{Me(!1)}}}else G=y;return j.memoizedState=j.baseState=G,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:G},j.queue=h,h=h.dispatch=Yce.bind(null,Xn,h),[j.memoizedState,h]},useRef:function(h){var y=Zs();return h={current:h},y.memoizedState=h},useState:function(h){h=pj(h);var y=h.queue,_=qU.bind(null,Xn,y);return y.dispatch=_,[h.memoizedState,_]},useDebugValue:bj,useDeferredValue:function(h,y){var _=Zs();return xj(_,h,y)},useTransition:function(){var h=pj(!1);return h=IU.bind(null,Xn,h.queue,!0,!1),Zs().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,y,_){var j=Xn,G=Zs();if(Sr){if(_===void 0)throw Error(r(407));_=_()}else{if(_=y(),oa===null)throw Error(r(349));(yr&127)!==0||hU(j,y,_)}G.memoizedState=_;var Z={value:_,getSnapshot:y};return G.queue=Z,AU(fU.bind(null,j,Z,h),[h]),j.flags|=2048,fb(9,{destroy:void 0},pU.bind(null,j,Z,_,y),null),_},useId:function(){var h=Zs(),y=oa.identifierPrefix;if(Sr){var _=cd,j=ld;_=(j&~(1<<32-Ie(j)-1)).toString(32)+_,y="_"+y+"R_"+_,_=h_++,0<_&&(y+="H"+_.toString(32)),y+="_"}else _=qce++,y="_"+y+"r_"+_.toString(32)+"_";return h.memoizedState=y},useHostTransitionStatus:vj,useFormState:kU,useActionState:kU,useOptimistic:function(h){var y=Zs();y.memoizedState=y.baseState=h;var _={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return y.queue=_,y=wj.bind(null,Xn,!0,_),_.dispatch=y,[h,y]},useMemoCache:uj,useCacheRefresh:function(){return Zs().memoizedState=Xce.bind(null,Xn)},useEffectEvent:function(h){var y=Zs(),_={impl:h};return y.memoizedState=_,function(){if((Lr&2)!==0)throw Error(r(440));return _.impl.apply(void 0,arguments)}}},Sj={readContext:ds,use:f_,useCallback:RU,useContext:ds,useEffect:gj,useImperativeHandle:FU,useInsertionEffect:MU,useLayoutEffect:EU,useMemo:LU,useReducer:g_,useRef:TU,useState:function(){return g_(hu)},useDebugValue:bj,useDeferredValue:function(h,y){var _=ii();return OU(_,Xr.memoizedState,h,y)},useTransition:function(){var h=g_(hu)[0],y=ii().memoizedState;return[typeof h=="boolean"?h:dv(h),y]},useSyncExternalStore:mU,useId:BU,useHostTransitionStatus:vj,useFormState:NU,useActionState:NU,useOptimistic:function(h,y){var _=ii();return xU(_,Xr,h,y)},useMemoCache:uj,useCacheRefresh:HU};Sj.useEffectEvent=jU;var WU={readContext:ds,use:f_,useCallback:RU,useContext:ds,useEffect:gj,useImperativeHandle:FU,useInsertionEffect:MU,useLayoutEffect:EU,useMemo:LU,useReducer:hj,useRef:TU,useState:function(){return hj(hu)},useDebugValue:bj,useDeferredValue:function(h,y){var _=ii();return Xr===null?xj(_,h,y):OU(_,Xr.memoizedState,h,y)},useTransition:function(){var h=hj(hu)[0],y=ii().memoizedState;return[typeof h=="boolean"?h:dv(h),y]},useSyncExternalStore:mU,useId:BU,useHostTransitionStatus:vj,useFormState:PU,useActionState:PU,useOptimistic:function(h,y){var _=ii();return Xr!==null?xU(_,Xr,h,y):(_.baseState=h,[h,_.queue.dispatch])},useMemoCache:uj,useCacheRefresh:HU};WU.useEffectEvent=jU;function _j(h,y,_,j){y=h.memoizedState,_=_(j,y),_=_==null?y:m({},y,_),h.memoizedState=_,h.lanes===0&&(h.updateQueue.baseState=_)}var kj={enqueueSetState:function(h,y,_){h=h._reactInternals;var j=Zo(),G=Qm(j);G.payload=y,_!=null&&(G.callback=_),y=Jm(h,G,j),y!==null&&(To(y,h,j),sv(y,h,j))},enqueueReplaceState:function(h,y,_){h=h._reactInternals;var j=Zo(),G=Qm(j);G.tag=1,G.payload=y,_!=null&&(G.callback=_),y=Jm(h,G,j),y!==null&&(To(y,h,j),sv(y,h,j))},enqueueForceUpdate:function(h,y){h=h._reactInternals;var _=Zo(),j=Qm(_);j.tag=2,y!=null&&(j.callback=y),y=Jm(h,j,_),y!==null&&(To(y,h,_),sv(y,h,_))}};function KU(h,y,_,j,G,Z,Ne){return h=h.stateNode,typeof h.shouldComponentUpdate=="function"?h.shouldComponentUpdate(j,Z,Ne):y.prototype&&y.prototype.isPureReactComponent?!Vm(_,j)||!Vm(G,Z):!0}function XU(h,y,_,j){h=y.state,typeof y.componentWillReceiveProps=="function"&&y.componentWillReceiveProps(_,j),typeof y.UNSAFE_componentWillReceiveProps=="function"&&y.UNSAFE_componentWillReceiveProps(_,j),y.state!==h&&kj.enqueueReplaceState(y,y.state,null)}function df(h,y){var _=y;if("ref"in y){_={};for(var j in y)j!=="ref"&&(_[j]=y[j])}if(h=h.defaultProps){_===y&&(_=m({},_));for(var G in h)_[G]===void 0&&(_[G]=h[G])}return _}function YU(h){QS(h)}function QU(h){console.error(h)}function JU(h){QS(h)}function v_(h,y){try{var _=h.onUncaughtError;_(y.value,{componentStack:y.stack})}catch(j){setTimeout(function(){throw j})}}function ZU(h,y,_){try{var j=h.onCaughtError;j(_.value,{componentStack:_.stack,errorBoundary:y.tag===1?y.stateNode:null})}catch(G){setTimeout(function(){throw G})}}function Nj(h,y,_){return _=Qm(_),_.tag=3,_.payload={element:null},_.callback=function(){v_(h,y)},_}function eB(h){return h=Qm(h),h.tag=3,h}function tB(h,y,_,j){var G=_.type.getDerivedStateFromError;if(typeof G=="function"){var Z=j.value;h.payload=function(){return G(Z)},h.callback=function(){ZU(y,_,j)}}var Ne=_.stateNode;Ne!==null&&typeof Ne.componentDidCatch=="function"&&(h.callback=function(){ZU(y,_,j),typeof G!="function"&&(ah===null?ah=new Set([this]):ah.add(this));var qe=j.stack;this.componentDidCatch(j.value,{componentStack:qe!==null?qe:""})})}function Qce(h,y,_,j,G){if(_.flags|=32768,j!==null&&typeof j=="object"&&typeof j.then=="function"){if(y=_.alternate,y!==null&&ob(y,_,G,!0),_=Xo.current,_!==null){switch(_.tag){case 31:case 13:return Dl===null?E_():_.alternate===null&&Va===0&&(Va=3),_.flags&=-257,_.flags|=65536,_.lanes=G,j===o_?_.flags|=16384:(y=_.updateQueue,y===null?_.updateQueue=new Set([j]):y.add(j),Yj(h,j,G)),!1;case 22:return _.flags|=65536,j===o_?_.flags|=16384:(y=_.updateQueue,y===null?(y={transitions:null,markerInstances:null,retryQueue:new Set([j])},_.updateQueue=y):(_=y.retryQueue,_===null?y.retryQueue=new Set([j]):_.add(j)),Yj(h,j,G)),!1}throw Error(r(435,_.tag))}return Yj(h,j,G),E_(),!1}if(Sr)return y=Xo.current,y!==null?((y.flags&65536)===0&&(y.flags|=256),y.flags|=65536,y.lanes=G,j!==$A&&(h=Error(r(422),{cause:j}),tv(Al(h,_)))):(j!==$A&&(y=Error(r(423),{cause:j}),tv(Al(y,_))),h=h.current.alternate,h.flags|=65536,G&=-G,h.lanes|=G,j=Al(j,_),G=Nj(h.stateNode,j,G),tj(h,G),Va!==4&&(Va=2)),!1;var Z=Error(r(520),{cause:j});if(Z=Al(Z,_),vv===null?vv=[Z]:vv.push(Z),Va!==4&&(Va=2),y===null)return!0;j=Al(j,_),_=y;do{switch(_.tag){case 3:return _.flags|=65536,h=G&-G,_.lanes|=h,h=Nj(_.stateNode,j,h),tj(_,h),!1;case 1:if(y=_.type,Z=_.stateNode,(_.flags&128)===0&&(typeof y.getDerivedStateFromError=="function"||Z!==null&&typeof Z.componentDidCatch=="function"&&(ah===null||!ah.has(Z))))return _.flags|=65536,G&=-G,_.lanes|=G,G=eB(G),tB(G,h,_,j),tj(_,G),!1}_=_.return}while(_!==null);return!1}var Cj=Error(r(461)),hi=!1;function us(h,y,_,j){y.child=h===null?iU(y,null,_,j):lf(y,h.child,_,j)}function nB(h,y,_,j,G){_=_.render;var Z=y.ref;if("ref"in j){var Ne={};for(var qe in j)qe!=="ref"&&(Ne[qe]=j[qe])}else Ne=j;return rf(y),j=oj(h,y,_,Ne,Z,G),qe=lj(),h!==null&&!hi?(cj(h,y,G),pu(h,y,G)):(Sr&&qe&&HA(y),y.flags|=1,us(h,y,j,G),y.child)}function rB(h,y,_,j,G){if(h===null){var Z=_.type;return typeof Z=="function"&&!zA(Z)&&Z.defaultProps===void 0&&_.compare===null?(y.tag=15,y.type=Z,aB(h,y,Z,j,G)):(h=t_(_.type,null,j,y,y.mode,G),h.ref=y.ref,h.return=y,y.child=h)}if(Z=h.child,!Fj(h,G)){var Ne=Z.memoizedProps;if(_=_.compare,_=_!==null?_:Vm,_(Ne,j)&&h.ref===y.ref)return pu(h,y,G)}return y.flags|=1,h=lu(Z,j),h.ref=y.ref,h.return=y,y.child=h}function aB(h,y,_,j,G){if(h!==null){var Z=h.memoizedProps;if(Vm(Z,j)&&h.ref===y.ref)if(hi=!1,y.pendingProps=j=Z,Fj(h,G))(h.flags&131072)!==0&&(hi=!0);else return y.lanes=h.lanes,pu(h,y,G)}return Pj(h,y,_,j,G)}function iB(h,y,_,j){var G=j.children,Z=h!==null?h.memoizedState:null;if(h===null&&y.stateNode===null&&(y.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),j.mode==="hidden"){if((y.flags&128)!==0){if(Z=Z!==null?Z.baseLanes|_:_,h!==null){for(j=y.child=h.child,G=0;j!==null;)G=G|j.lanes|j.childLanes,j=j.sibling;j=G&~Z}else j=0,y.child=null;return sB(h,y,Z,_,j)}if((_&536870912)!==0)y.memoizedState={baseLanes:0,cachePool:null},h!==null&&i_(y,Z!==null?Z.cachePool:null),Z!==null?lU(y,Z):rj(),cU(y);else return j=y.lanes=536870912,sB(h,y,Z!==null?Z.baseLanes|_:_,_,j)}else Z!==null?(i_(y,Z.cachePool),lU(y,Z),eh(),y.memoizedState=null):(h!==null&&i_(y,null),rj(),eh());return us(h,y,G,_),y.child}function hv(h,y){return h!==null&&h.tag===22||y.stateNode!==null||(y.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),y.sibling}function sB(h,y,_,j,G){var Z=QA();return Z=Z===null?null:{parent:ui._currentValue,pool:Z},y.memoizedState={baseLanes:_,cachePool:Z},h!==null&&i_(y,null),rj(),cU(y),h!==null&&ob(h,y,j,!0),y.childLanes=G,null}function w_(h,y){return y=__({mode:y.mode,children:y.children},h.mode),y.ref=h.ref,h.child=y,y.return=h,y}function oB(h,y,_){return lf(y,h.child,null,_),h=w_(y,y.pendingProps),h.flags|=2,Yo(y),y.memoizedState=null,h}function Jce(h,y,_){var j=y.pendingProps,G=(y.flags&128)!==0;if(y.flags&=-129,h===null){if(Sr){if(j.mode==="hidden")return h=w_(y,j),y.lanes=536870912,hv(null,h);if(ij(y),(h=xa)?(h=y8(h,El),h=h!==null&&h.data==="&"?h:null,h!==null&&(y.memoizedState={dehydrated:h,treeContext:Gm!==null?{id:ld,overflow:cd}:null,retryLane:536870912,hydrationErrors:null},_=$5(h),_.return=y,y.child=_,cs=y,xa=null)):h=null,h===null)throw Km(y);return y.lanes=536870912,null}return w_(y,j)}var Z=h.memoizedState;if(Z!==null){var Ne=Z.dehydrated;if(ij(y),G)if(y.flags&256)y.flags&=-257,y=oB(h,y,_);else if(y.memoizedState!==null)y.child=h.child,y.flags|=128,y=null;else throw Error(r(558));else if(hi||ob(h,y,_,!1),G=(_&h.childLanes)!==0,hi||G){if(j=oa,j!==null&&(Ne=Vt(j,_),Ne!==0&&Ne!==Z.retryLane))throw Z.retryLane=Ne,Zp(h,Ne),To(j,h,Ne),Cj;E_(),y=oB(h,y,_)}else h=Z.treeContext,xa=Fl(Ne.nextSibling),cs=y,Sr=!0,Wm=null,El=!1,h!==null&&W5(y,h),y=w_(y,j),y.flags|=4096;return y}return h=lu(h.child,{mode:j.mode,children:j.children}),h.ref=y.ref,y.child=h,h.return=y,h}function S_(h,y){var _=y.ref;if(_===null)h!==null&&h.ref!==null&&(y.flags|=4194816);else{if(typeof _!="function"&&typeof _!="object")throw Error(r(284));(h===null||h.ref!==_)&&(y.flags|=4194816)}}function Pj(h,y,_,j,G){return rf(y),_=oj(h,y,_,j,void 0,G),j=lj(),h!==null&&!hi?(cj(h,y,G),pu(h,y,G)):(Sr&&j&&HA(y),y.flags|=1,us(h,y,_,G),y.child)}function lB(h,y,_,j,G,Z){return rf(y),y.updateQueue=null,_=uU(y,j,_,G),dU(h),j=lj(),h!==null&&!hi?(cj(h,y,Z),pu(h,y,Z)):(Sr&&j&&HA(y),y.flags|=1,us(h,y,_,Z),y.child)}function cB(h,y,_,j,G){if(rf(y),y.stateNode===null){var Z=rb,Ne=_.contextType;typeof Ne=="object"&&Ne!==null&&(Z=ds(Ne)),Z=new _(j,Z),y.memoizedState=Z.state!==null&&Z.state!==void 0?Z.state:null,Z.updater=kj,y.stateNode=Z,Z._reactInternals=y,Z=y.stateNode,Z.props=j,Z.state=y.memoizedState,Z.refs={},ZA(y),Ne=_.contextType,Z.context=typeof Ne=="object"&&Ne!==null?ds(Ne):rb,Z.state=y.memoizedState,Ne=_.getDerivedStateFromProps,typeof Ne=="function"&&(_j(y,_,Ne,j),Z.state=y.memoizedState),typeof _.getDerivedStateFromProps=="function"||typeof Z.getSnapshotBeforeUpdate=="function"||typeof Z.UNSAFE_componentWillMount!="function"&&typeof Z.componentWillMount!="function"||(Ne=Z.state,typeof Z.componentWillMount=="function"&&Z.componentWillMount(),typeof Z.UNSAFE_componentWillMount=="function"&&Z.UNSAFE_componentWillMount(),Ne!==Z.state&&kj.enqueueReplaceState(Z,Z.state,null),lv(y,j,Z,G),ov(),Z.state=y.memoizedState),typeof Z.componentDidMount=="function"&&(y.flags|=4194308),j=!0}else if(h===null){Z=y.stateNode;var qe=y.memoizedProps,lt=df(_,qe);Z.props=lt;var vt=Z.context,Rt=_.contextType;Ne=rb,typeof Rt=="object"&&Rt!==null&&(Ne=ds(Rt));var Ut=_.getDerivedStateFromProps;Rt=typeof Ut=="function"||typeof Z.getSnapshotBeforeUpdate=="function",qe=y.pendingProps!==qe,Rt||typeof Z.UNSAFE_componentWillReceiveProps!="function"&&typeof Z.componentWillReceiveProps!="function"||(qe||vt!==Ne)&&XU(y,Z,j,Ne),Ym=!1;var _t=y.memoizedState;Z.state=_t,lv(y,j,Z,G),ov(),vt=y.memoizedState,qe||_t!==vt||Ym?(typeof Ut=="function"&&(_j(y,_,Ut,j),vt=y.memoizedState),(lt=Ym||KU(y,_,lt,j,_t,vt,Ne))?(Rt||typeof Z.UNSAFE_componentWillMount!="function"&&typeof Z.componentWillMount!="function"||(typeof Z.componentWillMount=="function"&&Z.componentWillMount(),typeof Z.UNSAFE_componentWillMount=="function"&&Z.UNSAFE_componentWillMount()),typeof Z.componentDidMount=="function"&&(y.flags|=4194308)):(typeof Z.componentDidMount=="function"&&(y.flags|=4194308),y.memoizedProps=j,y.memoizedState=vt),Z.props=j,Z.state=vt,Z.context=Ne,j=lt):(typeof Z.componentDidMount=="function"&&(y.flags|=4194308),j=!1)}else{Z=y.stateNode,ej(h,y),Ne=y.memoizedProps,Rt=df(_,Ne),Z.props=Rt,Ut=y.pendingProps,_t=Z.context,vt=_.contextType,lt=rb,typeof vt=="object"&&vt!==null&&(lt=ds(vt)),qe=_.getDerivedStateFromProps,(vt=typeof qe=="function"||typeof Z.getSnapshotBeforeUpdate=="function")||typeof Z.UNSAFE_componentWillReceiveProps!="function"&&typeof Z.componentWillReceiveProps!="function"||(Ne!==Ut||_t!==lt)&&XU(y,Z,j,lt),Ym=!1,_t=y.memoizedState,Z.state=_t,lv(y,j,Z,G),ov();var At=y.memoizedState;Ne!==Ut||_t!==At||Ym||h!==null&&h.dependencies!==null&&r_(h.dependencies)?(typeof qe=="function"&&(_j(y,_,qe,j),At=y.memoizedState),(Rt=Ym||KU(y,_,Rt,j,_t,At,lt)||h!==null&&h.dependencies!==null&&r_(h.dependencies))?(vt||typeof Z.UNSAFE_componentWillUpdate!="function"&&typeof Z.componentWillUpdate!="function"||(typeof Z.componentWillUpdate=="function"&&Z.componentWillUpdate(j,At,lt),typeof Z.UNSAFE_componentWillUpdate=="function"&&Z.UNSAFE_componentWillUpdate(j,At,lt)),typeof Z.componentDidUpdate=="function"&&(y.flags|=4),typeof Z.getSnapshotBeforeUpdate=="function"&&(y.flags|=1024)):(typeof Z.componentDidUpdate!="function"||Ne===h.memoizedProps&&_t===h.memoizedState||(y.flags|=4),typeof Z.getSnapshotBeforeUpdate!="function"||Ne===h.memoizedProps&&_t===h.memoizedState||(y.flags|=1024),y.memoizedProps=j,y.memoizedState=At),Z.props=j,Z.state=At,Z.context=lt,j=Rt):(typeof Z.componentDidUpdate!="function"||Ne===h.memoizedProps&&_t===h.memoizedState||(y.flags|=4),typeof Z.getSnapshotBeforeUpdate!="function"||Ne===h.memoizedProps&&_t===h.memoizedState||(y.flags|=1024),j=!1)}return Z=j,S_(h,y),j=(y.flags&128)!==0,Z||j?(Z=y.stateNode,_=j&&typeof _.getDerivedStateFromError!="function"?null:Z.render(),y.flags|=1,h!==null&&j?(y.child=lf(y,h.child,null,G),y.child=lf(y,null,_,G)):us(h,y,_,G),y.memoizedState=Z.state,h=y.child):h=pu(h,y,G),h}function dB(h,y,_,j){return tf(),y.flags|=256,us(h,y,_,j),y.child}var Tj={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Aj(h){return{baseLanes:h,cachePool:Z5()}}function jj(h,y,_){return h=h!==null?h.childLanes&~_:0,y&&(h|=Jo),h}function uB(h,y,_){var j=y.pendingProps,G=!1,Z=(y.flags&128)!==0,Ne;if((Ne=Z)||(Ne=h!==null&&h.memoizedState===null?!1:(ai.current&2)!==0),Ne&&(G=!0,y.flags&=-129),Ne=(y.flags&32)!==0,y.flags&=-33,h===null){if(Sr){if(G?Zm(y):eh(),(h=xa)?(h=y8(h,El),h=h!==null&&h.data!=="&"?h:null,h!==null&&(y.memoizedState={dehydrated:h,treeContext:Gm!==null?{id:ld,overflow:cd}:null,retryLane:536870912,hydrationErrors:null},_=$5(h),_.return=y,y.child=_,cs=y,xa=null)):h=null,h===null)throw Km(y);return mM(h)?y.lanes=32:y.lanes=536870912,null}var qe=j.children;return j=j.fallback,G?(eh(),G=y.mode,qe=__({mode:"hidden",children:qe},G),j=ef(j,G,_,null),qe.return=y,j.return=y,qe.sibling=j,y.child=qe,j=y.child,j.memoizedState=Aj(_),j.childLanes=jj(h,Ne,_),y.memoizedState=Tj,hv(null,j)):(Zm(y),Mj(y,qe))}var lt=h.memoizedState;if(lt!==null&&(qe=lt.dehydrated,qe!==null)){if(Z)y.flags&256?(Zm(y),y.flags&=-257,y=Ej(h,y,_)):y.memoizedState!==null?(eh(),y.child=h.child,y.flags|=128,y=null):(eh(),qe=j.fallback,G=y.mode,j=__({mode:"visible",children:j.children},G),qe=ef(qe,G,_,null),qe.flags|=2,j.return=y,qe.return=y,j.sibling=qe,y.child=j,lf(y,h.child,null,_),j=y.child,j.memoizedState=Aj(_),j.childLanes=jj(h,Ne,_),y.memoizedState=Tj,y=hv(null,j));else if(Zm(y),mM(qe)){if(Ne=qe.nextSibling&&qe.nextSibling.dataset,Ne)var vt=Ne.dgst;Ne=vt,j=Error(r(419)),j.stack="",j.digest=Ne,tv({value:j,source:null,stack:null}),y=Ej(h,y,_)}else if(hi||ob(h,y,_,!1),Ne=(_&h.childLanes)!==0,hi||Ne){if(Ne=oa,Ne!==null&&(j=Vt(Ne,_),j!==0&&j!==lt.retryLane))throw lt.retryLane=j,Zp(h,j),To(Ne,h,j),Cj;uM(qe)||E_(),y=Ej(h,y,_)}else uM(qe)?(y.flags|=192,y.child=h.child,y=null):(h=lt.treeContext,xa=Fl(qe.nextSibling),cs=y,Sr=!0,Wm=null,El=!1,h!==null&&W5(y,h),y=Mj(y,j.children),y.flags|=4096);return y}return G?(eh(),qe=j.fallback,G=y.mode,lt=h.child,vt=lt.sibling,j=lu(lt,{mode:"hidden",children:j.children}),j.subtreeFlags=lt.subtreeFlags&65011712,vt!==null?qe=lu(vt,qe):(qe=ef(qe,G,_,null),qe.flags|=2),qe.return=y,j.return=y,j.sibling=qe,y.child=j,hv(null,j),j=y.child,qe=h.child.memoizedState,qe===null?qe=Aj(_):(G=qe.cachePool,G!==null?(lt=ui._currentValue,G=G.parent!==lt?{parent:lt,pool:lt}:G):G=Z5(),qe={baseLanes:qe.baseLanes|_,cachePool:G}),j.memoizedState=qe,j.childLanes=jj(h,Ne,_),y.memoizedState=Tj,hv(h.child,j)):(Zm(y),_=h.child,h=_.sibling,_=lu(_,{mode:"visible",children:j.children}),_.return=y,_.sibling=null,h!==null&&(Ne=y.deletions,Ne===null?(y.deletions=[h],y.flags|=16):Ne.push(h)),y.child=_,y.memoizedState=null,_)}function Mj(h,y){return y=__({mode:"visible",children:y},h.mode),y.return=h,h.child=y}function __(h,y){return h=Ko(22,h,null,y),h.lanes=0,h}function Ej(h,y,_){return lf(y,h.child,null,_),h=Mj(y,y.pendingProps.children),h.flags|=2,y.memoizedState=null,h}function mB(h,y,_){h.lanes|=y;var j=h.alternate;j!==null&&(j.lanes|=y),WA(h.return,y,_)}function Dj(h,y,_,j,G,Z){var Ne=h.memoizedState;Ne===null?h.memoizedState={isBackwards:y,rendering:null,renderingStartTime:0,last:j,tail:_,tailMode:G,treeForkCount:Z}:(Ne.isBackwards=y,Ne.rendering=null,Ne.renderingStartTime=0,Ne.last=j,Ne.tail=_,Ne.tailMode=G,Ne.treeForkCount=Z)}function hB(h,y,_){var j=y.pendingProps,G=j.revealOrder,Z=j.tail;j=j.children;var Ne=ai.current,qe=(Ne&2)!==0;if(qe?(Ne=Ne&1|2,y.flags|=128):Ne&=1,me(ai,Ne),us(h,y,j,_),j=Sr?ev:0,!qe&&h!==null&&(h.flags&128)!==0)e:for(h=y.child;h!==null;){if(h.tag===13)h.memoizedState!==null&&mB(h,_,y);else if(h.tag===19)mB(h,_,y);else if(h.child!==null){h.child.return=h,h=h.child;continue}if(h===y)break e;for(;h.sibling===null;){if(h.return===null||h.return===y)break e;h=h.return}h.sibling.return=h.return,h=h.sibling}switch(G){case"forwards":for(_=y.child,G=null;_!==null;)h=_.alternate,h!==null&&u_(h)===null&&(G=_),_=_.sibling;_=G,_===null?(G=y.child,y.child=null):(G=_.sibling,_.sibling=null),Dj(y,!1,G,_,Z,j);break;case"backwards":case"unstable_legacy-backwards":for(_=null,G=y.child,y.child=null;G!==null;){if(h=G.alternate,h!==null&&u_(h)===null){y.child=G;break}h=G.sibling,G.sibling=_,_=G,G=h}Dj(y,!0,_,null,Z,j);break;case"together":Dj(y,!1,null,null,void 0,j);break;default:y.memoizedState=null}return y.child}function pu(h,y,_){if(h!==null&&(y.dependencies=h.dependencies),rh|=y.lanes,(_&y.childLanes)===0)if(h!==null){if(ob(h,y,_,!1),(_&y.childLanes)===0)return null}else return null;if(h!==null&&y.child!==h.child)throw Error(r(153));if(y.child!==null){for(h=y.child,_=lu(h,h.pendingProps),y.child=_,_.return=y;h.sibling!==null;)h=h.sibling,_=_.sibling=lu(h,h.pendingProps),_.return=y;_.sibling=null}return y.child}function Fj(h,y){return(h.lanes&y)!==0?!0:(h=h.dependencies,!!(h!==null&&r_(h)))}function Zce(h,y,_){switch(y.tag){case 3:D(y,y.stateNode.containerInfo),Xm(y,ui,h.memoizedState.cache),tf();break;case 27:case 5:U(y);break;case 4:D(y,y.stateNode.containerInfo);break;case 10:Xm(y,y.type,y.memoizedProps.value);break;case 31:if(y.memoizedState!==null)return y.flags|=128,ij(y),null;break;case 13:var j=y.memoizedState;if(j!==null)return j.dehydrated!==null?(Zm(y),y.flags|=128,null):(_&y.child.childLanes)!==0?uB(h,y,_):(Zm(y),h=pu(h,y,_),h!==null?h.sibling:null);Zm(y);break;case 19:var G=(h.flags&128)!==0;if(j=(_&y.childLanes)!==0,j||(ob(h,y,_,!1),j=(_&y.childLanes)!==0),G){if(j)return hB(h,y,_);y.flags|=128}if(G=y.memoizedState,G!==null&&(G.rendering=null,G.tail=null,G.lastEffect=null),me(ai,ai.current),j)break;return null;case 22:return y.lanes=0,iB(h,y,_,y.pendingProps);case 24:Xm(y,ui,h.memoizedState.cache)}return pu(h,y,_)}function pB(h,y,_){if(h!==null)if(h.memoizedProps!==y.pendingProps)hi=!0;else{if(!Fj(h,_)&&(y.flags&128)===0)return hi=!1,Zce(h,y,_);hi=(h.flags&131072)!==0}else hi=!1,Sr&&(y.flags&1048576)!==0&&G5(y,ev,y.index);switch(y.lanes=0,y.tag){case 16:e:{var j=y.pendingProps;if(h=sf(y.elementType),y.type=h,typeof h=="function")zA(h)?(j=df(h,j),y.tag=1,y=cB(null,y,h,j,_)):(y.tag=0,y=Pj(null,y,h,j,_));else{if(h!=null){var G=h.$$typeof;if(G===P){y.tag=11,y=nB(null,y,h,j,_);break e}else if(G===T){y.tag=14,y=rB(null,y,h,j,_);break e}}throw y=L(h)||h,Error(r(306,y,""))}}return y;case 0:return Pj(h,y,y.type,y.pendingProps,_);case 1:return j=y.type,G=df(j,y.pendingProps),cB(h,y,j,G,_);case 3:e:{if(D(y,y.stateNode.containerInfo),h===null)throw Error(r(387));j=y.pendingProps;var Z=y.memoizedState;G=Z.element,ej(h,y),lv(y,j,null,_);var Ne=y.memoizedState;if(j=Ne.cache,Xm(y,ui,j),j!==Z.cache&&KA(y,[ui],_,!0),ov(),j=Ne.element,Z.isDehydrated)if(Z={element:j,isDehydrated:!1,cache:Ne.cache},y.updateQueue.baseState=Z,y.memoizedState=Z,y.flags&256){y=dB(h,y,j,_);break e}else if(j!==G){G=Al(Error(r(424)),y),tv(G),y=dB(h,y,j,_);break e}else for(h=y.stateNode.containerInfo,h.nodeType===9?h=h.body:h=h.nodeName==="HTML"?h.ownerDocument.body:h,xa=Fl(h.firstChild),cs=y,Sr=!0,Wm=null,El=!0,_=iU(y,null,j,_),y.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling;else{if(tf(),j===G){y=pu(h,y,_);break e}us(h,y,j,_)}y=y.child}return y;case 26:return S_(h,y),h===null?(_=N8(y.type,null,y.pendingProps,null))?y.memoizedState=_:Sr||(_=y.type,h=y.pendingProps,j=z_(B.current).createElement(_),j[jt]=y,j[Jt]=h,ms(j,_,h),nt(j),y.stateNode=j):y.memoizedState=N8(y.type,h.memoizedProps,y.pendingProps,h.memoizedState),null;case 27:return U(y),h===null&&Sr&&(j=y.stateNode=S8(y.type,y.pendingProps,B.current),cs=y,El=!0,G=xa,lh(y.type)?(hM=G,xa=Fl(j.firstChild)):xa=G),us(h,y,y.pendingProps.children,_),S_(h,y),h===null&&(y.flags|=4194304),y.child;case 5:return h===null&&Sr&&((G=j=xa)&&(j=Ade(j,y.type,y.pendingProps,El),j!==null?(y.stateNode=j,cs=y,xa=Fl(j.firstChild),El=!1,G=!0):G=!1),G||Km(y)),U(y),G=y.type,Z=y.pendingProps,Ne=h!==null?h.memoizedProps:null,j=Z.children,lM(G,Z)?j=null:Ne!==null&&lM(G,Ne)&&(y.flags|=32),y.memoizedState!==null&&(G=oj(h,y,$ce,null,null,_),Tv._currentValue=G),S_(h,y),us(h,y,j,_),y.child;case 6:return h===null&&Sr&&((h=_=xa)&&(_=jde(_,y.pendingProps,El),_!==null?(y.stateNode=_,cs=y,xa=null,h=!0):h=!1),h||Km(y)),null;case 13:return uB(h,y,_);case 4:return D(y,y.stateNode.containerInfo),j=y.pendingProps,h===null?y.child=lf(y,null,j,_):us(h,y,j,_),y.child;case 11:return nB(h,y,y.type,y.pendingProps,_);case 7:return us(h,y,y.pendingProps,_),y.child;case 8:return us(h,y,y.pendingProps.children,_),y.child;case 12:return us(h,y,y.pendingProps.children,_),y.child;case 10:return j=y.pendingProps,Xm(y,y.type,j.value),us(h,y,j.children,_),y.child;case 9:return G=y.type._context,j=y.pendingProps.children,rf(y),G=ds(G),j=j(G),y.flags|=1,us(h,y,j,_),y.child;case 14:return rB(h,y,y.type,y.pendingProps,_);case 15:return aB(h,y,y.type,y.pendingProps,_);case 19:return hB(h,y,_);case 31:return Jce(h,y,_);case 22:return iB(h,y,_,y.pendingProps);case 24:return rf(y),j=ds(ui),h===null?(G=QA(),G===null&&(G=oa,Z=XA(),G.pooledCache=Z,Z.refCount++,Z!==null&&(G.pooledCacheLanes|=_),G=Z),y.memoizedState={parent:j,cache:G},ZA(y),Xm(y,ui,G)):((h.lanes&_)!==0&&(ej(h,y),lv(y,null,null,_),ov()),G=h.memoizedState,Z=y.memoizedState,G.parent!==j?(G={parent:j,cache:j},y.memoizedState=G,y.lanes===0&&(y.memoizedState=y.updateQueue.baseState=G),Xm(y,ui,j)):(j=Z.cache,Xm(y,ui,j),j!==G.cache&&KA(y,[ui],_,!0))),us(h,y,y.pendingProps.children,_),y.child;case 29:throw y.pendingProps}throw Error(r(156,y.tag))}function fu(h){h.flags|=4}function Rj(h,y,_,j,G){if((y=(h.mode&32)!==0)&&(y=!1),y){if(h.flags|=16777216,(G&335544128)===G)if(h.stateNode.complete)h.flags|=8192;else if(BB())h.flags|=8192;else throw of=o_,JA}else h.flags&=-16777217}function fB(h,y){if(y.type!=="stylesheet"||(y.state.loading&4)!==0)h.flags&=-16777217;else if(h.flags|=16777216,!j8(y))if(BB())h.flags|=8192;else throw of=o_,JA}function k_(h,y){y!==null&&(h.flags|=4),h.flags&16384&&(y=h.tag!==22?st():536870912,h.lanes|=y,yb|=y)}function pv(h,y){if(!Sr)switch(h.tailMode){case"hidden":y=h.tail;for(var _=null;y!==null;)y.alternate!==null&&(_=y),y=y.sibling;_===null?h.tail=null:_.sibling=null;break;case"collapsed":_=h.tail;for(var j=null;_!==null;)_.alternate!==null&&(j=_),_=_.sibling;j===null?y||h.tail===null?h.tail=null:h.tail.sibling=null:j.sibling=null}}function ya(h){var y=h.alternate!==null&&h.alternate.child===h.child,_=0,j=0;if(y)for(var G=h.child;G!==null;)_|=G.lanes|G.childLanes,j|=G.subtreeFlags&65011712,j|=G.flags&65011712,G.return=h,G=G.sibling;else for(G=h.child;G!==null;)_|=G.lanes|G.childLanes,j|=G.subtreeFlags,j|=G.flags,G.return=h,G=G.sibling;return h.subtreeFlags|=j,h.childLanes=_,y}function ede(h,y,_){var j=y.pendingProps;switch(qA(y),y.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return ya(y),null;case 1:return ya(y),null;case 3:return _=y.stateNode,j=null,h!==null&&(j=h.memoizedState.cache),y.memoizedState.cache!==j&&(y.flags|=2048),uu(ui),M(),_.pendingContext&&(_.context=_.pendingContext,_.pendingContext=null),(h===null||h.child===null)&&(sb(y)?fu(y):h===null||h.memoizedState.isDehydrated&&(y.flags&256)===0||(y.flags|=1024,VA())),ya(y),null;case 26:var G=y.type,Z=y.memoizedState;return h===null?(fu(y),Z!==null?(ya(y),fB(y,Z)):(ya(y),Rj(y,G,null,j,_))):Z?Z!==h.memoizedState?(fu(y),ya(y),fB(y,Z)):(ya(y),y.flags&=-16777217):(h=h.memoizedProps,h!==j&&fu(y),ya(y),Rj(y,G,h,j,_)),null;case 27:if(Y(y),_=B.current,G=y.type,h!==null&&y.stateNode!=null)h.memoizedProps!==j&&fu(y);else{if(!j){if(y.stateNode===null)throw Error(r(166));return ya(y),null}h=xe.current,sb(y)?K5(y):(h=S8(G,j,_),y.stateNode=h,fu(y))}return ya(y),null;case 5:if(Y(y),G=y.type,h!==null&&y.stateNode!=null)h.memoizedProps!==j&&fu(y);else{if(!j){if(y.stateNode===null)throw Error(r(166));return ya(y),null}if(Z=xe.current,sb(y))K5(y);else{var Ne=z_(B.current);switch(Z){case 1:Z=Ne.createElementNS("http://www.w3.org/2000/svg",G);break;case 2:Z=Ne.createElementNS("http://www.w3.org/1998/Math/MathML",G);break;default:switch(G){case"svg":Z=Ne.createElementNS("http://www.w3.org/2000/svg",G);break;case"math":Z=Ne.createElementNS("http://www.w3.org/1998/Math/MathML",G);break;case"script":Z=Ne.createElement("div"),Z.innerHTML=" +