1- import { Button , Dialog , Flex , Text } from "@radix-ui/themes" ;
1+ import { Button , Dialog , Flex , Spinner , Text } from "@radix-ui/themes" ;
22import { logger } from "@renderer/lib/logger" ;
33import { useCallback , useEffect , useState } from "react" ;
44
@@ -8,6 +8,11 @@ export function UpdatePrompt() {
88 const [ open , setOpen ] = useState ( false ) ;
99 const [ isInstalling , setIsInstalling ] = useState ( false ) ;
1010 const [ errorMessage , setErrorMessage ] = useState < string | null > ( null ) ;
11+ const [ checkDialogOpen , setCheckDialogOpen ] = useState ( false ) ;
12+ const [ checkingForUpdates , setCheckingForUpdates ] = useState ( false ) ;
13+ const [ checkResultMessage , setCheckResultMessage ] = useState < string | null > (
14+ null ,
15+ ) ;
1116
1217 useEffect ( ( ) => {
1318 const unsubscribe = window . electronAPI ?. onUpdateReady ( ( ) => {
@@ -20,6 +25,55 @@ export function UpdatePrompt() {
2025 } ;
2126 } , [ ] ) ;
2227
28+ useEffect ( ( ) => {
29+ const unsubscribeStatus = window . electronAPI ?. onUpdateStatus ( ( status ) => {
30+ if ( status . checking === false && status . upToDate ) {
31+ setCheckingForUpdates ( false ) ;
32+ setCheckResultMessage (
33+ `Array is up to date (version ${ window . electronAPI ? "" : "unknown" } )` ,
34+ ) ;
35+ } else if ( status . checking === false ) {
36+ setCheckingForUpdates ( false ) ;
37+ } else if ( status . checking === true ) {
38+ setCheckingForUpdates ( true ) ;
39+ setCheckResultMessage ( null ) ;
40+ }
41+ } ) ;
42+
43+ return ( ) => {
44+ unsubscribeStatus ?.( ) ;
45+ } ;
46+ } , [ ] ) ;
47+
48+ useEffect ( ( ) => {
49+ const handleMenuCheck = async ( ) => {
50+ setCheckDialogOpen ( true ) ;
51+ setCheckingForUpdates ( true ) ;
52+ setCheckResultMessage ( null ) ;
53+
54+ try {
55+ const result = await window . electronAPI ?. checkForUpdates ( ) ;
56+
57+ if ( ! result ?. success ) {
58+ setCheckingForUpdates ( false ) ;
59+ setCheckResultMessage ( result ?. error || "Failed to check for updates" ) ;
60+ }
61+ } catch ( error ) {
62+ log . error ( "Failed to check for updates:" , error ) ;
63+ setCheckingForUpdates ( false ) ;
64+ setCheckResultMessage ( "An unexpected error occurred" ) ;
65+ }
66+ } ;
67+
68+ const unsubscribeMenuCheck = window . electronAPI ?. onCheckForUpdatesMenu ( ( ) =>
69+ handleMenuCheck ( ) ,
70+ ) ;
71+
72+ return ( ) => {
73+ unsubscribeMenuCheck ?.( ) ;
74+ } ;
75+ } , [ ] ) ;
76+
2377 const handleRestart = useCallback ( async ( ) => {
2478 if ( ! window . electronAPI || isInstalling ) {
2579 return ;
@@ -44,44 +98,77 @@ export function UpdatePrompt() {
4498 }
4599 } , [ isInstalling ] ) ;
46100
47- if ( ! open ) {
48- return null ;
49- }
50-
51101 return (
52- < Dialog . Root open = { open } onOpenChange = { setOpen } >
53- < Dialog . Content maxWidth = "360px" >
54- < Flex direction = "column" gap = "3" >
55- < Dialog . Title className = "mb-0" > Update ready</ Dialog . Title >
56- < Dialog . Description >
57- A new version of Array has finished downloading. Restart now to
58- install it or choose Later to keep working and update next time.
59- </ Dialog . Description >
60- { errorMessage ? (
61- < Text size = "2" color = "red" >
62- { errorMessage }
63- </ Text >
64- ) : null }
65- < Flex justify = "end" gap = "3" mt = "2" >
66- < Button
67- type = "button"
68- variant = "soft"
69- color = "gray"
70- onClick = { ( ) => setOpen ( false ) }
71- disabled = { isInstalling }
72- >
73- Later
74- </ Button >
75- < Button
76- type = "button"
77- onClick = { handleRestart }
78- disabled = { isInstalling }
79- >
80- { isInstalling ? "Restarting…" : "Restart now" }
81- </ Button >
82- </ Flex >
83- </ Flex >
84- </ Dialog . Content >
85- </ Dialog . Root >
102+ < >
103+ { /* Update ready dialog */ }
104+ { open && (
105+ < Dialog . Root open = { open } onOpenChange = { setOpen } >
106+ < Dialog . Content maxWidth = "360px" >
107+ < Flex direction = "column" gap = "3" >
108+ < Dialog . Title className = "mb-0" > Update ready</ Dialog . Title >
109+ < Dialog . Description >
110+ A new version of Array has finished downloading. Restart now to
111+ install it or choose Later to keep working and update next time.
112+ </ Dialog . Description >
113+ { errorMessage ? (
114+ < Text size = "2" color = "red" >
115+ { errorMessage }
116+ </ Text >
117+ ) : null }
118+ < Flex justify = "end" gap = "3" mt = "2" >
119+ < Button
120+ type = "button"
121+ variant = "soft"
122+ color = "gray"
123+ onClick = { ( ) => setOpen ( false ) }
124+ disabled = { isInstalling }
125+ >
126+ Later
127+ </ Button >
128+ < Button
129+ type = "button"
130+ onClick = { handleRestart }
131+ disabled = { isInstalling }
132+ >
133+ { isInstalling ? "Restarting…" : "Restart now" }
134+ </ Button >
135+ </ Flex >
136+ </ Flex >
137+ </ Dialog . Content >
138+ </ Dialog . Root >
139+ ) }
140+
141+ { /* Check for updates dialog (menu-triggered) */ }
142+ { checkDialogOpen && (
143+ < Dialog . Root open = { checkDialogOpen } onOpenChange = { setCheckDialogOpen } >
144+ < Dialog . Content maxWidth = "360px" >
145+ < Flex direction = "column" gap = "3" >
146+ < Dialog . Title className = "mb-0" > Check for Updates</ Dialog . Title >
147+ < Dialog . Description >
148+ { checkingForUpdates ? (
149+ < Flex align = "center" gap = "2" >
150+ < Spinner />
151+ < Text > Checking for updates...</ Text >
152+ </ Flex >
153+ ) : checkResultMessage ? (
154+ < Text > { checkResultMessage } </ Text >
155+ ) : (
156+ < Text > Ready to check for updates</ Text >
157+ ) }
158+ </ Dialog . Description >
159+ < Flex justify = "end" mt = "2" >
160+ < Button
161+ type = "button"
162+ onClick = { ( ) => setCheckDialogOpen ( false ) }
163+ disabled = { checkingForUpdates }
164+ >
165+ OK
166+ </ Button >
167+ </ Flex >
168+ </ Flex >
169+ </ Dialog . Content >
170+ </ Dialog . Root >
171+ ) }
172+ </ >
86173 ) ;
87174}
0 commit comments