diff --git a/assets/i18n/en_US.json b/assets/i18n/en_US.json index fa9ec5fc..225863d6 100644 --- a/assets/i18n/en_US.json +++ b/assets/i18n/en_US.json @@ -1,6 +1,7 @@ { "okButton": "OK", "cancelButton": "Cancel", + "updateButton": "Update", "enabledLabel": "Enabled", "disabledLabel": "Disabled", "yesButton": "Yes", @@ -21,7 +22,7 @@ "noInstallations": "No patched applications installed", "installed": "Installed", "updateDialogTitle": "Update Manager", - "updateDialogText": "Are you sure you want to download and update ReVanced Manager?", + "updateChangelogTitle": "Changelog", "notificationTitle": "Update downloaded", "notificationText": "Tap to install the update", "downloadingMessage": "Downloading update...", diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index 6c34748d..bf73bb5f 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -51,7 +51,7 @@ class GithubAPI { } } - Future?> _getLatestRelease(String repoName) async { + Future?> getLatestRelease(String repoName) async { try { var response = await _dio.get( '/repos/$repoName/releases/latest', @@ -97,7 +97,7 @@ class GithubAPI { Future getLatestReleaseFile(String extension, String repoName) async { try { - Map? release = await _getLatestRelease(repoName); + Map? release = await getLatestRelease(repoName); if (release != null) { Map? asset = (release['assets'] as List).firstWhereOrNull( @@ -133,7 +133,7 @@ class GithubAPI { Future getLastestReleaseVersion(String repoName) async { try { - Map? release = await _getLatestRelease(repoName); + Map? release = await getLatestRelease(repoName); if (release != null) { return release['tag_name']; } else { diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 764a03ec..60317247 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -12,10 +12,11 @@ import 'package:revanced_manager/app/app.router.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/patcher_api.dart'; +import 'package:revanced_manager/services/github_api.dart'; import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; -import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; +import 'package:revanced_manager/ui/widgets/homeView/update_confirmation_dialog.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; @@ -26,6 +27,7 @@ class HomeViewModel extends BaseViewModel { final NavigationService _navigationService = locator(); final ManagerAPI _managerAPI = locator(); final PatcherAPI _patcherAPI = locator(); + final GithubAPI _githubAPI = locator(); final Toast _toast = locator(); final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); DateTime? _lastUpdate; @@ -147,36 +149,26 @@ class HomeViewModel extends BaseViewModel { _toast.showBottom('homeView.updatesDisabled'); } - Future showUpdateConfirmationDialog(BuildContext parentContext) async { - return showDialog( + Future showUpdateConfirmationDialog(BuildContext parentContext) { + return showModalBottomSheet( context: parentContext, - builder: (context) => AlertDialog( - title: I18nText('homeView.updateDialogTitle'), - backgroundColor: Theme.of(context).colorScheme.secondaryContainer, - content: I18nText('homeView.updateDialogText'), - actions: [ - CustomMaterialButton( - isFilled: false, - label: I18nText('noButton'), - onPressed: () => Navigator.of(context).pop(), - ), - CustomMaterialButton( - label: I18nText('yesButton'), - onPressed: () { - Navigator.of(context).pop(); - updateManager(parentContext); - }, - ) - ], + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(24.0)), ), + builder: (context) => const UpdateConfirmationDialog(), ); } - Future getLatestPatcherReleaseTime() async { + Future?> getLatestManagerRelease() { + return _githubAPI.getLatestRelease(_managerAPI.defaultManagerRepo); + } + + Future getLatestPatcherReleaseTime() { return _managerAPI.getLatestPatcherReleaseTime(); } - Future getLatestManagerReleaseTime() async { + Future getLatestManagerReleaseTime() { return _managerAPI.getLatestManagerReleaseTime(); } diff --git a/lib/ui/widgets/homeView/update_confirmation_dialog.dart b/lib/ui/widgets/homeView/update_confirmation_dialog.dart new file mode 100644 index 00000000..bee19399 --- /dev/null +++ b/lib/ui/widgets/homeView/update_confirmation_dialog.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; +import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; + +class UpdateConfirmationDialog extends StatelessWidget { + const UpdateConfirmationDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final HomeViewModel model = locator(); + + return DraggableScrollableSheet( + expand: false, + initialChildSize: 0.5, + snap: true, + snapSizes: const [0.5], + builder: (context, scrollController) => SingleChildScrollView( + controller: scrollController, + child: SafeArea( + child: FutureBuilder?>( + future: model.getLatestManagerRelease(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const SizedBox( + height: 300, + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only( + top: 40.0, left: 24.0, right: 24.0, bottom: 32.0), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + I18nText( + 'homeView.updateDialogTitle', + child: const Text( + "", + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + ), + const SizedBox(height: 4.0), + Row( + children: [ + Icon( + Icons.new_releases_outlined, + color: + Theme.of(context).colorScheme.secondary, + ), + const SizedBox(width: 8.0), + Text( + snapshot.data!["tag_name"] ?? "Unknown", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .colorScheme + .secondary, + ), + ), + ], + ), + ], + ), + ), + CustomMaterialButton( + isExpanded: true, + label: I18nText('updateButton'), + onPressed: () { + Navigator.of(context).pop(); + model.updateManager(context); + }, + ) + ], + ), + ), + Padding( + padding: const EdgeInsets.only(left: 24.0, bottom: 12.0), + child: I18nText( + 'homeView.updateChangelogTitle', + child: Text( + "", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer), + ), + ), + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 24.0), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(12.0), + ), + child: Markdown( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(20.0), + data: snapshot.data!["body"] ?? "", + ), + ), + ], + ); + }, + ), + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 94b86e55..0fe1ce9a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,6 +76,7 @@ dependencies: sentry_dio: ^6.12.2 flutter_dotenv: ^5.0.2 pub_release: ^8.0.3 + flutter_markdown: ^0.6.13 dev_dependencies: json_serializable: ^6.3.1