Przeglądaj źródła

feat(diagnostic): add "Store sent files on external storage" check (install step 4)

  Detects the printer-side variant of install step 4 — many users (esp. on
  clean installs) forget to enable this and only notice when their archive
  cards have no thumbnails. The diagnostic now catches it upfront.

  Detection: read state.store_to_sdcard, which Bambuddy already parses from
  MQTT push_status home_flag bit 11 (bambu_mqtt.py:153). Instant, no I/O.

  An FTP upload-and-verify probe was tried first and rejected. /cache is
  always writable from Bambuddy regardless of the slicer setting — only
  BambuStudio's own behaviour changes when the toggle flips, not the
  printer's acceptance policy. Confirmed empirically against X1C + H2D
  with the slicer option toggled off: probe succeeded, home_flag bit 11
  stayed True. So the only reliable signal is what the printer actually
  reports about its own state.

  Limitation: the printer-side variant only exists on newer firmware
  (P2S 01.02 / Bambu Studio 2.6+). On older versions the toggle lives
  only in the slicer and the printer never hears about it, so this check
  will pass even when the user is missing step 4 in BambuStudio. The
  skip-text and the wiki call this out explicitly. A reactive banner on
  the no-3MF archive-fallback path is planned as a follow-up to cover
  that case.

  Statuses:
  - pass:  state.store_to_sdcard is True
  - fail:  state.store_to_sdcard is False (-> overall escalates to problems)
  - skip:  no live state, disconnected, or field never populated
maziggy 2 miesięcy temu
rodzic
commit
60e31634b8

Plik diff jest za duży
+ 0 - 0
CHANGELOG.md


+ 28 - 1
backend/app/services/printer_diagnostic.py

@@ -160,8 +160,35 @@ async def run_connection_diagnostic(
                 )
             )
 
-    # --- MQTT credentials / connection ---
+    # --- External storage (printer-side "Store sent files on external storage") ---
+    # Install step 4. The setting has two variants depending on
+    # firmware/slicer combo: on newer firmware the toggle lives on the
+    # printer (P2S 01.02 / BambuStudio 2.6+), on older versions it's
+    # purely a slicer-side preference.
+    #
+    # For the printer-side variant, `home_flag` bit 11 is pushed on every
+    # status report and parsed into state.store_to_sdcard (bambu_mqtt.py
+    # line 153). That's the signal here — instant, no FTP I/O.
+    #
+    # For the slicer-side variant, the printer never hears about it and
+    # this check will pass even when the user is missing step 4. That gap
+    # is covered separately by the "no_3mf_available" archive-fallback
+    # banner. An FTP upload-and-verify probe was tried and rejected — the
+    # /cache directory is always writable from Bambuddy regardless of
+    # either toggle, so the probe always passes and detects nothing.
     state = printer_manager.get_status(printer.id) if printer else None
+    if state is None or not state.connected:
+        checks.append(DiagnosticCheck(id="external_storage", status="skip"))
+    elif getattr(state, "store_to_sdcard", None) is True:
+        checks.append(DiagnosticCheck(id="external_storage", status="pass"))
+    elif getattr(state, "store_to_sdcard", None) is False:
+        checks.append(DiagnosticCheck(id="external_storage", status="fail"))
+    else:
+        # State exists but the field was never populated — skip rather than
+        # report a false fail.
+        checks.append(DiagnosticCheck(id="external_storage", status="skip"))
+
+    # --- MQTT credentials / connection ---
     if not mqtt_ok:
         # Can't reach the broker at all — the port check already reported it.
         checks.append(DiagnosticCheck(id="mqtt_auth", status="skip"))

+ 62 - 3
backend/tests/unit/services/test_printer_diagnostic.py

@@ -30,8 +30,12 @@ def _port_probe(overrides=None):
     return _probe
 
 
-def _state(*, connected=True, developer_mode=True):
-    return types.SimpleNamespace(connected=connected, developer_mode=developer_mode)
+def _state(*, connected=True, developer_mode=True, store_to_sdcard=True):
+    return types.SimpleNamespace(
+        connected=connected,
+        developer_mode=developer_mode,
+        store_to_sdcard=store_to_sdcard,
+    )
 
 
 class _Env:
