From e88e997436d8692023d49480089fe7d71538492b Mon Sep 17 00:00:00 2001 From: kitadai31 <90122968+kitadai31@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:07:01 +0900 Subject: [PATCH 1/6] feat: Pre-release patches toggle --- assets/i18n/strings.i18n.json | 4 ++ lib/services/github_api.dart | 31 +--------- lib/services/manager_api.dart | 22 +++++-- lib/ui/views/home/home_viewmodel.dart | 8 ++- lib/ui/views/settings/settings_viewmodel.dart | 60 +++++++++++++++++++ .../settings_use_alternative_sources.dart | 11 +++- .../settings_use_prerelease_patches.dart | 35 +++++++++++ 7 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 lib/ui/widgets/settingsView/settings_use_prerelease_patches.dart diff --git a/assets/i18n/strings.i18n.json b/assets/i18n/strings.i18n.json index fa08eb0283..9de25d2e07 100755 --- a/assets/i18n/strings.i18n.json +++ b/assets/i18n/strings.i18n.json @@ -208,6 +208,10 @@ "requireSuggestedAppVersionLabel": "Require suggested app version", "requireSuggestedAppVersionHint": "Prevent selecting an app with a version that is not the suggested", "requireSuggestedAppVersionDialogText": "Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?", + "usePrereleasePatchesLabel": "Use pre-release patches", + "usePrereleasePatchesHint": "Use the pre-release versions of patches and integrations", + "usePrereleasePatchesDialogText": "Pre-release patches are for development purposes and may cause unexpected issues.", + "usePrereleasePatchesDialogText2": "It may not be compatible with the current version of ReVanced Manager and may cause patching errors.\n\nDo you want to proceed anyways?", "aboutLabel": "About", "snackbarMessage": "Copied to clipboard", "restartAppForChanges": "Restart the app to apply changes", diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index 0c0080b9e6..36d248e1c7 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -21,12 +21,12 @@ class GithubAPI { await _downloadManager.clearAllCache(); } - Future?> getLatestRelease( + Future?> getLatestReleaseWithPreReleases( String repoName, ) async { try { final response = await _dio.get( - '/repos/$repoName/releases', + '/repos/$repoName/releases?per_page=1', ); return response.data[0]; } on Exception catch (e) { @@ -54,7 +54,7 @@ class GithubAPI { } } - Future?> getLatestPatchesRelease( + Future?> getLatestRelease( String repoName, ) async { try { @@ -108,31 +108,6 @@ class GithubAPI { } } - Future getLatestReleaseFile( - String extension, - String repoName, - ) async { - try { - final Map? release = await getLatestRelease(repoName); - if (release != null) { - final Map? asset = - (release['assets'] as List).firstWhereOrNull( - (asset) => (asset['name'] as String).endsWith(extension), - ); - if (asset != null) { - return await _downloadManager.getSingleFile( - asset['browser_download_url'], - ); - } - } - } on Exception catch (e) { - if (kDebugMode) { - print(e); - } - } - return null; - } - Future getPatchesReleaseFile( String extension, String repoName, diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 8851858724..be04239f55 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -222,6 +222,14 @@ class ManagerAPI { return _prefs.getBool('useAlternativeSources') ?? false; } + Future usePrereleasePatches(bool value) async { + await _prefs.setBool('usePrereleasePatches', value); + } + + bool isUsingPrereleasePatches() { + return _prefs.getBool('usePrereleasePatches') ?? false; + } + Option? getPatchOption(String packageName, String patchName, String key) { final String? optionJson = _prefs.getString('patchOption-$packageName-$patchName-$key'); @@ -469,8 +477,9 @@ class ManagerAPI { defaultPatchesRepo, ); } else { - final release = - await _githubAPI.getLatestPatchesRelease(getPatchesRepo()); + final release = !isUsingPrereleasePatches() + ? await _githubAPI.getLatestRelease(getPatchesRepo()) + : await _githubAPI.getLatestReleaseWithPreReleases(getPatchesRepo()); if (release != null) { final DateTime timestamp = DateTime.parse(release['created_at'] as String); @@ -502,7 +511,9 @@ class ManagerAPI { defaultIntegrationsRepo, ); } else { - final release = await _githubAPI.getLatestRelease(getIntegrationsRepo()); + final release = !isUsingPrereleasePatches() + ? await _githubAPI.getLatestRelease(getIntegrationsRepo()) + : await _githubAPI.getLatestReleaseWithPreReleases(getIntegrationsRepo()); if (release != null) { return release['tag_name']; } else { @@ -518,8 +529,9 @@ class ManagerAPI { defaultPatchesRepo, ); } else { - final release = - await _githubAPI.getLatestPatchesRelease(getPatchesRepo()); + final release = !isUsingPrereleasePatches() + ? await _githubAPI.getLatestRelease(getPatchesRepo()) + : await _githubAPI.getLatestReleaseWithPreReleases(getPatchesRepo()); 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 3327c42b4b..b5c2b1a431 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -480,7 +480,13 @@ class HomeViewModel extends BaseViewModel { } Future?> getLatestPatchesRelease() { - return _githubAPI.getLatestPatchesRelease(_managerAPI.defaultPatchesRepo); + if (_managerAPI.isUsingAlternativeSources() && + _managerAPI.isUsingPrereleasePatches()) { + return _githubAPI + .getLatestReleaseWithPreReleases(_managerAPI.getPatchesRepo()); + } else { + return _githubAPI.getLatestRelease(_managerAPI.getPatchesRepo()); + } } Future getLatestPatchesReleaseTime() { diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 8dbfefc4ba..635cf5179f 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -198,6 +198,66 @@ class SettingsViewModel extends BaseViewModel { } } + bool isUsingPrereleasePatches() { + return _managerAPI.isUsingPrereleasePatches(); + } + + Future? showUsePrelereasePatchesDialog( + BuildContext context, + bool value, + ) { + if (value) { + return showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(t.warning), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + t.settingsView.usePrereleasePatchesDialogText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 16), + Text( + t.settingsView.usePrereleasePatchesDialogText2, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.error, + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + _managerAPI.usePrereleasePatches(true); + _toast.showBottom(t.settingsView.restartAppForChanges); + Navigator.of(context).pop(); + }, + child: Text(t.yesButton), + ), + FilledButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(t.noButton), + ), + ], + ), + ); + } else { + _managerAPI.usePrereleasePatches(false); + _toast.showBottom(t.settingsView.restartAppForChanges); + } + return null; + } + void deleteKeystore() { _managerAPI.deleteKeystore(); _toast.showBottom(t.settingsView.regeneratedKeystore); diff --git a/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart b/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart index 2876288f32..accce6121b 100644 --- a/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart +++ b/lib/ui/widgets/settingsView/settings_use_alternative_sources.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; +import 'package:revanced_manager/ui/widgets/settingsView/settings_use_prerelease_patches.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; class SUseAlternativeSources extends StatefulWidget { @@ -31,12 +32,16 @@ class _SUseAlternativeSourcesState extends State { subtitle: Text(t.settingsView.useAlternativeSourcesHint), value: _settingsViewModel.isUsingAlternativeSources(), onChanged: (value) { - _settingsViewModel.useAlternativeSources(value); - setState(() {}); + setState(() { + _settingsViewModel.useAlternativeSources(value); + }); }, ), if (_settingsViewModel.isUsingAlternativeSources()) - const SManageSourcesUI(), + ...[ + const SManageSourcesUI(), + const SUsePrereleasePatches(), + ], ], ); } diff --git a/lib/ui/widgets/settingsView/settings_use_prerelease_patches.dart b/lib/ui/widgets/settingsView/settings_use_prerelease_patches.dart new file mode 100644 index 0000000000..781082e134 --- /dev/null +++ b/lib/ui/widgets/settingsView/settings_use_prerelease_patches.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; +import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; +import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; + +class SUsePrereleasePatches extends StatefulWidget { + const SUsePrereleasePatches({super.key}); + + @override + State createState() => _SUsePrereleasePatchesState(); +} + +final _settingsViewModel = SettingsViewModel(); + +class _SUsePrereleasePatchesState extends State { + @override + Widget build(BuildContext context) { + return HapticSwitchListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), + title: Text( + t.settingsView.usePrereleasePatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + ), + ), + subtitle: Text(t.settingsView.usePrereleasePatchesHint), + value: _settingsViewModel.isUsingPrereleasePatches(), + onChanged: (value) async { + await _settingsViewModel.showUsePrelereasePatchesDialog(context, value); + setState(() {}); + }, + ); + } +} From 47c411bdbe306239c7060e942302eeb990ba997b Mon Sep 17 00:00:00 2001 From: kitadai31 <90122968+kitadai31@users.noreply.github.com> Date: Tue, 14 May 2024 14:31:27 +0900 Subject: [PATCH 2/6] fix fetching pre-release logic If there are multiple dev releases on the same day, they will be sorted by alphabetically. Therefore, releases[0] is not guaranteed to be the latest. vX.X.X-dev.10 will be older than vX.X.X-dev.9 so we have to iterate several releases and find the latest --- lib/services/github_api.dart | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index 10b961134b..7e1e735ebf 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -38,13 +38,25 @@ class GithubAPI { } Future?> getLatestReleaseWithPreReleases( - String repoName, - ) async { + String repoName, + ) async { try { - final response = await _dio.get( - '/repos/$repoName/releases?per_page=1', - ); - return response.data[0]; + final response = await _dio.get('/repos/$repoName/releases?per_page=10'); + final List releases = response.data; + + /* + * Loop through all releases (including pre-releases) and return the latest + */ + Map? latestRelease; + DateTime latestReleaseDate = DateTime.fromMillisecondsSinceEpoch(0); + for (final release in releases) { + final DateTime releaseDate = DateTime.parse(release['published_at']); + if (releaseDate.isAfter(latestReleaseDate)) { + latestReleaseDate = releaseDate; + latestRelease = release; + } + } + return latestRelease; } on Exception catch (e) { if (kDebugMode) { print(e); From 1b25454b2234be17daec4f1ab3f9651ecd67055d Mon Sep 17 00:00:00 2001 From: kitadai31 <90122968+kitadai31@users.noreply.github.com> Date: Sat, 20 Apr 2024 18:44:09 +0900 Subject: [PATCH 3/6] support ReVanced API --- lib/services/manager_api.dart | 35 +++++++---- lib/services/revanced_api.dart | 59 +++++++++++++++++++ lib/ui/views/home/home_viewmodel.dart | 3 +- .../settingsView/settings_data_section.dart | 2 + .../settings_use_alternative_sources.dart | 6 +- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 3d8392c549..9944684b39 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -29,6 +29,8 @@ class ManagerAPI { final RootAPI _rootAPI = RootAPI(); final String patcherRepo = 'revanced-patcher'; final String cliRepo = 'revanced-cli'; + final String patchesRepo = 'revanced-patches'; + final String integrationsRepo = 'revanced-integrations'; late SharedPreferences _prefs; List patches = []; List