diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 965383b..488914e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,6 +30,15 @@ + + + @@ -39,6 +48,7 @@ + diff --git a/android/app/src/main/res/xml/filepaths.xml b/android/app/src/main/res/xml/filepaths.xml new file mode 100644 index 0000000..774ca56 --- /dev/null +++ b/android/app/src/main/res/xml/filepaths.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/lib/config/constant.dart b/lib/config/constant.dart index 7bd69f9..e852b4f 100644 --- a/lib/config/constant.dart +++ b/lib/config/constant.dart @@ -45,3 +45,7 @@ const String LOGIN_API = 'https://mp4.ikksgroup.com' + "/authentication/login"; const String PRODUCT_API = 'https://mp4.ikksgroup.com' + "/example/getProduct"; const String SERVLET_API = 'https://mp4.ikksgroup.com' + "/MobilePortal4_external/UploadPhotoServlet"; + +// https://blogit.q2ii.fr +// https://mp4.ikksgroup.com +const String DOMAIN_CHECK_VERSION = 'https://mp4.ikksgroup.com'; diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index 31bea63..a997956 100644 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -481,4 +481,24 @@ class ApiProvider { void close() { _dio.close(); } + + Future checkAppVersion() async { + try { + final response = await http + .get(Uri.parse(DOMAIN_CHECK_VERSION + '/deploy/mobdr/version.json')); + final data = jsonDecode(response.body); + + if (data.containsKey('latest_version')) { + if (data['latest_version'] != SharedPrefs().appVersion) { + // The versions differ + return true; + } + } + } catch (e) { + print('Error verifying the version : $e'); + } + + // If an error has occurred or if the versions are identical + return false; + } } diff --git a/lib/ui/account/tab_account.dart b/lib/ui/account/tab_account.dart index 3c319df..fae6cf8 100644 --- a/lib/ui/account/tab_account.dart +++ b/lib/ui/account/tab_account.dart @@ -11,6 +11,7 @@ import 'package:mobdr/ui/account/settings.dart'; import 'package:mobdr/ui/account/log.dart'; import 'package:mobdr/ui/general/notification.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; +import 'package:mobdr/ui/appstore/updatecheck.dart'; import 'package:flutter/material.dart'; import 'package:mobdr/ui/authentication/signin.dart'; import 'dart:convert'; @@ -78,6 +79,8 @@ class _TabAccountPageState extends State _reusableWidget.divider1(), _createListMenu('Show logs', LogPage()), _reusableWidget.divider1(), + _createListMenu('Check version', UpdateCheckPage()), + _reusableWidget.divider1(), Container( margin: EdgeInsets.fromLTRB(0, 18, 0, 0), child: GestureDetector( diff --git a/lib/ui/appstore/updatecheck.dart b/lib/ui/appstore/updatecheck.dart new file mode 100644 index 0000000..9e4ea75 --- /dev/null +++ b/lib/ui/appstore/updatecheck.dart @@ -0,0 +1,175 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:ota_update/ota_update.dart'; +import 'package:http/http.dart' as http; + +import 'package:mobdr/service/shared_prefs.dart'; +import 'package:mobdr/config/constant.dart'; + +class UpdateCheckPage extends StatefulWidget { + @override + _UpdateCheckPageState createState() => _UpdateCheckPageState(); +} + +class _UpdateCheckPageState extends State { + OtaEvent? currentEvent = null; + + String _currentVersion = SharedPrefs().appVersion; + String _latestVersion = ''; + String _releaseDate = ''; + List _releaseNotes = []; + String _downloadLink = ''; + String _checksum = ''; + + @override + void initState() { + super.initState(); + _fetchLatestVersion(); + } + + Future _fetchLatestVersion() async { + try { + final response = await http + .get(Uri.parse(DOMAIN_CHECK_VERSION + '/deploy/mobdr/version.json')); + final data = jsonDecode(response.body); + + setState(() { + _latestVersion = data['latest_version']; + _releaseDate = data['release_date']; + _releaseNotes = List.from(data['release_notes']); + _downloadLink = data['download_link']; + _checksum = data['checksum']; + }); + } catch (e) { + print('Error retrieving latest version : $e'); + } + } + + Future _doUpdate() async { + try { + OtaUpdate() + .execute( + _downloadLink, + // OPTIONAL + destinationFilename: 'app_release.apk', + //OPTIONAL, ANDROID ONLY - ABILITY TO VALIDATE CHECKSUM OF FILE: + sha256checksum: _checksum, + ) + .listen( + (OtaEvent event) { + setState(() => currentEvent = event); + }, + ); + } catch (e) { + print('Failed to make OTA update. Details: $e'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Checking for update'), + ), + body: Center( + child: currentEvent == null + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Current version : ', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + Text( + _currentVersion, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 22, + color: Colors.red, + ), + ), + SizedBox(height: 16), + Text( + 'Version available : ', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + Text( + _latestVersion, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + color: Colors.green, + ), + ), + if (_currentVersion != _latestVersion) ...[ + SizedBox(height: 16), + Text( + 'Publication date : $_releaseDate', + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(height: 8), + Text( + 'Release notes :', + style: TextStyle(fontWeight: FontWeight.bold), + ), + for (String note in _releaseNotes) ...[ + SizedBox(height: 4), + Text('- $note'), + ], + SizedBox(height: 16), + ElevatedButton( + onPressed: _doUpdate, + child: Text( + 'Update', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + ), + ), + ] else ...[ + SizedBox(height: 32), + Text( + 'You have the latest version', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + ], + ], + ) + : Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'OTA status', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox(height: 32), + Text('${currentEvent!.status}'), + SizedBox(height: 16), + Text( + '${currentEvent!.value}', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ) + ], + )), + ); + } +} diff --git a/lib/ui/sync/tab_synchro.dart b/lib/ui/sync/tab_synchro.dart index 252a931..492b291 100644 --- a/lib/ui/sync/tab_synchro.dart +++ b/lib/ui/sync/tab_synchro.dart @@ -7,6 +7,7 @@ import 'package:mobdr/config/global_style.dart'; import 'package:mobdr/main.dart'; import 'package:mobdr/events.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; +import 'package:mobdr/ui/appstore/updatecheck.dart'; import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/network/api_provider.dart'; import 'package:mobdr/db/box_visit_photo.dart'; @@ -71,7 +72,43 @@ class _SynchronizationPageState extends State _isInternetConnexion = true; // synchronization start - startSync(); + await startSync(); + + // Vérifier si une mise à jour est disponible + bool isUpdateAvailable = await _apiProvider.checkAppVersion(); + + if (isUpdateAvailable) { + // Afficher le message de mise à jour + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text("New version available"), + content: Text( + "A new version is available. Would you like to install it?"), + actions: [ + TextButton( + child: Text("No"), + onPressed: () { + Navigator.pop(context); // Closes the dialog box + }, + ), + TextButton( + child: Text("Yes"), + onPressed: () { + Navigator.pop(context); // Closes the dialog box + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => UpdateCheckPage()), + ); + }, + ), + ], + ); + }, + ); + } } } @@ -200,7 +237,7 @@ class _SynchronizationPageState extends State } } - void startSync() async { + Future startSync() async { // disable navigation bar buttons eventBus.fire(SynchronizationEvent(true)); diff --git a/macos/Podfile.lock b/macos/Podfile.lock index c77e049..10e64f5 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,4 +1,6 @@ PODS: + - audioplayers_darwin (0.0.1): + - FlutterMacOS - connectivity_plus (0.0.1): - FlutterMacOS - ReachabilitySwift @@ -28,13 +30,14 @@ PODS: - FlutterMacOS DEPENDENCIES: + - audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos`) - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - objectbox_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/objectbox_flutter_libs/macos`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`) @@ -45,6 +48,8 @@ SPEC REPOS: - ReachabilitySwift EXTERNAL SOURCES: + audioplayers_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos connectivity_plus: :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos device_info_plus: @@ -56,15 +61,16 @@ EXTERNAL SOURCES: package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos path_provider_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin sqflite: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos wakelock_macos: :path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos SPEC CHECKSUMS: + audioplayers_darwin: dcad41de4fbd0099cb3749f7ab3b0cb8f70b810c connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 diff --git a/pubspec.lock b/pubspec.lock index ef81716..5133d87 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -429,10 +429,10 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" file: dependency: transitive description: @@ -781,6 +781,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + ota_update: + dependency: "direct main" + description: + name: ota_update + sha256: "7ce0af2119458cb7cc3122ecdc4e18ec3c0108162bfab9a4b064d686e1a5fc22" + url: "https://pub.dev" + source: hosted + version: "5.1.0" package_config: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 465359b..058fb76 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.1+1 +version: 0.2.3+1 environment: sdk: '>=2.19.0 <3.0.0' @@ -99,7 +99,7 @@ dependencies: # https://pub.dev/packages/device_info_plus/ device_info_plus: ^8.2.0 - # https://pwebview_flutterub.dev/packages/webview_flutter/ + # https://pub.dev/packages/webview_flutter/ # MP4 webview_flutter: ^4.2.1 @@ -121,6 +121,9 @@ dependencies: # https://pub.dev/packages/permission_handler permission_handler: 10.3.0 + # https://pub.dev/packages/ota_update + ota_update: ^5.1.0 + # hhttps://pub.dev/packages/timelines #timelines: ^0.1.0