@@ -101,7 +105,10 @@ class TestSameSubnet:
 
 class TestExistingPrinter:
     async def test_all_healthy(self):
-        with _Env(state=_state(connected=True, developer_mode=True), report_messages_since_connect=42):
+        with _Env(
+            state=_state(connected=True, developer_mode=True, store_to_sdcard=True),
+            report_messages_since_connect=42,
+        ):
             result = await run_connection_diagnostic("192.168.1.50", printer=_printer())
         s = _statuses(result)
         assert result.overall == "ok"
@@ -111,6 +118,7 @@ class TestExistingPrinter:
             "port_rtsps": "pass",
             "network_mode": "pass",
             "subnet": "pass",
+            "external_storage": "pass",
             "mqtt_auth": "pass",
             "developer_mode": "pass",
             "printer_publishing": "pass",
@@ -236,3 +244,54 @@ class TestPreAddFlow:
         with _Env():
             result = await run_connection_diagnostic("192.168.1.50")
         assert _statuses(result)["mqtt_auth"] == "skip"
+
+
+class TestExternalStorageCheck:
+    """Install step 4 — "Store sent files on external storage".
+
+    Detected via ``state.store_to_sdcard`` (parsed from MQTT push_status
+    ``home_flag`` bit 11). Only catches the printer-side variant of the
+    setting on newer firmware (P2S 01.02 / Studio 2.6+) — the older
+    slicer-side variant is undetectable from outside the slicer and is
+    covered separately by the no-3MF archive-fallback banner.
+    """
+
+    async def test_passes_when_store_to_sdcard_true(self):
+        with _Env(state=_state(store_to_sdcard=True)):
+            result = await run_connection_diagnostic("192.168.1.50", printer=_printer())
+        assert _statuses(result)["external_storage"] == "pass"
+
+    async def test_fails_when_store_to_sdcard_false(self):
+        # Bit 11 reported as 0 -> printer-side toggle is off. Overall
+        # escalates to "problems" because a fail is present.
+        with _Env(state=_state(store_to_sdcard=False)):
+            result = await run_connection_diagnostic("192.168.1.50", printer=_printer())
+        assert _statuses(result)["external_storage"] == "fail"
+        assert result.overall == "problems"
+
+    async def test_skips_when_disconnected(self):
+        # State exists (we have a saved printer) but the MQTT connection
+        # dropped, so the latest store_to_sdcard value can't be trusted.
+        with _Env(state=_state(connected=False, store_to_sdcard=True)):
+            result = await run_connection_diagnostic("192.168.1.50", printer=_printer())
+        assert _statuses(result)["external_storage"] == "skip"
+
+    async def test_skips_pre_add_flow(self):
+        # No saved printer -> no state -> nothing to read. The check has
+        # to skip; pre-add can't probe this without a live MQTT session.
+        with _Env():
+            result = await run_connection_diagnostic(
+                "192.168.1.50",
+                serial_number="01P",
+                access_code="probe-code",
+            )
+        assert _statuses(result)["external_storage"] == "skip"
+
+    async def test_skips_when_field_missing(self):
+        # State exists and is connected but store_to_sdcard was never
+        # populated (firmware that doesn't push home_flag). Skip rather
+        # than fabricate a False from a missing field.
+        bare = types.SimpleNamespace(connected=True, developer_mode=True)
+        with _Env(state=bare):
+            result = await run_connection_diagnostic("192.168.1.50", printer=_printer())
+        assert _statuses(result)["external_storage"] == "skip"

+ 6 - 0
frontend/src/i18n/locales/de.ts

@@ -5662,6 +5662,12 @@ export default {
         pass: 'Erreichbar — das Senden von Druckdateien funktioniert.',
         warn: 'Port 990 ist nicht erreichbar. Die Überwachung funktioniert möglicherweise weiterhin, aber das Senden von Drucken an den Drucker schlägt fehl. Stellen Sie sicher, dass Port 990 nicht blockiert ist.',
       },
