11import 'dart:io' ;
22import 'package:flutter/material.dart' ;
3+ import 'package:go_router/go_router.dart' ;
34import 'package:supabase_flutter/supabase_flutter.dart' ;
45import 'package:package_info_plus/package_info_plus.dart' ;
56import 'package:http/http.dart' as http;
@@ -32,12 +33,12 @@ class UpdateManager {
3233 PackageInfo packageInfo = await PackageInfo .fromPlatform ();
3334 String currentVersion = packageInfo.version; // e.g., "1.0.0"
3435 Map <String , dynamic >? latestInfo = await getLatestVersion ();
35-
36+
3637 if (latestInfo == null ) return false ;
37-
38+
3839 String latestVersion = latestInfo['version' ]; // e.g., "1.1.0"
3940 print ('Current version: $currentVersion , Latest version: $latestVersion ' );
40-
41+
4142 return _compareVersions (currentVersion, latestVersion) < 0 ;
4243 } catch (e) {
4344 print ('Error checking for update: $e ' );
@@ -49,15 +50,15 @@ class UpdateManager {
4950 int _compareVersions (String current, String latest) {
5051 List <String > currentParts = current.split ('.' );
5152 List <String > latestParts = latest.split ('.' );
52-
53+
5354 // Ensure both lists have at least 3 elements
5455 while (currentParts.length < 3 ) currentParts.add ('0' );
5556 while (latestParts.length < 3 ) latestParts.add ('0' );
56-
57+
5758 for (int i = 0 ; i < 3 ; i++ ) {
5859 int currentNum = int .tryParse (currentParts[i]) ?? 0 ;
5960 int latestNum = int .tryParse (latestParts[i]) ?? 0 ;
60-
61+
6162 if (latestNum > currentNum) return - 1 ;
6263 if (latestNum < currentNum) return 1 ;
6364 }
@@ -102,7 +103,7 @@ class UpdateManager {
102103 // Create batch file for Windows update
103104 final tempDir = await getTemporaryDirectory ();
104105 File batchFile = File ('${tempDir .path }/update.bat' );
105-
106+
106107 String script = '''
107108 @echo off
108109 echo Updating Cooketh Flow...
@@ -112,37 +113,40 @@ class UpdateManager {
112113 start "" "$currentPath "
113114 exit
114115 ''' ;
115-
116+
116117 await batchFile.writeAsString (script);
117- await Process .start ('cmd.exe' , ['/c' , batchFile.path], runInShell: true );
118+ await Process .start ('cmd.exe' , ['/c' , batchFile.path],
119+ runInShell: true );
118120 exit (0 );
119121 } else if (Platform .isLinux) {
120122 final appDir = await getApplicationDocumentsDirectory ();
121123 final updateDir = Directory ('${appDir .path }/update' );
122124 if (! await updateDir.exists ()) {
123125 await updateDir.create (recursive: true );
124126 }
125-
127+
126128 // Extract the tarball
127- await Process .run ('tar' , ['-xzf' , downloadedPath, '-C' , updateDir.path]);
128-
129+ await Process .run (
130+ 'tar' , ['-xzf' , downloadedPath, '-C' , updateDir.path]);
131+
129132 // Make the new binary executable
130133 String newBinaryPath = '${updateDir .path }/cookethflow' ;
131134 if (await File (newBinaryPath).exists ()) {
132135 await Process .run ('chmod' , ['+x' , newBinaryPath]);
133-
136+
134137 // Create a shell script to replace the current binary and restart
135138 File scriptFile = File ('${updateDir .path }/apply_update.sh' );
136-
139+
137140 String script = '''
138141 #!/bin/bash
139142 cp "$newBinaryPath " "${Platform .resolvedExecutable }"
140143 exec "${Platform .resolvedExecutable }"
141144 ''' ;
142-
145+
143146 await scriptFile.writeAsString (script);
144147 await Process .run ('chmod' , ['+x' , scriptFile.path]);
145- await Process .start (scriptFile.path, [], mode: ProcessStartMode .detached);
148+ await Process .start (scriptFile.path, [],
149+ mode: ProcessStartMode .detached);
146150 exit (0 );
147151 } else {
148152 throw Exception ('Update binary not found in tarball' );
@@ -154,44 +158,44 @@ class UpdateManager {
154158 if (! await updateDir.exists ()) {
155159 await updateDir.create (recursive: true );
156160 }
157-
161+
158162 // For macOS, assuming it's a DMG file
159163 await Process .run ('open' , [downloadedPath]);
160164 // Show instructions to the user for manual update
161165 // (automatic update on macOS often requires elevated privileges)
162166 }
163167 } catch (e) {
164168 print ('Error applying update: $e ' );
165- throw e ;
169+ rethrow ;
166170 }
167171 }
168172
169173 // Show update prompt
170174 Future <void > checkAndPromptForUpdate (BuildContext context) async {
171175 if (_isCheckingForUpdate) return ;
172-
176+
173177 _isCheckingForUpdate = true ;
174-
178+
175179 try {
176180 bool updateAvailable = await isUpdateAvailable ();
177-
181+
178182 if (! updateAvailable) {
179183 print ('No updates available' );
180184 _isCheckingForUpdate = false ;
181185 return ;
182186 }
183-
187+
184188 Map <String , dynamic >? latestInfo = await getLatestVersion ();
185189 if (latestInfo == null ) {
186190 _isCheckingForUpdate = false ;
187191 return ;
188192 }
189-
193+
190194 if (! context.mounted) {
191195 _isCheckingForUpdate = false ;
192196 return ;
193197 }
194-
198+
195199 showDialog (
196200 context: context,
197201 barrierDismissible: false ,
@@ -211,7 +215,8 @@ class UpdateManager {
211215 } else if (snapshot.hasError) {
212216 return const Text ('Error fetching version' );
213217 } else {
214- return Text ('Current version: ${snapshot .data ?.version ?? 'Unknown' }' );
218+ return Text (
219+ 'Current version: ${snapshot .data ?.version ?? 'Unknown' }' );
215220 }
216221 },
217222 ),
@@ -224,22 +229,23 @@ class UpdateManager {
224229 color: Colors .grey[200 ],
225230 borderRadius: BorderRadius .circular (4 ),
226231 ),
227- child: Text (latestInfo['release_notes' ] ?? 'No release notes available' ),
232+ child: Text (latestInfo['release_notes' ] ??
233+ 'No release notes available' ),
228234 ),
229235 ],
230236 ),
231237 actions: [
232238 TextButton (
233239 onPressed: () {
234- Navigator .pop (context );
240+ context .pop ();
235241 _isCheckingForUpdate = false ;
236242 },
237243 child: const Text ('Later' ),
238244 ),
239245 ElevatedButton (
240246 onPressed: () async {
241- Navigator .pop (context );
242-
247+ context .pop ();
248+
243249 // Show loading dialog
244250 showDialog (
245251 context: context,
@@ -251,52 +257,54 @@ class UpdateManager {
251257 children: [
252258 LinearProgressIndicator (),
253259 SizedBox (height: 16 ),
254- Text ('Please wait while the update is being downloaded...' ),
260+ Text (
261+ 'Please wait while the update is being downloaded...' ),
255262 ],
256263 ),
257264 ),
258265 );
259-
266+
260267 String ? url = getDownloadUrl (latestInfo);
261268 if (url != null ) {
262269 try {
263270 String ? path = await downloadUpdate (url);
264-
271+
265272 if (! context.mounted) {
266273 _isCheckingForUpdate = false ;
267274 return ;
268275 }
269-
276+
270277 // Close the loading dialog
271- Navigator .pop (context );
272-
278+ context .pop ();
279+
273280 if (path != null ) {
274281 // Show confirmation before applying update
275282 showDialog (
276283 context: context,
277284 builder: (context) => AlertDialog (
278285 title: const Text ('Ready to Update' ),
279286 content: const Text (
280- 'The update has been downloaded and is ready to install. '
281- 'The application will restart during this process.'
282- ),
287+ 'The update has been downloaded and is ready to install. '
288+ 'The application will restart during this process.' ),
283289 actions: [
284290 TextButton (
285291 onPressed: () {
286- Navigator .pop (context );
292+ context .pop ();
287293 _isCheckingForUpdate = false ;
288294 },
289295 child: const Text ('Cancel' ),
290296 ),
291297 ElevatedButton (
292298 onPressed: () async {
293- Navigator .pop (context );
299+ context .pop ();
294300 try {
295301 await applyUpdate (path);
296302 } catch (e) {
297303 if (context.mounted) {
298304 ScaffoldMessenger .of (context).showSnackBar (
299- SnackBar (content: Text ('Failed to apply update: $e ' )),
305+ SnackBar (
306+ content: Text (
307+ 'Failed to apply update: $e ' )),
300308 );
301309 }
302310 _isCheckingForUpdate = false ;
@@ -310,14 +318,15 @@ class UpdateManager {
310318 } else {
311319 if (context.mounted) {
312320 ScaffoldMessenger .of (context).showSnackBar (
313- const SnackBar (content: Text ('Failed to download update' )),
321+ const SnackBar (
322+ content: Text ('Failed to download update' )),
314323 );
315324 }
316325 _isCheckingForUpdate = false ;
317326 }
318327 } catch (e) {
319328 if (context.mounted) {
320- Navigator .pop (context ); // Close loading dialog
329+ context .pop (); // Close loading dialog
321330 ScaffoldMessenger .of (context).showSnackBar (
322331 SnackBar (content: Text ('Error during update: $e ' )),
323332 );
@@ -326,9 +335,11 @@ class UpdateManager {
326335 }
327336 } else {
328337 if (context.mounted) {
329- Navigator .pop (context ); // Close loading dialog
338+ context .pop (); // Close loading dialog
330339 ScaffoldMessenger .of (context).showSnackBar (
331- const SnackBar (content: Text ('No download available for your platform' )),
340+ const SnackBar (
341+ content:
342+ Text ('No download available for your platform' )),
332343 );
333344 }
334345 _isCheckingForUpdate = false ;
@@ -344,4 +355,4 @@ class UpdateManager {
344355 _isCheckingForUpdate = false ;
345356 }
346357 }
347- }
358+ }
0 commit comments