import { useState } from "react"; import { Loader2, Copy, Sparkles, ChevronRight } from "lucide-react"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { useApi } from "@/contexts/ApiContext"; import { useToast } from "@/hooks/use-toast"; import { useUpdateCheck } from "@/hooks/useUpdateCheck"; /** * App-level popup that notifies the user when a newer LeLab is available on * GitHub. Offers a copy-able upgrade command, a best-effort "Update now" button * (runs the pip upgrade on the backend), and a "don't ask again" opt-out. */ const UpdateNotice = () => { const { status, open, dismiss } = useUpdateCheck(); const { baseUrl, fetchWithHeaders } = useApi(); const { toast } = useToast(); const [dontAsk, setDontAsk] = useState(false); const [updating, setUpdating] = useState(false); const [output, setOutput] = useState(null); if (!status) return null; const behind = typeof status.commits_behind === "number" && status.commits_behind > 0 ? `${status.commits_behind} commit${status.commits_behind === 1 ? "" : "s"} behind` : "A new version is available"; const copyCommand = async () => { if (!status.update_command) return; try { await navigator.clipboard.writeText(status.update_command); toast({ title: "Copied", description: "Update command copied to clipboard.", }); } catch { toast({ title: "Copy failed", description: "Select and copy the command manually.", variant: "destructive", }); } }; const runUpdate = async () => { setUpdating(true); setOutput(null); try { const r = await fetchWithHeaders(`${baseUrl}/system/update`, { method: "POST", }); const body: { success: boolean; message: string; output: string } = await r.json(); if (body.success) { toast({ title: "Updated", description: body.message }); dismiss(false); } else { setOutput(body.output || body.message); toast({ title: "Update failed", description: body.message, variant: "destructive", }); } } catch (e) { toast({ title: "Update failed", description: e instanceof Error ? e.message : String(e), variant: "destructive", }); } finally { setUpdating(false); } }; return ( { if (!o && !updating) dismiss(dontAsk); }} > e.preventDefault()} > LeLab update available You're {behind} 😱.
Update to get the latest fixes and features 🤗. {status.compare_url && ( <> {" "} See what changed . )}
Or update manually
{status.update_command}
{output && (
              {output}
            
)}
{status.can_auto_update && ( )}
); }; export default UpdateNotice;