Files
donutbrowser/src/components/app-update-toast.tsx
T
2026-05-14 20:04:19 +04:00

104 lines
3.1 KiB
TypeScript

"use client";
import { useTranslation } from "react-i18next";
import { FaExternalLinkAlt, FaTimes } from "react-icons/fa";
import { LuCheckCheck } from "react-icons/lu";
import { Button } from "@/components/ui/button";
import type { AppUpdateInfo } from "@/types";
import { RippleButton } from "./ui/ripple";
interface AppUpdateToastProps {
updateInfo: AppUpdateInfo;
onRestart: () => Promise<void>;
onDismiss: () => void;
updateReady?: boolean;
}
export function AppUpdateToast({
updateInfo,
onRestart,
onDismiss,
updateReady = false,
}: AppUpdateToastProps) {
const { t } = useTranslation();
const handleRestartClick = async () => {
await onRestart();
};
const handleViewRelease = () => {
if (updateInfo.release_page_url) {
const event = new CustomEvent("url-open-request", {
detail: updateInfo.release_page_url,
});
window.dispatchEvent(event);
}
};
return (
<div className="flex items-start p-4 w-full max-w-md rounded-lg border shadow-lg bg-card border-border text-card-foreground">
<div className="mr-3 mt-0.5">
<LuCheckCheck className="flex-shrink-0 size-5" />
</div>
<div className="flex-1 min-w-0">
<div className="flex gap-2 justify-between items-start">
<div className="flex flex-col gap-1">
<span className="text-sm font-semibold text-foreground">
{updateReady
? t("appUpdate.toast.updateReady")
: updateInfo.repo_update
? "Update available via package manager"
: t("appUpdate.toast.manualDownloadRequired")}
</span>
<div className="text-xs text-muted-foreground">
{updateInfo.current_version} {updateInfo.new_version}
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={onDismiss}
className="p-0 size-6 shrink-0"
>
<FaTimes className="size-3" />
</Button>
</div>
<div className="flex gap-2 items-center mt-3">
{updateReady ? (
<RippleButton
onClick={() => void handleRestartClick()}
size="sm"
className="flex gap-2 items-center text-xs"
>
<LuCheckCheck className="size-3" />
{t("appUpdate.toast.restartNow")}
</RippleButton>
) : (
!updateInfo.repo_update &&
updateInfo.manual_update_required && (
<RippleButton
onClick={handleViewRelease}
size="sm"
className="flex gap-2 items-center text-xs"
>
<FaExternalLinkAlt className="size-3" />
{t("appUpdate.toast.viewRelease")}
</RippleButton>
)
)}
<RippleButton
variant="outline"
onClick={onDismiss}
size="sm"
className="text-xs"
>
{t("appUpdate.toast.later")}
</RippleButton>
</div>
</div>
</div>
);
}