diff --git a/lib/app.dart b/lib/app.dart index ea3bf9a..83723fb 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -5,7 +5,7 @@ import 'features/converter/presentation/pages/converter_page.dart'; import 'features/shopping_list/presentation/pages/shopping_list_page.dart'; import 'features/guide/presentation/widgets/info_bottom_sheet.dart'; import 'shared/services/update_service.dart'; -import 'shared/services/url_launcher_service.dart'; +import 'shared/widgets/update_dialog.dart'; class BitePlanApp extends StatelessWidget { const BitePlanApp({super.key}); @@ -33,8 +33,6 @@ class _MainScaffoldState extends State<_MainScaffold> { late final List _pages; static const _titles = ['Piano Pasti', 'Convertitore', 'Lista della spesa']; - static const _releasesUrl = - 'https://github.com/davide3011/biteplan/releases/latest'; @override void initState() { @@ -48,38 +46,11 @@ class _MainScaffoldState extends State<_MainScaffold> { ]; UpdateService.checkUpdate().then((newVersion) { if (newVersion != null && mounted) { - _showUpdateDialog(newVersion); + showUpdateDialog(context, newVersion); } }); } - void _showUpdateDialog(String newVersion) { - showDialog( - context: context, - builder: (ctx) => AlertDialog( - icon: const Icon(Icons.system_update_outlined, size: 32), - title: const Text('Aggiornamento disponibile'), - content: Text( - 'È disponibile la versione $newVersion di BitePlan.\n' - 'Vuoi scaricare il nuovo APK?', - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(ctx).pop(), - child: const Text('Più tardi'), - ), - FilledButton( - onPressed: () { - Navigator.of(ctx).pop(); - UrlLauncherService.launch(_releasesUrl); - }, - child: const Text('Scarica'), - ), - ], - ), - ); - } - @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/shared/services/update_service.dart b/lib/shared/services/update_service.dart index c27974b..4035ded 100644 --- a/lib/shared/services/update_service.dart +++ b/lib/shared/services/update_service.dart @@ -27,14 +27,24 @@ class UpdateService { final body = await response.transform(utf8.decoder).join(); client.close(); if (response.statusCode != 200) return null; - final data = jsonDecode(body) as Map; - final tag = (data['tag_name'] as String).replaceFirst(RegExp(r'^v'), ''); + final tag = parseTagName(body); + if (tag == null) return null; return isNewer(tag, kAppVersion) ? tag : null; } catch (_) { return null; } } + @visibleForTesting + static String? parseTagName(String body) { + try { + final data = jsonDecode(body) as Map; + return (data['tag_name'] as String).replaceFirst(RegExp(r'^v'), ''); + } catch (_) { + return null; + } + } + @visibleForTesting static bool isNewer(String remote, String local) { final r = parseVersion(remote); diff --git a/lib/shared/widgets/update_dialog.dart b/lib/shared/widgets/update_dialog.dart new file mode 100644 index 0000000..eab8432 --- /dev/null +++ b/lib/shared/widgets/update_dialog.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import '../services/url_launcher_service.dart'; + +const _releasesUrl = 'https://github.com/davide3011/biteplan/releases/latest'; + +void showUpdateDialog(BuildContext context, String newVersion) { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + icon: const Icon(Icons.system_update_outlined, size: 32), + title: const Text('Aggiornamento disponibile'), + content: Text( + 'È disponibile la versione $newVersion di BitePlan.\n' + 'Vuoi scaricare il nuovo APK?', + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(ctx).pop(), + child: const Text('Più tardi'), + ), + FilledButton( + onPressed: () { + Navigator.of(ctx).pop(); + UrlLauncherService.launch(_releasesUrl); + }, + child: const Text('Scarica'), + ), + ], + ), + ); +}