@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
22import {
33 Info , Package , User , Calendar , Hash , FileText , Github , Heart , Sparkles ,
44 Zap , CheckCircle , Settings as SettingsIcon ,
5- ArrowUpCircle , RefreshCw , Download , Globe , Plus , Trash2 , Box , ShoppingBag , Loader2
5+ ArrowUpCircle , RefreshCw , Download , Globe , Trash2 , ShoppingBag , Loader2
66} from 'lucide-react' ;
77
88export default function Settings ( ) {
@@ -12,6 +12,7 @@ export default function Settings() {
1212 const [ latestVersion , setLatestVersion ] = useState ( null ) ;
1313 const [ updateAvailable , setUpdateAvailable ] = useState ( false ) ;
1414 const [ searchTerm , setSearchTerm ] = useState ( '' ) ;
15+ const [ downloadingUpdate , setDownloadingUpdate ] = useState ( false ) ;
1516
1617 // Provider State
1718 const [ installedProviders , setInstalledProviders ] = useState ( [ ] ) ;
@@ -22,7 +23,7 @@ export default function Settings() {
2223 name : "novel-scraper-desktop" ,
2324 productName : "UNS" ,
2425 description : "Desktop app for scraping web novels into EPUB format" ,
25- version : "1.2.0" , // Current Version
26+ version : "1.2.1" ,
2627 author : "Osama" ,
2728 license : "CC-BY-NC-4.0" ,
2829 appId : "com.universalnovelscraper.app" ,
@@ -31,11 +32,49 @@ export default function Settings() {
3132 } ;
3233
3334 useEffect ( ( ) => {
34- checkForUpdates ( ) ;
3535 refreshInstalled ( ) ;
3636 if ( activeTab === 'store' ) fetchStore ( ) ;
37+
38+ if ( window . electronAPI ) {
39+ window . electronAPI . onUpdateAvailable ( ( info ) => {
40+ setLatestVersion ( info . version ) ;
41+ setUpdateAvailable ( true ) ;
42+ setUpdateLoading ( false ) ;
43+ } ) ;
44+
45+ window . electronAPI . onUpdateNotAvailable ( ( ) => {
46+ setUpdateAvailable ( false ) ;
47+ setUpdateLoading ( false ) ;
48+ } ) ;
49+
50+ window . electronAPI . onUpdateDownloaded ( ( ) => {
51+ setDownloadingUpdate ( false ) ;
52+ } ) ;
53+
54+ // 👈 NEW: Instantly stop all spinners if the connection fails
55+ window . electronAPI . onUpdateError ( ( errorMessage ) => {
56+ console . error ( "Update failed:" , errorMessage ) ;
57+ setUpdateLoading ( false ) ;
58+ setDownloadingUpdate ( false ) ;
59+ } ) ;
60+ }
61+
62+ return ( ) => {
63+ if ( window . electronAPI ) window . electronAPI . removeUpdateListeners ( ) ;
64+ } ;
3765 } , [ activeTab ] ) ;
3866
67+ // Look how much cleaner this is!
68+ const checkForUpdates = ( ) => {
69+ setUpdateLoading ( true ) ;
70+ window . electronAPI ?. checkForUpdates ( ) ;
71+ } ;
72+
73+ const handleUpdateNow = ( ) => {
74+ setDownloadingUpdate ( true ) ;
75+ window . electronAPI ?. downloadUpdate ( ) ;
76+ } ;
77+
3978 const refreshInstalled = async ( ) => {
4079 const list = await window . electronAPI ?. getProviders ( ) || [ ] ;
4180 setInstalledProviders ( list ) ;
@@ -51,7 +90,7 @@ export default function Settings() {
5190 // 2. Map the manifest data to include the download URL for each script
5291 const scripts = manifest . map ( item => ( {
5392 ...item ,
54- id :item . id ,
93+ id : item . id ,
5594 name : item . name || item . id . charAt ( 0 ) . toUpperCase ( ) + item . id . slice ( 1 ) ,
5695 type : item . type ,
5796 download_url : `https://raw.githubusercontent.com/${ packageInfo . providersRepo } /main/${ item . id } .js`
@@ -78,19 +117,6 @@ export default function Settings() {
78117 if ( success ) refreshInstalled ( ) ;
79118 } ;
80119
81- const checkForUpdates = async ( ) => {
82- setUpdateLoading ( true ) ;
83- try {
84- const response = await fetch ( `https://api.github.com/repos/${ packageInfo . repo } /releases/latest` ) ;
85- const data = await response . json ( ) ;
86- if ( data . tag_name ) {
87- const latest = data . tag_name . replace ( 'v' , '' ) ;
88- setLatestVersion ( latest ) ;
89- if ( latest !== packageInfo . version ) setUpdateAvailable ( true ) ;
90- }
91- } catch ( e ) { } finally { setUpdateLoading ( false ) ; }
92- } ;
93-
94120 return (
95121 < div className = "max-w-5xl mx-auto px-6 animate-in fade-in duration-700" >
96122 { /* Header */ }
@@ -130,10 +156,10 @@ export default function Settings() {
130156 </ h2 >
131157 < button
132158 onClick = { checkForUpdates }
133- disabled = { updateLoading }
134- className = "p-2 hover:bg-zinc-800 rounded-lg transition-colors text-zinc-400"
159+ disabled = { updateLoading || downloadingUpdate }
160+ className = "p-2 hover:bg-zinc-800 rounded-lg transition-colors text-zinc-400 disabled:opacity-50 "
135161 >
136- < RefreshCw size = { 16 } className = { updateLoading ? "animate-spin" : "" } />
162+ < RefreshCw size = { 16 } className = { ( updateLoading || downloadingUpdate ) ? "animate-spin" : "" } />
137163 </ button >
138164 </ div >
139165 < div className = "p-6" >
@@ -149,11 +175,21 @@ export default function Settings() {
149175 </ div >
150176 </ div >
151177 < button
152- onClick = { ( ) => window . electronAPI ?. openExternal ( `https://github.com/${ packageInfo . repo } /releases/latest` ) }
153- className = "flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-500 text-white rounded-lg text-sm font-medium transition-all"
178+ onClick = { handleUpdateNow }
179+ disabled = { downloadingUpdate }
180+ className = "flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-500 text-white rounded-lg text-sm font-medium transition-all disabled:opacity-50"
154181 >
155- < Download size = { 16 } />
156- Update Now
182+ { downloadingUpdate ? (
183+ < >
184+ < Loader2 size = { 16 } className = "animate-spin" />
185+ Downloading...
186+ </ >
187+ ) : (
188+ < >
189+ < Download size = { 16 } />
190+ Update Now
191+ </ >
192+ ) }
157193 </ button >
158194 </ div >
159195 ) : (
@@ -299,7 +335,7 @@ export default function Settings() {
299335 // 🔍 Match Case-Insensitive for IDs
300336 const installed = installedProviders . find ( p => p . id . toLowerCase ( ) === script . id . toLowerCase ( ) ) ;
301337 const needsUpdate = installed && installed . version !== script . version ;
302-
338+
303339 return (
304340 < div key = { script . id } className = "p-5 bg-zinc-950/50 border border-zinc-800 rounded-2xl flex items-center justify-between hover:border-zinc-700 transition-all group" >
305341 < div className = "flex items-center gap-4" >
0 commit comments