+      external_storage: {
+        title: 'Gesendete Dateien auf externem Speicher speichern (Installationsschritt 4)',
+        pass: 'Der Drucker meldet, dass diese Option aktiv ist — gesendete Dateien werden auf der SD-Karte gespeichert und Archive enthalten Vorschaubilder und Slicer-Metadaten.',
+        fail: 'Der Drucker meldet, dass diese Option deaktiviert ist. Aktivieren Sie "Gesendete Dateien auf externem Speicher speichern" — bei neuer Firmware (P2S 01.02 / Bambu Studio 2.6+) liegt der Schalter in den Druckeinstellungen des Druckers, bei älteren Versionen im Geräte-Tab von Bambu Studio / OrcaSlicer. Ohne diese Option fehlen jedem archivierten Druck Vorschaubild und Slicer-Metadaten.',
+        skip: 'Nicht geprüft — eine aktive MQTT-Verbindung ist erforderlich. Bei älteren Slicern, in denen diese Einstellung nur im Slicer existiert, meldet sie der Drucker nicht — diese Prüfung besteht auch dann, wenn die Option deaktiviert ist. Prüfen Sie Installationsschritt 4 in diesem Fall manuell.',
+      },
       port_rtsps: {
         title: 'Kameraport (RTSPS 322)',
         pass: 'Erreichbar — der Kamerastream funktioniert.',

+ 6 - 0
frontend/src/i18n/locales/en.ts

@@ -5675,6 +5675,12 @@ export default {
         pass: 'Reachable — sending print files will work.',
         warn: 'Port 990 is unreachable. Monitoring may still work, but sending prints to the printer will fail. Make sure port 990 is not blocked.',
       },
+      external_storage: {
+        title: 'Store sent files on external storage (install step 4)',
+        pass: 'The printer reports this option is on — sent files will be stored on the SD card and archives will have thumbnails and slicer metadata.',
+        fail: 'The printer reports this option is off. Enable "Store sent files on external storage" — on newer firmware (P2S 01.02 / Bambu Studio 2.6+) the toggle lives on the printer\'s Print Settings; on older versions it\'s in Bambu Studio / OrcaSlicer\'s Device tab. Without it, every archived print is missing its thumbnail and slicer metadata.',
+        skip: 'Not checked — needs a live MQTT connection. On older slicers where this setting lives only in the slicer the printer never reports it, so this check will pass even when the option is off — verify install step 4 manually.',
+      },
       port_rtsps: {
         title: 'Camera port (RTSPS 322)',
         pass: 'Reachable — the camera stream will work.',

+ 6 - 0
frontend/src/i18n/locales/es.ts

@@ -5671,6 +5671,12 @@ export default {
         pass: 'Accesible — el envío de archivos de impresión funcionará.',
         warn: 'El puerto 990 no es accesible. La supervisión puede seguir funcionando, pero el envío de impresiones a la impresora fallará. Asegúrese de que el puerto 990 no esté bloqueado.',
       },
+      external_storage: {
+        title: 'Almacenar archivos enviados en almacenamiento externo (paso 4 de instalación)',
+        pass: 'La impresora informa que esta opción está activada — los archivos enviados se guardarán en la tarjeta SD y los archivos tendrán miniaturas y metadatos del slicer.',
+        fail: 'La impresora informa que esta opción está desactivada. Active "Almacenar archivos enviados en almacenamiento externo" — en firmware reciente (P2S 01.02 / Bambu Studio 2.6+) el conmutador está en los Ajustes de Impresión de la impresora; en versiones anteriores está en la pestaña Dispositivo de Bambu Studio / OrcaSlicer. Sin esta opción, cada impresión archivada queda sin miniatura ni metadatos del slicer.',
+        skip: 'No comprobado — se necesita una conexión MQTT activa. En slicers más antiguos donde este ajuste solo existe en el slicer, la impresora no lo reporta, así que esta comprobación pasa aunque la opción esté desactivada — verifique el paso 4 de la instalación manualmente.',
+      },
       port_rtsps: {
         title: 'Puerto de la cámara (RTSPS 322)',
         pass: 'Accesible — la transmisión de la cámara funcionará.',

+ 6 - 0
frontend/src/i18n/locales/fr.ts

@@ -5652,6 +5652,12 @@ export default {
         pass: 'Accessible — l\'envoi de fichiers d\'impression fonctionnera.',
         warn: 'Le port 990 est inaccessible. La surveillance peut toujours fonctionner, mais l\'envoi d\'impressions vers l\'imprimante échouera. Assurez-vous que le port 990 n\'est pas bloqué.',
       },
+      external_storage: {
+        title: 'Stocker les fichiers envoyés sur stockage externe (étape 4 de l\'installation)',
+        pass: 'L\'imprimante signale que cette option est activée — les fichiers envoyés seront stockés sur la carte SD et les archives auront des miniatures et des métadonnées slicer.',
+        fail: 'L\'imprimante signale que cette option est désactivée. Activez « Stocker les fichiers envoyés sur stockage externe » — sur les firmwares récents (P2S 01.02 / Bambu Studio 2.6+) l\'interrupteur se trouve dans les Paramètres d\'impression de l\'imprimante ; sur les versions antérieures, il est dans l\'onglet Périphérique de Bambu Studio / OrcaSlicer. Sans cette option, chaque impression archivée est dépourvue de miniature et de métadonnées slicer.',
+        skip: 'Non vérifié — une connexion MQTT active est requise. Sur les slicers plus anciens où ce paramètre n\'existe que dans le slicer, l\'imprimante ne le signale pas, donc cette vérification passe même si l\'option est désactivée — vérifiez l\'étape 4 de l\'installation manuellement.',
+      },
       port_rtsps: {
         title: 'Port caméra (RTSPS 322)',
         pass: 'Accessible — le flux de la caméra fonctionnera.',

+ 6 - 0
frontend/src/i18n/locales/it.ts

@@ -5651,6 +5651,12 @@ export default {
         pass: 'Raggiungibile — l\'invio dei file di stampa funzionerà.',
         warn: 'La porta 990 non è raggiungibile. Il monitoraggio potrebbe ancora funzionare, ma l\'invio delle stampe alla stampante fallirà. Assicurati che la porta 990 non sia bloccata.',
       },
+      external_storage: {
+        title: 'Memorizza file inviati su archiviazione esterna (passo 4 dell\'installazione)',
+        pass: 'La stampante segnala che questa opzione è attiva — i file inviati saranno memorizzati sulla scheda SD e gli archivi avranno miniature e metadati dello slicer.',
+        fail: 'La stampante segnala che questa opzione è disattivata. Abilita "Memorizza file inviati su archiviazione esterna" — nei firmware recenti (P2S 01.02 / Bambu Studio 2.6+) l\'interruttore si trova nelle Impostazioni di stampa della stampante; nelle versioni precedenti è nella scheda Dispositivo di Bambu Studio / OrcaSlicer. Senza questa opzione, ogni stampa archiviata è priva di miniatura e di metadati dello slicer.',
+        skip: 'Non verificato — è necessaria una connessione MQTT attiva. Negli slicer più vecchi dove questa impostazione esiste solo nello slicer, la stampante non la segnala, quindi questo controllo passa anche se l\'opzione è disattivata — verifica manualmente il passo 4 dell\'installazione.',
+      },
       port_rtsps: {
         title: 'Porta fotocamera (RTSPS 322)',
         pass: 'Raggiungibile — lo streaming della fotocamera funzionerà.',

+ 6 - 0
frontend/src/i18n/locales/ja.ts

@@ -5663,6 +5663,12 @@ export default {
         pass: '到達可能 — 印刷ファイルの送信は機能します。',
         warn: 'ポート990に到達できません。監視は引き続き機能する場合がありますが、プリンターへの印刷送信は失敗します。ポート990がブロックされていないことを確認してください。',
       },
+      external_storage: {
+        title: '送信ファイルを外部ストレージに保存 (インストール手順4)',
+        pass: 'プリンターはこのオプションが有効と報告しています — 送信されたファイルはSDカードに保存され、アーカイブにはサムネイルとスライサーメタデータが含まれます。',
+        fail: 'プリンターはこのオプションが無効と報告しています。「送信ファイルを外部ストレージに保存」を有効にしてください — 新しいファームウェア (P2S 01.02 / Bambu Studio 2.6以降) ではプリンター本体の印刷設定にトグルがあります。古いバージョンでは Bambu Studio / OrcaSlicer のデバイスタブにあります。この設定がないと、アーカイブされた印刷にはサムネイルもスライサーメタデータも残りません。',
+        skip: '未確認 — アクティブなMQTT接続が必要です。古いスライサーでこの設定がスライサー側のみに存在する場合、プリンターはそれを報告しないため、オプションが無効でもこのチェックは通過します — インストール手順4を手動で確認してください。',
+      },
       port_rtsps: {
         title: 'カメラポート (RTSPS 322)',
         pass: '到達可能 — カメラストリームは機能します。',

+ 6 - 0
frontend/src/i18n/locales/ko.ts

@@ -5712,6 +5712,12 @@ export default {
         pass: '연결 가능 — 인쇄 파일 전송이 작동합니다.',
         warn: '포트 990에 연결할 수 없습니다. 모니터링은 작동할 수 있지만 프린터로 파일 전송에 실패합니다. 포트 990이 차단되지 않았는지 확인하세요.'
       },
+      external_storage: {
+        title: '전송된 파일을 외부 저장소에 저장 (설치 단계 4)',
+        pass: '프린터가 이 옵션이 켜져 있다고 보고합니다 — 전송된 파일이 SD 카드에 저장되며 아카이브에 썸네일과 슬라이서 메타데이터가 포함됩니다.',
+        fail: '프린터가 이 옵션이 꺼져 있다고 보고합니다. "전송된 파일을 외부 저장소에 저장"을 활성화하세요 — 최신 펌웨어 (P2S 01.02 / Bambu Studio 2.6 이상)에서는 프린터의 인쇄 설정에 토글이 있고, 이전 버전에서는 Bambu Studio / OrcaSlicer의 장치 탭에 있습니다. 이 옵션이 없으면 아카이브된 모든 인쇄물에 썸네일과 슬라이서 메타데이터가 없습니다.',
+        skip: '확인되지 않음 — 활성 MQTT 연결이 필요합니다. 이 설정이 슬라이서에만 존재하는 이전 슬라이서에서는 프린터가 보고하지 않으므로, 옵션이 꺼져 있어도 이 검사는 통과합니다 — 설치 단계 4를 수동으로 확인하세요.'
+      },
       port_rtsps: {
         title: '카메라 포트 (RTSPS 322)',
         pass: '연결 가능 — 카메라 스트림이 작동합니다.',

+ 6 - 0
frontend/src/i18n/locales/pt-BR.ts

@@ -5651,6 +5651,12 @@ export default {
         pass: 'Acessível — o envio de arquivos de impressão funcionará.',
         warn: 'A porta 990 está inacessível. O monitoramento ainda pode funcionar, mas o envio de impressões para a impressora falhará. Verifique se a porta 990 não está bloqueada.',
       },
+      external_storage: {
+        title: 'Armazenar arquivos enviados no armazenamento externo (passo 4 da instalação)',
+        pass: 'A impressora informa que esta opção está ligada — os arquivos enviados serão armazenados no cartão SD e os arquivos terão miniaturas e metadados do fatiador.',
+        fail: 'A impressora informa que esta opção está desligada. Ative "Armazenar arquivos enviados no armazenamento externo" — em firmwares recentes (P2S 01.02 / Bambu Studio 2.6+) o interruptor fica nas Configurações de Impressão da impressora; em versões mais antigas, está na aba Dispositivo do Bambu Studio / OrcaSlicer. Sem essa opção, cada impressão arquivada fica sem miniatura nem metadados do fatiador.',
+        skip: 'Não verificado — é necessária uma conexão MQTT ativa. Em fatiadores mais antigos onde essa configuração existe apenas no fatiador, a impressora não a reporta, então esta verificação passa mesmo com a opção desligada — verifique o passo 4 da instalação manualmente.',
+      },
       port_rtsps: {
         title: 'Porta da câmera (RTSPS 322)',
         pass: 'Acessível — o streaming da câmera funcionará.',

+ 6 - 0
frontend/src/i18n/locales/tr.ts

@@ -5601,6 +5601,12 @@ export default {
         pass: 'Erişilebilir — baskı dosyaları gönderme çalışacak.',
         warn: 'Port 990 erişilemez. İzleme yine çalışabilir, ancak yazıcıya baskı gönderme başarısız olacak. Port 990\'ın engellenmediğinden emin olun.',
       },
+      external_storage: {
+        title: 'Gönderilen dosyaları harici depolamada sakla (kurulum adımı 4)',
+        pass: 'Yazıcı bu seçeneğin açık olduğunu bildiriyor — gönderilen dosyalar SD kartta saklanacak ve arşivler küçük resim ve dilimleyici meta verileri içerecek.',
+        fail: 'Yazıcı bu seçeneğin kapalı olduğunu bildiriyor. "Gönderilen dosyaları harici depolamada sakla" seçeneğini etkinleştirin — yeni donanım yazılımlarında (P2S 01.02 / Bambu Studio 2.6+) düğme yazıcının Baskı Ayarları\'nda; eski sürümlerde Bambu Studio / OrcaSlicer\'in Cihaz sekmesindedir. Bu seçenek olmadan, arşivlenen her baskıda küçük resim ve dilimleyici meta verisi olmayacak.',
+        skip: 'Kontrol edilmedi — etkin bir MQTT bağlantısı gerekli. Bu ayarın yalnızca dilimleyicide bulunduğu eski dilimleyicilerde yazıcı bunu bildirmez, bu nedenle seçenek kapalı olsa bile bu kontrol geçer — kurulum adımı 4\'ü manuel olarak doğrulayın.',
+      },
       port_rtsps: {
         title: 'Kamera portu (RTSPS 322)',
         pass: 'Erişilebilir — kamera akışı çalışacak.',

+ 6 - 0
frontend/src/i18n/locales/zh-CN.ts

@@ -5650,6 +5650,12 @@ export default {
         pass: '可达 — 发送打印文件将正常工作。',
         warn: '端口 990 不可达。监控可能仍然有效,但向打印机发送打印任务将失败。请确保端口 990 未被阻止。',
       },
+      external_storage: {
+        title: '将发送的文件存储在外部存储中(安装步骤 4)',
+        pass: '打印机报告此选项已开启 — 发送的文件将存储在 SD 卡上,归档将包含缩略图和切片机元数据。',
+        fail: '打印机报告此选项已关闭。请启用"将发送的文件存储在外部存储中" — 在较新固件 (P2S 01.02 / Bambu Studio 2.6+) 中,开关位于打印机的打印设置中;在较旧版本中位于 Bambu Studio / OrcaSlicer 的设备选项卡中。如果不启用此选项,每次归档的打印都将没有缩略图也没有切片机元数据。',
+        skip: '未检查 — 需要有效的 MQTT 连接。在该设置仅存在于切片机中的较旧切片机上,打印机不会报告此设置,因此即使选项已关闭,此检查也会通过 — 请手动验证安装步骤 4。',
+      },
       port_rtsps: {
         title: '摄像头端口(RTSPS 322)',
         pass: '可达 — 摄像头视频流将正常工作。',

+ 6 - 0
frontend/src/i18n/locales/zh-TW.ts

@@ -5650,6 +5650,12 @@ export default {
         pass: '可達 — 傳送列印檔案將正常運作。',
         warn: '連接埠 990 無法連線。監控可能仍然有效,但向印表機傳送列印工作將失敗。請確保連接埠 990 未被封鎖。',
       },
+      external_storage: {
+        title: '將傳送的檔案儲存在外部儲存中(安裝步驟 4)',
+        pass: '印表機回報此選項已開啟 — 傳送的檔案將儲存在 SD 卡上,封存將包含縮圖和切片機中繼資料。',
+        fail: '印表機回報此選項已關閉。請啟用「將傳送的檔案儲存在外部儲存中」 — 在較新韌體 (P2S 01.02 / Bambu Studio 2.6+) 中,開關位於印表機的列印設定中;在較舊版本中位於 Bambu Studio / OrcaSlicer 的裝置分頁中。如果未啟用此選項,每次封存的列印都將沒有縮圖也沒有切片機中繼資料。',
+        skip: '未檢查 — 需要有效的 MQTT 連線。在該設定僅存在於切片機中的較舊切片機上,印表機不會回報此設定,因此即使選項已關閉,此檢查也會通過 — 請手動驗證安裝步驟 4。',
+      },
       port_rtsps: {
         title: '攝影機連接埠(RTSPS 322)',
         pass: '可達 — 攝影機串流將正常運作。',

Plik diff jest za duży
+ 0 - 0
static/assets/index-DInAXQkE.js


+ 1 - 1
static/index.html

@@ -26,7 +26,7 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-DGbY3_Tm.js"></script>
+    <script type="module" crossorigin src="/assets/index-DInAXQkE.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-BvmIMSUd.css">
   </head>
   <body>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików