diff --git a/assets/locales/en_us.json b/assets/locales/en_us.json index c7298fe..4414ba5 100644 --- a/assets/locales/en_us.json +++ b/assets/locales/en_us.json @@ -55,7 +55,7 @@ "edit": "Edit", "delete": "Delete", "settings": "Settings", - "settingsNotificationBgService": "Background Notification Service", + "settingsNotificationBgService": "Background notification service", "settingsNotificationBgServiceDesc": "A notification service is always installed on the device, so that some devices that do not support push notifications can receive notifications in the background. When this feature is enabled, push notifications will not be registered with the server, and you will always appear to be online in the eyes of others (except for invisible). You may need to turn off power and traffic optimization in the settings.", "search": "Search", "post": "Post", @@ -428,5 +428,9 @@ "preferencesApplied": "Preferences has been applied.", "save": "Save", "updateAvailable": "Update available", - "updateAvailableDesc": "There is an update available (@version). Do you want to download and install it now? You can still use the app normally while waiting for the download to complete." + "updateAvailableDesc": "There is an update available (@version). Do you want to download and install it now? You can still use the app normally while waiting for the download to complete.", + "update": "Update", + "updateCheckStrictly": "Strict mode", + "updateCheckStrictlyDesc": "If enabled, the app will ask for updating once the local version is different from remote one.", + "updateMayAvailable": "App version @version is available, you can update from app store or our website." } diff --git a/assets/locales/zh_cn.json b/assets/locales/zh_cn.json index 78484cc..53be8fb 100644 --- a/assets/locales/zh_cn.json +++ b/assets/locales/zh_cn.json @@ -424,5 +424,9 @@ "preferencesApplied": "偏好设置已应用", "save": "保存", "updateAvailable": "有可用更新", - "updateAvailableDesc": "有可用更新 (@version) 你想现在下载安装吗?在等待下载期间你仍可以正常使用。" + "updateAvailableDesc": "有可用更新 (@from 到 @to) 你想现在下载安装吗?在等待下载期间你仍可以正常使用。", + "update": "更新", + "updateCheckStrictly": "严格模式", + "updateCheckStrictlyDesc": "如果启用,应用程序将会在本地版本与远程版本不同时询问更新,而不会检查版本号大小。", + "updateMayAvailable": "版本 @version 现已可用,你可以前往应用商店或是我们的官网下载更新。" } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0f696c3..7449cbd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -154,6 +154,8 @@ PODS: - PromisesSwift (~> 2.1) - FirebaseSharedSwift (11.2.0) - Flutter (1.0.0) + - flutter_app_update (0.0.1): + - Flutter - flutter_background_service_ios (0.0.3): - Flutter - flutter_keyboard_visibility (0.0.1): @@ -306,6 +308,7 @@ DEPENDENCIES: - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - firebase_performance (from `.symlinks/plugins/firebase_performance/ios`) - Flutter (from `Flutter`) + - flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`) - flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`) - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) @@ -383,6 +386,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_performance/ios" Flutter: :path: Flutter + flutter_app_update: + :path: ".symlinks/plugins/flutter_app_update/ios" flutter_background_service_ios: :path: ".symlinks/plugins/flutter_background_service_ios/ios" flutter_keyboard_visibility: @@ -464,6 +469,7 @@ SPEC CHECKSUMS: FirebaseSessions: adcec8b72d0066a385e3affcd1bcb1ebb3908ce6 FirebaseSharedSwift: 7a0d78d155ede78407f0fdc89fbc914014c7c540 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_app_update: 65f61da626cb111d1b24674abc4b01728d7723bc flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 diff --git a/lib/bootstrapper.dart b/lib/bootstrapper.dart index 2ed03e3..53e0675 100644 --- a/lib/bootstrapper.dart +++ b/lib/bootstrapper.dart @@ -1,8 +1,11 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; import 'package:get/get.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:solian/exts.dart'; import 'package:solian/platform.dart'; import 'package:solian/providers/auth.dart'; @@ -14,6 +17,7 @@ import 'package:solian/providers/websocket.dart'; import 'package:solian/services.dart'; import 'package:solian/widgets/sized_container.dart'; import 'package:flutter_app_update/flutter_app_update.dart'; +import 'package:version/version.dart'; class BootstrapperShell extends StatefulWidget { final Widget child; @@ -35,6 +39,8 @@ class _BootstrapperShellState extends State { int _periodCursor = 0; + final Completer _bootCompleter = Completer(); + late final List<({String label, Future Function() action})> _periods = [ ( label: 'bsLoadingTheme', @@ -47,12 +53,20 @@ class _BootstrapperShellState extends State { action: () async { if (PlatformInfo.isWeb) return; try { + final prefs = await SharedPreferences.getInstance(); final info = await PackageInfo.fromPlatform(); final localVersionString = '${info.version}+${info.buildNumber}'; final resp = await GetConnect().get( 'https://git.solsynth.dev/api/v1/repos/hydrogen/solian/tags?page=1&limit=1', ); - if (resp.body[0]['name'] != localVersionString) { + final remoteVersionString = + (resp.body as List).firstOrNull?['name'] ?? '0.0.0'; + final remoteVersion = Version.parse(remoteVersionString ?? '0.0.0'); + final localVersion = + Version.parse(localVersionString.split('+').first); + final strictUpdate = prefs.getBool('check_update_strictly') ?? false; + if (remoteVersion > localVersion || + (remoteVersionString != localVersionString && strictUpdate)) { setState(() { _isErrored = true; _subtitle = 'bsCheckForUpdateDesc'.tr; @@ -63,7 +77,8 @@ class _BootstrapperShellState extends State { .showConfirmDialog( 'updateAvailable'.tr, 'updateAvailableDesc'.trParams({ - 'version': resp.body[0]['name'], + 'from': localVersionString, + 'to': remoteVersionString, }), ) .then((result) { @@ -75,21 +90,23 @@ class _BootstrapperShellState extends State { 'https://testflight.apple.com/join/YJ0lmN6O', ); AzhonAppUpdate.update(model); - if (mounted) { - setState(() { - _isErrored = false; - _subtitle = null; - }); - } } }); + } else { + setState(() { + _isErrored = true; + _subtitle = 'bsCheckForUpdateDesc'.tr; + }); } + } else if (remoteVersionString != localVersionString) { + _bootCompleter.future.then((_) { + context.showSnackbar('updateMayAvailable'.trParams({ + 'version': remoteVersionString, + })); + }); } } catch (e) { - setState(() { - _isErrored = true; - _subtitle = 'bsCheckForUpdateFailed'.tr; - }); + context.showErrorDialog('Unable to check update: $e'); } }, ), @@ -180,6 +197,9 @@ class _BootstrapperShellState extends State { } } finally { setState(() => _isBusy = false); + Future.delayed(const Duration(milliseconds: 100), () { + _bootCompleter.complete(); + }); } } @@ -277,6 +297,9 @@ class _BootstrapperShellState extends State { _isBusy = false; _isErrored = false; }); + Future.delayed(const Duration(milliseconds: 100), () { + _bootCompleter.complete(); + }); } else { setState(() { _isBusy = true; diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index 955730a..b83f924 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -114,6 +114,21 @@ class _SettingScreenState extends State { }, ), ), + _buildCaptionHeader('update'.tr), + CheckboxListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 22), + secondary: const Icon(Icons.sync_alt), + title: Text('updateCheckStrictly'.tr), + subtitle: Text('updateCheckStrictlyDesc'.tr), + value: _prefs?.getBool('check_update_strictly') ?? false, + onChanged: (value) { + _prefs + ?.setBool('check_update_strictly', value ?? false) + .then((_) { + setState(() {}); + }); + }, + ), _buildCaptionHeader('more'.tr), ListTile( leading: const Icon(Icons.delete_sweep), diff --git a/pubspec.lock b/pubspec.lock index 41bee73..eae0d8e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: ddc6f775260b89176d329dee26f88b9469ef46aa3228ff6a0b91caf2b2989692 + sha256: "5fdcea390499dd26c808a3c662df5f4208d6bbc0643072eee94f1476249e2818" url: "https://pub.dev" source: hosted - version: "1.3.42" + version: "1.3.43" _macros: dependency: transitive description: dart @@ -490,114 +490,114 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: "7b5ae39d853ead76f9d030dc23389bfec4ea826d7cccb4eea4873dcb0cdd172b" + sha256: "9c52c099e9cbb852c7f1d2302c7eb34a15758834eca1877f7a779e6082f9882d" url: "https://pub.dev" source: hosted - version: "11.3.1" + version: "11.3.2" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "0205e05bb37abd29d5dec5cd89aeb04f3f58bf849aad21dd938be0507d52a40c" + sha256: "4ec57aee951832fdbf10ca722bbb83fe0001d6168d6c4cfea9ccee0df6afb1e0" url: "https://pub.dev" source: hosted - version: "4.2.3" + version: "4.2.4" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "434807f8b30526e21cc062410c28ee5c6680a13626c4443b5ffede29f84b0c74" + sha256: "95c594fb1e8960992a607b135459e2f9ea3683dd8d01e6b845cace7c6665ec7e" url: "https://pub.dev" source: hosted - version: "0.5.10" + version: "0.5.10+1" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "40921de9795fbf5887ed5c0adfdf4972d5a8d7ae7e1b2bb98dea39bc02626a88" + sha256: c7de9354eb2cd8bfe8059e1112174c9a58beda7051807207306bc48283277cfb url: "https://pub.dev" source: hosted - version: "3.4.1" + version: "3.5.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: f7d7180c7f99babd4b4c517754d41a09a4943a0f7a69b65c894ca5c68ba66315 + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 url: "https://pub.dev" source: hosted - version: "5.2.1" + version: "5.3.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: f4ee170441ca141c5f9ee5ad8737daba3ee9c8e7efb6902aee90b4fbd178ce25 + sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 url: "https://pub.dev" source: hosted - version: "2.18.0" + version: "2.18.1" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics - sha256: c4fdbb14ba6f36794f89dc27fb5c759c9cc67ecbaeb079edc4dba515bbf9f555 + sha256: "7821f9d8373b91f2a5ca8214226891d5870e196a7376f66350f65204387e9c15" url: "https://pub.dev" source: hosted - version: "4.1.1" + version: "4.1.2" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: "891d6f7ba4b93672d0e1265f27b6a9dccd56ba2cc30ce6496586b32d1d8770ac" + sha256: "8ed539fd9e9b6c07905f9f44c5f6d4785ac841a5a8195bd35586c8b1d54ec26d" url: "https://pub.dev" source: hosted - version: "3.6.42" + version: "3.6.43" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: cc02c4afd6510cd84586020670140c4a23fbe52af16cd260ccf8ede101bb8d1b + sha256: "32ce60b747e755b48d7112d728d4f736ba82acd98ec825626558d444d385fa3a" url: "https://pub.dev" source: hosted - version: "15.1.1" + version: "15.1.2" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: d8a4984635f09213302243ea670fe5c42f3261d7d8c7c0a5f7dcd5d6c84be459 + sha256: "69671a0f1a40c7b7c46ad0283e6f34ca2a59a0362ca14a240a4ea01c46e8a521" url: "https://pub.dev" source: hosted - version: "4.5.44" + version: "4.5.45" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "258b9d637965db7855299b123533609ed95e52350746a723dfd1d8d6f3fac678" + sha256: "6890111a9d01d7b13d0f6fe74850812c334e903d2c80a2d9356a3abb8c3a9e9a" url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.9.1" firebase_performance: dependency: "direct main" description: name: firebase_performance - sha256: "879ce4d83242cb7d1ec67a8b45daa351f230211778e34eeea979894839c4832a" + sha256: ed9a408b6d1f221fc0e2890dcf0733b604d1aea6cd3b897f97dd3f889f01ddfc url: "https://pub.dev" source: hosted - version: "0.10.0+6" + version: "0.10.0+7" firebase_performance_platform_interface: dependency: transitive description: name: firebase_performance_platform_interface - sha256: ac68eba644f593903a931ba7f26f0677b725d5a60f8f7bc0fed01d88a11d1463 + sha256: bfcfbfcefeaf3853a72602675b786e13a609d49ac70fc325d302b5794b8b0c06 url: "https://pub.dev" source: hosted - version: "0.1.4+42" + version: "0.1.4+43" firebase_performance_web: dependency: transitive description: name: firebase_performance_web - sha256: ff53b9c5d8601fc983d0173b88fdfd8abcc74948f0a3753f3c1ec276b680f23c + sha256: "2ac9e44a1be7b20f1a7a3912d84bf2e1ec76398f2dadc07b6b7c3173d590e329" url: "https://pub.dev" source: hosted - version: "0.1.7" + version: "0.1.7+1" fixnum: dependency: transitive description: @@ -2138,6 +2138,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + version: + dependency: "direct main" + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" very_good_infinite_list: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index cc172af..c7240a3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -81,6 +81,7 @@ dependencies: flutter_background_service: ^5.0.10 flutter_local_notifications: ^17.2.2 flutter_app_update: ^3.1.0 + version: ^3.0.2 dev_dependencies: flutter_test: