import { useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import type { Update } from "@tauri-apps/plugin-updater"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; type Status = "idle" | "downloading" | "error"; /** * Проверка обновлений — только десктоп (Windows/macOS/Linux). На мобильных * сборках плагин не зарегистрирован (см. src-tauri/src/lib.rs, #[cfg(desktop)]), * поэтому check() там просто недоступен — ошибка тихо проглатывается ниже, * без падения остального приложения. */ export function UpdateChecker() { const { t } = useTranslation(); const [update, setUpdate] = useState(null); const [status, setStatus] = useState("idle"); const [progress, setProgress] = useState(0); const installing = useRef(false); useEffect(() => { let cancelled = false; (async () => { try { const { check } = await import("@tauri-apps/plugin-updater"); const result = await check(); if (!cancelled && result?.available) { setUpdate(result); } } catch { // Мобильная сборка или плагин недоступен в этом окружении — не критично. } })(); return () => { cancelled = true; }; }, []); if (!update) return null; const installUpdate = async () => { if (installing.current) return; installing.current = true; setStatus("downloading"); try { let downloaded = 0; let total = 0; await update.downloadAndInstall((event) => { if (event.event === "Started") { total = event.data.contentLength ?? 0; } else if (event.event === "Progress") { downloaded += event.data.chunkLength; setProgress(total > 0 ? Math.round((downloaded / total) * 100) : 0); } }); const { relaunch } = await import("@tauri-apps/plugin-process"); await relaunch(); } catch (e) { console.error("[UpdateChecker] Установка обновления не удалась:", e); setStatus("error"); installing.current = false; } }; return ( {}}> {t("update_available_title")} {t("update_available_desc", { version: update.version })} ); }