/** * UpdateNotification - компонент уведомления о доступном обновлении * Показывает информацию об обновлении и предоставляет действия для пользователя */ import { X } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { useUpdateManager } from "../hooks/use-update-manager" interface UpdateNotificationProps { className?: string onClose?: () => void showProgress?: boolean } /** * Компонент уведомления об обновлении */ export function UpdateNotification({ className, onClose, showProgress = true }: UpdateNotificationProps) { const { isUpdateAvailable, isDownloading, isReadyToInstall, isInstalling, isInstalled, isError, availableUpdate, error, progress, downloadUpdate, installUpdate, dismiss, retry, } = useUpdateManager() // Не показываем уведомление если нет обновления или произошла ошибка if (!isUpdateAvailable && !isDownloading && !isReadyToInstall && !isInstalling && !isInstalled && !isError) { return null } const handleClose = () => { dismiss() onClose?.() } const getTitle = () => { if (isError) return "Ошибка обновления" if (isInstalled) return "Обновление установлено" if (isInstalling) return "Установка обновления..." if (isReadyToInstall) return "Готово к установке" if (isDownloading) return "Загрузка обновления..." return "Доступно обновление" } const getDescription = () => { if (isError) return error || "Произошла ошибка при обновлении" if (isInstalled) return "Обновление успешно установлено. Перезапустите приложение для применения изменений." if (isInstalling) return "Пожалуйста, подождите..." if (isReadyToInstall) return "Обновление загружено и готово к установке" if (isDownloading) return "Загружается новая версия приложения" if (availableUpdate) { return `Версия ${availableUpdate.version} готова к загрузке` } return "Новая версия приложения готова к загрузке" } const getActionButtons = () => { if (isError) { return (
) } if (isInstalled) { return ( ) } if (isInstalling) { return ( ) } if (isReadyToInstall) { return (
) } if (isDownloading) { return ( ) } // isUpdateAvailable return (
) } const getBadgeVariant = () => { if (isError) return "destructive" as const if (isInstalled) return "default" as const if (isInstalling || isDownloading) return "secondary" as const return "default" as const } const getBadgeText = () => { if (isError) return "Ошибка" if (isInstalled) return "Установлено" if (isInstalling) return "Установка" if (isReadyToInstall) return "Готово" if (isDownloading) return "Загрузка" return "Новое" } return (
{getTitle()} {getBadgeText()}
{getDescription()}
{/* Прогресс загрузки */} {showProgress && isDownloading && progress && (
Прогресс {progress.percentage}%
{progress.total && (
{formatBytes(progress.downloaded)} / {formatBytes(progress.total)}
)}
)} {/* Информация о версии */} {availableUpdate && (isUpdateAvailable || isDownloading) && (
Версия {availableUpdate.version}
{availableUpdate.notes && (
{availableUpdate.notes}
)} {availableUpdate.pub_date && (
{new Date(availableUpdate.pub_date).toLocaleDateString("ru-RU")}
)}
)} {/* Кнопки действий */}
{getActionButtons()}
) } /** * Утилита для форматирования размера файла */ function formatBytes(bytes: number): string { if (bytes === 0) return "0 Bytes" const k = 1024 const sizes = ["Bytes", "KB", "MB", "GB"] const i = Math.floor(Math.log(bytes) / Math.log(k)) return `${Number.parseFloat((bytes / k ** i).toFixed(1))} ${sizes[i]}` }