1+ import { useState } from "react" ;
12import { useTranslation } from "../../../i18n" ;
23import { useAppSettingStore } from "../../../store/app-setting" ;
4+ import { Button } from "../../ui/button" ;
35import {
46 FrameTitle ,
57 FrameDescription ,
68 Frame ,
79 FramePanel ,
10+ FrameFooter ,
811} from "../../ui/frame" ;
912import { Switch } from "../../ui/switch" ;
13+ import { AlertDialog , AlertDialogContent } from "../../ui/alert-dialog" ;
14+ import { Gift , Loader2 } from "lucide-react" ;
15+ import { check } from "@tauri-apps/plugin-updater" ;
16+ import { relaunch } from "@tauri-apps/plugin-process" ;
17+ import { useMutation } from "@tanstack/react-query" ;
18+ import { toastManager } from "../../ui/toast" ;
1019
1120export function AutoUpdate ( ) {
1221 const { t } = useTranslation ( ) ;
1322 const value = useAppSettingStore ( ( r ) => r . autoUpdate ) ;
1423 const toggle = useAppSettingStore ( ( r ) => r . setAutoUpdate ) ;
24+ const [ isOpen , setIsOpen ] = useState ( false ) ;
25+ const checkForUpdates = useMutation ( {
26+ mutationFn : async ( ) => {
27+ const update = await check ( ) ;
28+ return update ;
29+ } ,
30+ onSuccess : ( update ) => {
31+ if ( update ) {
32+ setIsOpen ( true ) ;
33+ } else {
34+ toastManager . add ( {
35+ title : "No updates available" ,
36+ description : "You are already using the latest version" ,
37+ type : "info" ,
38+ } ) ;
39+ }
40+ } ,
41+ } ) ;
42+ const handleUpdate = useMutation ( {
43+ mutationFn : async ( ) => {
44+ const update = await check ( ) ;
45+ if ( update ) {
46+ await update . downloadAndInstall ( ) ;
47+ await relaunch ( ) ;
48+ }
49+ } ,
50+ onSuccess : ( ) => {
51+ setIsOpen ( false ) ;
52+ } ,
53+ } ) ;
1554
1655 return (
1756 < Frame >
@@ -26,6 +65,55 @@ export function AutoUpdate() {
2665 </ div >
2766 < Switch checked = { value } onCheckedChange = { toggle } />
2867 </ FramePanel >
68+ { value === false && (
69+ < FrameFooter className = "flex-row justify-end" >
70+ < Button
71+ className = "w-48"
72+ variant = "secondary"
73+ onClick = { ( ) => checkForUpdates . mutate ( ) }
74+ disabled = { checkForUpdates . isPending }
75+ >
76+ { checkForUpdates . isPending ? (
77+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
78+ ) : null }
79+ Check for updates
80+ </ Button >
81+ </ FrameFooter >
82+ ) }
83+ < AlertDialog open = { isOpen } onOpenChange = { setIsOpen } >
84+ < AlertDialogContent
85+ backdropClassName = "!bg-transparent !backdrop-blur-none"
86+ className = "fixed bottom-1 left-2 translate-x-0 translate-y-0 w-md"
87+ >
88+ < div className = "flex px-5 py-4 items-center gap-2" >
89+ < Gift className = "w-4 h-4 text-muted-foreground" />
90+ < p className = "text-sm flex items-center text-muted-foreground" >
91+ A new version is available -{ " " }
92+ { checkForUpdates . data ?. version }
93+ </ p >
94+ < div className = "flex gap-2 ml-auto" >
95+ < Button
96+ variant = "outline"
97+ size = "sm"
98+ onClick = { ( ) => setIsOpen ( false ) }
99+ >
100+ Later
101+ </ Button >
102+ < Button
103+ size = "sm"
104+ disabled = { handleUpdate . isPending }
105+ onClick = { ( ) => handleUpdate . mutate ( ) }
106+ >
107+ { handleUpdate . isPending ? (
108+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
109+ ) : (
110+ "Update now"
111+ ) }
112+ </ Button >
113+ </ div >
114+ </ div >
115+ </ AlertDialogContent >
116+ </ AlertDialog >
29117 </ Frame >
30118 ) ;
31119}
0 commit comments