✨ Updater
This commit is contained in:
		| @@ -718,5 +718,8 @@ | ||||
|   "stickersNew": "New Sticker", | ||||
|   "stickersNewDescription": "Create a new sticker belongs to this pack.", | ||||
|   "stickersPackNew": "New Sticker Pack", | ||||
|   "trayMenuShow": "Show" | ||||
|   "trayMenuShow": "Show", | ||||
|   "update": "Update", | ||||
|   "forceUpdate": "Force Update", | ||||
|   "forceUpdateDescription": "Force to show the application update popup, even the new version is not available." | ||||
| } | ||||
|   | ||||
| @@ -716,5 +716,8 @@ | ||||
|   "stickersNew": "新建贴图", | ||||
|   "stickersNewDescription": "创建一个新的贴图。", | ||||
|   "stickersPackNew": "新建贴图包", | ||||
|   "trayMenuShow": "显示" | ||||
|   "trayMenuShow": "显示", | ||||
|   "update": "更新", | ||||
|   "forceUpdate": "强制更新", | ||||
|   "forceUpdateDescription": "强制更新应用程序,即使有更新的版本可能不可用。" | ||||
| } | ||||
|   | ||||
| @@ -715,5 +715,9 @@ | ||||
|   "fieldStickerAttachment": "附件", | ||||
|   "stickersNew": "新建貼圖", | ||||
|   "stickersNewDescription": "創建一個新的貼圖。", | ||||
|   "stickersPackNew": "新建貼圖包" | ||||
|   "stickersPackNew": "新建貼圖包", | ||||
|   "trayMenuShow": "顯示", | ||||
|   "update": "更新", | ||||
|   "forceUpdate": "強制更新", | ||||
|   "forceUpdateDescription": "強制更新應用程序,即使有更新的版本可能不可用。" | ||||
| } | ||||
|   | ||||
| @@ -715,5 +715,9 @@ | ||||
|   "fieldStickerAttachment": "附件", | ||||
|   "stickersNew": "新建貼圖", | ||||
|   "stickersNewDescription": "創建一個新的貼圖。", | ||||
|   "stickersPackNew": "新建貼圖包" | ||||
|   "stickersPackNew": "新建貼圖包", | ||||
|   "trayMenuShow": "顯示", | ||||
|   "update": "更新", | ||||
|   "forceUpdate": "強制更新", | ||||
|   "forceUpdateDescription": "強制更新應用程序,即使有更新的版本可能不可用。" | ||||
| } | ||||
|   | ||||
| @@ -179,7 +179,7 @@ PODS: | ||||
|   - in_app_review (2.0.0): | ||||
|     - Flutter | ||||
|   - Kingfisher (8.2.0) | ||||
|   - livekit_client (2.3.6): | ||||
|   - livekit_client (2.4.0): | ||||
|     - Flutter | ||||
|     - flutter_webrtc | ||||
|     - WebRTC-SDK (= 125.6422.06) | ||||
| @@ -426,7 +426,7 @@ SPEC CHECKSUMS: | ||||
|   image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 | ||||
|   in_app_review: a31b5257259646ea78e0e35fc914979b0031d011 | ||||
|   Kingfisher: 323e5c4ec7983aaace12af655a7b51a7f88a599d | ||||
|   livekit_client: 148b2cf67a09aaf475ba8e5bf1667fe10dc35f81 | ||||
|   livekit_client: 9819ebc8be8ef00ed0fae7d806bf8938ec689573 | ||||
|   media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 | ||||
|   media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a | ||||
|   media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e | ||||
|   | ||||
| @@ -254,10 +254,9 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener { | ||||
|           receiveTimeout: const Duration(seconds: 60), | ||||
|         ), | ||||
|       ).get( | ||||
|         'https://git.solsynth.dev/api/v1/repos/HyperNet/Surface/tags?page=1&limit=1', | ||||
|         'https://api.github.com/repos/Solsynth/HyperNet.Surface/releases/latest', | ||||
|       ); | ||||
|       final remoteVersionString = | ||||
|           (resp.data as List).firstOrNull?['name'] ?? '0.0.0+0'; | ||||
|       final remoteVersionString = resp.data?['tag_name'] ?? '0.0.0+0'; | ||||
|       final remoteVersion = Version.parse(remoteVersionString.split('+').first); | ||||
|       final localVersion = Version.parse(localVersionString.split('+').first); | ||||
|       final remoteBuildNumber = | ||||
| @@ -269,10 +268,12 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener { | ||||
|               remoteBuildNumber > localBuildNumber) && | ||||
|           mounted) { | ||||
|         final config = context.read<ConfigProvider>(); | ||||
|         config.setUpdate(remoteVersionString); | ||||
|         config.setUpdate( | ||||
|             remoteVersionString, resp.data?['body'] ?? 'No changelog'); | ||||
|         log("[Update] Update available: $remoteVersionString"); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       log('[Error] Unable to check update: $e'); | ||||
|       if (mounted) context.showErrorDialog('Unable to check update: $e'); | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -58,7 +58,8 @@ class ConfigProvider extends ChangeNotifier { | ||||
|           : false; | ||||
|     } | ||||
|  | ||||
|     if (newDrawerIsExpanded != drawerIsExpanded || newDrawerIsCollapsed != drawerIsCollapsed) { | ||||
|     if (newDrawerIsExpanded != drawerIsExpanded || | ||||
|         newDrawerIsCollapsed != drawerIsCollapsed) { | ||||
|       drawerIsExpanded = newDrawerIsExpanded; | ||||
|       drawerIsCollapsed = newDrawerIsCollapsed; | ||||
|       notifyListeners(); | ||||
| @@ -66,7 +67,9 @@ class ConfigProvider extends ChangeNotifier { | ||||
|   } | ||||
|  | ||||
|   FilterQuality get imageQuality { | ||||
|     return kImageQualityLevel.values.elementAtOrNull(prefs.getInt('app_image_quality') ?? 3) ?? FilterQuality.high; | ||||
|     return kImageQualityLevel.values | ||||
|             .elementAtOrNull(prefs.getInt('app_image_quality') ?? 3) ?? | ||||
|         FilterQuality.high; | ||||
|   } | ||||
|  | ||||
|   String get serverUrl { | ||||
| @@ -76,6 +79,7 @@ class ConfigProvider extends ChangeNotifier { | ||||
|   bool get realmCompactView { | ||||
|     return prefs.getBool(kAppRealmCompactView) ?? false; | ||||
|   } | ||||
|  | ||||
|   set realmCompactView(bool value) { | ||||
|     prefs.setBool(kAppRealmCompactView, value); | ||||
|   } | ||||
| @@ -86,9 +90,11 @@ class ConfigProvider extends ChangeNotifier { | ||||
|   } | ||||
|  | ||||
|   String? updatableVersion; | ||||
|   String? updatableChangelog; | ||||
|  | ||||
|   void setUpdate(String newVersion) { | ||||
|   void setUpdate(String newVersion, String newChangelog) { | ||||
|     updatableVersion = newVersion; | ||||
|     updatableChangelog = newChangelog; | ||||
|     notifyListeners(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,10 +1,8 @@ | ||||
| import 'dart:io'; | ||||
| import 'dart:math' as math; | ||||
| import 'dart:ui'; | ||||
|  | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter_app_update/flutter_app_update.dart'; | ||||
| import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:go_router/go_router.dart'; | ||||
| @@ -29,6 +27,7 @@ import 'package:surface/widgets/app_bar_leading.dart'; | ||||
| import 'package:surface/widgets/dialog.dart'; | ||||
| import 'package:surface/widgets/navigation/app_scaffold.dart'; | ||||
| import 'package:surface/widgets/post/post_item.dart'; | ||||
| import 'package:surface/widgets/updater.dart'; | ||||
|  | ||||
| class HomeScreenDashEntry { | ||||
|   final String name; | ||||
| @@ -83,14 +82,20 @@ class _HomeScreenState extends State<HomeScreen> { | ||||
|       body: LayoutBuilder( | ||||
|         builder: (context, constraints) { | ||||
|           return Align( | ||||
|             alignment: constraints.maxWidth > 640 ? Alignment.center : Alignment.topCenter, | ||||
|             alignment: constraints.maxWidth > 640 | ||||
|                 ? Alignment.center | ||||
|                 : Alignment.topCenter, | ||||
|             child: Container( | ||||
|               constraints: const BoxConstraints(maxWidth: 640), | ||||
|               child: SingleChildScrollView( | ||||
|                 child: Column( | ||||
|                   mainAxisAlignment: constraints.maxWidth > 640 ? MainAxisAlignment.center : MainAxisAlignment.start, | ||||
|                   mainAxisAlignment: constraints.maxWidth > 640 | ||||
|                       ? MainAxisAlignment.center | ||||
|                       : MainAxisAlignment.start, | ||||
|                   children: [ | ||||
|                     _HomeDashUpdateWidget(padding: const EdgeInsets.only(bottom: 8, left: 8, right: 8)), | ||||
|                     _HomeDashUpdateWidget( | ||||
|                         padding: const EdgeInsets.only( | ||||
|                             bottom: 8, left: 8, right: 8)), | ||||
|                     _HomeDashSpecialDayWidget().padding(horizontal: 8), | ||||
|                     StaggeredGrid.extent( | ||||
|                       maxCrossAxisExtent: 280, | ||||
| @@ -136,21 +141,15 @@ class _HomeDashUpdateWidget extends StatelessWidget { | ||||
|                 leading: Icon(Symbols.update), | ||||
|                 title: Text('updateAvailable').tr(), | ||||
|                 subtitle: Text(config.updatableVersion!), | ||||
|                 trailing: (kIsWeb || Platform.isWindows || Platform.isLinux) | ||||
|                     ? null | ||||
|                     : IconButton( | ||||
|                         icon: const Icon(Symbols.arrow_right_alt), | ||||
|                         onPressed: () { | ||||
|                           final model = UpdateModel( | ||||
|                             'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk', | ||||
|                             'solian-app-release-${config.updatableVersion!}.apk', | ||||
|                             'ic_launcher', | ||||
|                             'https://apps.apple.com/us/app/solian/id6499032345', | ||||
|                           ); | ||||
|                           AzhonAppUpdate.update(model); | ||||
|                           context.showSnackbar('updateOngoing'.tr()); | ||||
|                         }, | ||||
|                       ), | ||||
|                 trailing: IconButton( | ||||
|                   icon: const Icon(Symbols.arrow_right_alt), | ||||
|                   onPressed: () { | ||||
|                     showModalBottomSheet( | ||||
|                       context: context, | ||||
|                       builder: (context) => VersionUpdatePopup(), | ||||
|                     ); | ||||
|                   }, | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
| @@ -166,7 +165,8 @@ class _HomeDashSpecialDayWidget extends StatefulWidget { | ||||
|   const _HomeDashSpecialDayWidget(); | ||||
|  | ||||
|   @override | ||||
|   State<_HomeDashSpecialDayWidget> createState() => _HomeDashSpecialDayWidgetState(); | ||||
|   State<_HomeDashSpecialDayWidget> createState() => | ||||
|       _HomeDashSpecialDayWidgetState(); | ||||
| } | ||||
|  | ||||
| class _HomeDashSpecialDayWidgetState extends State<_HomeDashSpecialDayWidget> { | ||||
| @@ -208,7 +208,9 @@ class _HomeDashSpecialDayWidgetState extends State<_HomeDashSpecialDayWidget> { | ||||
|         margin: EdgeInsets.zero, | ||||
|         child: ListTile( | ||||
|           leading: Text(kSpecialDaysSymbol[name] ?? '🎉').fontSize(24), | ||||
|           title: Text('pending$name').tr(args: [RelativeTime(context).format(date).replaceFirst('in', '').trim()]), | ||||
|           title: Text('pending$name').tr(args: [ | ||||
|             RelativeTime(context).format(date).replaceFirst('in', '').trim() | ||||
|           ]), | ||||
|           subtitle: Row( | ||||
|             crossAxisAlignment: CrossAxisAlignment.center, | ||||
|             children: [ | ||||
| @@ -297,12 +299,19 @@ class _HomeDashTodayNewsState extends State<_HomeDashTodayNews> { | ||||
|                   children: [ | ||||
|                     Text( | ||||
|                       _article!.title, | ||||
|                       style: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 18), | ||||
|                       maxLines: MediaQuery.of(context).size.width >= 640 ? 2 : 1, | ||||
|                       style: Theme.of(context) | ||||
|                           .textTheme | ||||
|                           .titleMedium! | ||||
|                           .copyWith(fontSize: 18), | ||||
|                       maxLines: | ||||
|                           MediaQuery.of(context).size.width >= 640 ? 2 : 1, | ||||
|                       overflow: TextOverflow.ellipsis, | ||||
|                     ), | ||||
|                     Text( | ||||
|                       parse(_article!.description).children.map((e) => e.text.trim()).join(), | ||||
|                       parse(_article!.description) | ||||
|                           .children | ||||
|                           .map((e) => e.text.trim()) | ||||
|                           .join(), | ||||
|                       maxLines: 3, | ||||
|                       overflow: TextOverflow.ellipsis, | ||||
|                       style: Theme.of(context).textTheme.bodyMedium, | ||||
| @@ -313,9 +322,13 @@ class _HomeDashTodayNewsState extends State<_HomeDashTodayNews> { | ||||
|                         crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                         spacing: 2, | ||||
|                         children: [ | ||||
|                           Text(DateFormat().format(date)).textStyle(Theme.of(context).textTheme.bodySmall!), | ||||
|                           Text(' · ').textStyle(Theme.of(context).textTheme.bodySmall!).bold(), | ||||
|                           Text(RelativeTime(context).format(date)).textStyle(Theme.of(context).textTheme.bodySmall!), | ||||
|                           Text(DateFormat().format(date)).textStyle( | ||||
|                               Theme.of(context).textTheme.bodySmall!), | ||||
|                           Text(' · ') | ||||
|                               .textStyle(Theme.of(context).textTheme.bodySmall!) | ||||
|                               .bold(), | ||||
|                           Text(RelativeTime(context).format(date)).textStyle( | ||||
|                               Theme.of(context).textTheme.bodySmall!), | ||||
|                         ], | ||||
|                       ).opacity(0.75); | ||||
|                     }), | ||||
| @@ -386,15 +399,20 @@ class _HomeDashCheckInWidgetState extends State<_HomeDashCheckInWidget> { | ||||
|   } | ||||
|  | ||||
|   Widget _buildDetailChunk(int index, bool positive) { | ||||
|     final prefix = positive ? 'dailyCheckPositiveHint' : 'dailyCheckNegativeHint'; | ||||
|     final mod = positive ? kSuggestionPositiveHintCount : kSuggestionNegativeHintCount; | ||||
|     final prefix = | ||||
|         positive ? 'dailyCheckPositiveHint' : 'dailyCheckNegativeHint'; | ||||
|     final mod = | ||||
|         positive ? kSuggestionPositiveHintCount : kSuggestionNegativeHintCount; | ||||
|     final pos = math.max(1, _todayRecord!.resultModifiers[index] % mod); | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         Text( | ||||
|           prefix.tr(args: ['$prefix$pos'.tr()]), | ||||
|           style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold), | ||||
|           style: Theme.of(context) | ||||
|               .textTheme | ||||
|               .titleMedium! | ||||
|               .copyWith(fontWeight: FontWeight.bold), | ||||
|         ), | ||||
|         Text( | ||||
|           '$prefix${pos}Description', | ||||
| @@ -429,7 +447,10 @@ class _HomeDashCheckInWidgetState extends State<_HomeDashCheckInWidget> { | ||||
|               else | ||||
|                 Text( | ||||
|                   'dailyCheckEverythingIsNegative', | ||||
|                   style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold), | ||||
|                   style: Theme.of(context) | ||||
|                       .textTheme | ||||
|                       .titleMedium! | ||||
|                       .copyWith(fontWeight: FontWeight.bold), | ||||
|                 ).tr(), | ||||
|               const Gap(8), | ||||
|               if (_todayRecord?.resultTier != 4) | ||||
| @@ -445,7 +466,10 @@ class _HomeDashCheckInWidgetState extends State<_HomeDashCheckInWidget> { | ||||
|               else | ||||
|                 Text( | ||||
|                   'dailyCheckEverythingIsPositive', | ||||
|                   style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold), | ||||
|                   style: Theme.of(context) | ||||
|                       .textTheme | ||||
|                       .titleMedium! | ||||
|                       .copyWith(fontWeight: FontWeight.bold), | ||||
|                 ).tr(), | ||||
|             ], | ||||
|           ), | ||||
| @@ -571,10 +595,12 @@ class _HomeDashNotificationWidget extends StatefulWidget { | ||||
|   const _HomeDashNotificationWidget(); | ||||
|  | ||||
|   @override | ||||
|   State<_HomeDashNotificationWidget> createState() => _HomeDashNotificationWidgetState(); | ||||
|   State<_HomeDashNotificationWidget> createState() => | ||||
|       _HomeDashNotificationWidgetState(); | ||||
| } | ||||
|  | ||||
| class _HomeDashNotificationWidgetState extends State<_HomeDashNotificationWidget> { | ||||
| class _HomeDashNotificationWidgetState | ||||
|     extends State<_HomeDashNotificationWidget> { | ||||
|   int? _count; | ||||
|  | ||||
|   Future<void> _fetchNotificationCount() async { | ||||
| @@ -612,7 +638,9 @@ class _HomeDashNotificationWidgetState extends State<_HomeDashNotificationWidget | ||||
|                   style: Theme.of(context).textTheme.titleLarge, | ||||
|                 ).tr(), | ||||
|                 Text( | ||||
|                   _count == null ? 'loading'.tr() : 'notificationUnreadCount'.plural(_count ?? 0), | ||||
|                   _count == null | ||||
|                       ? 'loading'.tr() | ||||
|                       : 'notificationUnreadCount'.plural(_count ?? 0), | ||||
|                   style: Theme.of(context).textTheme.bodyLarge, | ||||
|                 ), | ||||
|               ], | ||||
| @@ -643,10 +671,12 @@ class _HomeDashRecommendationPostWidget extends StatefulWidget { | ||||
|   const _HomeDashRecommendationPostWidget(); | ||||
|  | ||||
|   @override | ||||
|   State<_HomeDashRecommendationPostWidget> createState() => _HomeDashRecommendationPostWidgetState(); | ||||
|   State<_HomeDashRecommendationPostWidget> createState() => | ||||
|       _HomeDashRecommendationPostWidgetState(); | ||||
| } | ||||
|  | ||||
| class _HomeDashRecommendationPostWidgetState extends State<_HomeDashRecommendationPostWidget> { | ||||
| class _HomeDashRecommendationPostWidgetState | ||||
|     extends State<_HomeDashRecommendationPostWidget> { | ||||
|   bool _isBusy = false; | ||||
|   List<SnPost>? _posts; | ||||
|  | ||||
| @@ -710,13 +740,15 @@ class _HomeDashRecommendationPostWidgetState extends State<_HomeDashRecommendati | ||||
|                   ).tr(), | ||||
|                 ], | ||||
|               ), | ||||
|               Text('${_currentPage + 1}/${_posts?.length ?? 0}', style: GoogleFonts.robotoMono()) | ||||
|               Text('${_currentPage + 1}/${_posts?.length ?? 0}', | ||||
|                   style: GoogleFonts.robotoMono()) | ||||
|             ], | ||||
|           ).padding(horizontal: 18, top: 12, bottom: 8), | ||||
|           Expanded( | ||||
|             child: PageView.builder( | ||||
|               controller: _pageController, | ||||
|               scrollBehavior: ScrollConfiguration.of(context).copyWith(dragDevices: { | ||||
|               scrollBehavior: | ||||
|                   ScrollConfiguration.of(context).copyWith(dragDevices: { | ||||
|                 PointerDeviceKind.mouse, | ||||
|                 PointerDeviceKind.touch, | ||||
|               }), | ||||
| @@ -729,7 +761,8 @@ class _HomeDashRecommendationPostWidgetState extends State<_HomeDashRecommendati | ||||
|                       showMenu: false, | ||||
|                     ).padding(bottom: 8), | ||||
|                     onTap: () { | ||||
|                       GoRouter.of(context).pushNamed('postDetail', pathParameters: { | ||||
|                       GoRouter.of(context) | ||||
|                           .pushNamed('postDetail', pathParameters: { | ||||
|                         'slug': _posts![index].id.toString(), | ||||
|                       }); | ||||
|                     }, | ||||
|   | ||||
| @@ -24,6 +24,7 @@ import 'package:surface/providers/theme.dart'; | ||||
| import 'package:surface/theme.dart'; | ||||
| import 'package:surface/widgets/dialog.dart'; | ||||
| import 'package:surface/widgets/navigation/app_scaffold.dart'; | ||||
| import 'package:surface/widgets/updater.dart'; | ||||
|  | ||||
| const Map<String, Color> kColorSchemes = { | ||||
|   'colorSchemeIndigo': Colors.indigo, | ||||
| @@ -604,6 +605,19 @@ class _SettingsScreenState extends State<SettingsScreen> { | ||||
|                     } | ||||
|                   }, | ||||
|                 ), | ||||
|                 ListTile( | ||||
|                   title: Text('forceUpdate').tr(), | ||||
|                   subtitle: Text('forceUpdateDescription').tr(), | ||||
|                   contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|                   leading: const Icon(Symbols.update), | ||||
|                   trailing: const Icon(Symbols.chevron_right), | ||||
|                   onTap: () async { | ||||
|                     showModalBottomSheet( | ||||
|                       context: context, | ||||
|                       builder: (context) => VersionUpdatePopup(), | ||||
|                     ); | ||||
|                   }, | ||||
|                 ), | ||||
|                 ListTile( | ||||
|                   title: Text('settingsMiscAbout').tr(), | ||||
|                   subtitle: Text('settingsMiscAboutDescription').tr(), | ||||
|   | ||||
							
								
								
									
										96
									
								
								lib/widgets/updater.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								lib/widgets/updater.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| import 'dart:io'; | ||||
|  | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_app_update/azhon_app_update.dart'; | ||||
| import 'package:flutter_app_update/update_model.dart'; | ||||
| import 'package:gap/gap.dart'; | ||||
| import 'package:google_fonts/google_fonts.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:surface/providers/config.dart'; | ||||
| import 'package:surface/widgets/dialog.dart'; | ||||
| import 'package:surface/widgets/markdown_content.dart'; | ||||
| import 'package:url_launcher/url_launcher_string.dart'; | ||||
|  | ||||
| class VersionUpdatePopup extends StatelessWidget { | ||||
|   const VersionUpdatePopup({super.key}); | ||||
|  | ||||
|   void _update(BuildContext context) async { | ||||
|     if (kIsWeb) return; | ||||
|  | ||||
|     final config = context.read<ConfigProvider>(); | ||||
|  | ||||
|     if (Platform.isAndroid) { | ||||
|       final model = UpdateModel( | ||||
|         'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk', | ||||
|         'solian-app-release-${config.updatableVersion!}.apk', | ||||
|         'ic_launcher', | ||||
|         'https://apps.apple.com/us/app/solian/id6499032345', | ||||
|       ); | ||||
|       AzhonAppUpdate.update(model); | ||||
|       context.showSnackbar('updateOngoing'.tr()); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     final resp = await Dio( | ||||
|       BaseOptions( | ||||
|         sendTimeout: const Duration(seconds: 60), | ||||
|         receiveTimeout: const Duration(seconds: 60), | ||||
|       ), | ||||
|     ).get( | ||||
|       'https://api.github.com/repos/Solsynth/HyperNet.Surface/releases/latest', | ||||
|     ); | ||||
|  | ||||
|     launchUrlString(resp.data?['html_url']); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final config = context.watch<ConfigProvider>(); | ||||
|  | ||||
|     return Column( | ||||
|       children: [ | ||||
|         Row( | ||||
|           children: [ | ||||
|             const Icon(Icons.update), | ||||
|             const Gap(16), | ||||
|             Text('update') | ||||
|                 .tr() | ||||
|                 .textStyle(Theme.of(context).textTheme.titleLarge!), | ||||
|           ], | ||||
|         ).padding(horizontal: 20, top: 16, bottom: 12), | ||||
|         Row( | ||||
|           children: [ | ||||
|             Expanded( | ||||
|               child: Text( | ||||
|                 config.updatableVersion ?? 'unknown'.tr(), | ||||
|                 style: GoogleFonts.robotoMono(), | ||||
|               ), | ||||
|             ), | ||||
|             ElevatedButton( | ||||
|               style: ButtonStyle( | ||||
|                 visualDensity: const VisualDensity( | ||||
|                   horizontal: -4, | ||||
|                   vertical: -3, | ||||
|                 ), | ||||
|               ), | ||||
|               onPressed: () => _update(context), | ||||
|               child: Text('update').tr(), | ||||
|             ), | ||||
|           ], | ||||
|         ).padding(horizontal: 20), | ||||
|         const Divider(height: 1).padding(vertical: 8), | ||||
|         Expanded( | ||||
|           child: SingleChildScrollView( | ||||
|             child: MarkdownTextContent( | ||||
|               content: config.updatableChangelog ?? 'No changelog', | ||||
|             ).padding(horizontal: 20), | ||||
|           ), | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -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: 2.3.2+71 | ||||
| version: 2.3.2+70 | ||||
|  | ||||
| environment: | ||||
|   sdk: ^3.5.4 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user