From 40f27b3a09b54ea37728bfae6e6cc2026ecf2100 Mon Sep 17 00:00:00 2001 From: Alberto Ponces Date: Wed, 17 Aug 2022 18:44:27 +0100 Subject: [PATCH] feat: call Installer through Home View --- lib/models/patched_application.dart | 4 +- lib/services/patcher_api.dart | 120 +++++++++++------- .../app_selector/app_selector_viewmodel.dart | 3 +- lib/ui/views/home/home_view.dart | 2 + lib/ui/views/home/home_viewmodel.dart | 18 +++ .../views/installer/installer_viewmodel.dart | 11 +- .../patches_selector_view.dart | 33 ++--- .../patches_selector_viewmodel.dart | 16 +-- lib/ui/widgets/available_updates_card.dart | 5 +- lib/ui/widgets/installed_apps_card.dart | 5 +- 10 files changed, 139 insertions(+), 78 deletions(-) diff --git a/lib/models/patched_application.dart b/lib/models/patched_application.dart index cf5871f6..c87d0270 100644 --- a/lib/models/patched_application.dart +++ b/lib/models/patched_application.dart @@ -18,7 +18,7 @@ class PatchedApplication { final DateTime patchDate; final bool isRooted; final bool isFromStorage; - final List appliedPatches; + List appliedPatches; PatchedApplication({ required this.name, @@ -29,7 +29,7 @@ class PatchedApplication { required this.patchDate, required this.isRooted, required this.isFromStorage, - this.appliedPatches = const [], + required this.appliedPatches, }); factory PatchedApplication.fromJson(Map json) => diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index bf641616..7f560d76 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -24,8 +24,6 @@ class PatcherAPI { ); final GithubAPI githubAPI = GithubAPI(); final RootAPI rootAPI = RootAPI(); - final List _filteredPackages = []; - final Map> _filteredPatches = >{}; Directory? _tmpDir; Directory? _workDir; Directory? _cacheDir; @@ -77,7 +75,8 @@ class PatcherAPI { } Future> getFilteredInstalledApps() async { - if (_patchBundleFile != null && _filteredPackages.isEmpty) { + List filteredPackages = []; + if (_patchBundleFile != null) { try { List? patchesPackages = await patcherChannel .invokeListMethod('getCompatiblePackages'); @@ -87,7 +86,7 @@ class PatcherAPI { ApplicationWithIcon? app = await DeviceApps.getApp(package, true) as ApplicationWithIcon?; if (app != null) { - _filteredPackages.add(app); + filteredPackages.add(app); } } catch (e) { continue; @@ -95,58 +94,91 @@ class PatcherAPI { } } } on Exception { - _filteredPackages.clear(); return List.empty(); } } - return _filteredPackages; + return filteredPackages; } - Future?> getFilteredPatches( + Future> getFilteredPatches( PatchedApplication? selectedApp, ) async { + List filteredPatches = []; if (_patchBundleFile != null && selectedApp != null) { - if (_filteredPatches[selectedApp.packageName] == null || - _filteredPatches[selectedApp.packageName]!.isEmpty) { - _filteredPatches[selectedApp.packageName] = []; - try { - var patches = - await patcherChannel.invokeListMethod>( - 'getFilteredPatches', - { - 'targetPackage': selectedApp.packageName, - 'targetVersion': selectedApp.version, - 'ignoreVersion': true, - }, - ); - if (patches != null) { - for (var patch in patches) { - if (!_filteredPatches[selectedApp.packageName]! - .any((element) => element.name == patch['name'])) { - _filteredPatches[selectedApp.packageName]!.add( - Patch( - name: patch['name'], - simpleName: (patch['name'] as String) - .replaceAll('-', ' ') - .split('-') - .join(' ') - .toTitleCase(), - version: patch['version'] ?? '?.?.?', - description: patch['description'] ?? 'N/A', - ), - ); - } + try { + var patches = + await patcherChannel.invokeListMethod>( + 'getFilteredPatches', + { + 'targetPackage': selectedApp.packageName, + 'targetVersion': selectedApp.version, + 'ignoreVersion': true, + }, + ); + if (patches != null) { + for (var patch in patches) { + if (!filteredPatches + .any((element) => element.name == patch['name'])) { + filteredPatches.add( + Patch( + name: patch['name'], + simpleName: (patch['name'] as String) + .replaceAll('-', ' ') + .split('-') + .join(' ') + .toTitleCase(), + version: patch['version'] ?? '?.?.?', + description: patch['description'] ?? 'N/A', + ), + ); } } - } on Exception { - _filteredPatches[selectedApp.packageName]!.clear(); - return List.empty(); } + } on Exception { + return List.empty(); } - } else { - return List.empty(); } - return _filteredPatches[selectedApp.packageName]; + return filteredPatches; + } + + Future> getAppliedPatches( + PatchedApplication? selectedApp, + ) async { + List appliedPatches = []; + if (_patchBundleFile != null && selectedApp != null) { + try { + var patches = + await patcherChannel.invokeListMethod>( + 'getFilteredPatches', + { + 'targetPackage': selectedApp.packageName, + 'targetVersion': selectedApp.version, + 'ignoreVersion': true, + }, + ); + if (patches != null) { + for (var patch in patches) { + if (selectedApp.appliedPatches.contains(patch['name'])) { + appliedPatches.add( + Patch( + name: patch['name'], + simpleName: (patch['name'] as String) + .replaceAll('-', ' ') + .split('-') + .join(' ') + .toTitleCase(), + version: patch['version'] ?? '?.?.?', + description: patch['description'] ?? 'N/A', + ), + ); + } + } + } + } on Exception { + return List.empty(); + } + } + return appliedPatches; } Future downloadIntegrations() async { @@ -187,7 +219,7 @@ class PatcherAPI { 'patchedFilePath': _patchedFile!.path, 'outFilePath': _outFile!.path, 'integrationsPath': _integrations!.path, - 'selectedPatches': selectedPatches.map((e) => e.name).toList(), + 'selectedPatches': selectedPatches.map((p) => p.name).toList(), 'cacheDirPath': _cacheDir!.path, 'mergeIntegrations': mergeIntegrations, 'resourcePatching': resourcePatching, diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index 5bb78b1b..255a0b25 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -27,7 +27,6 @@ class AppSelectorViewModel extends BaseViewModel { } Future getApps() async { - await patcherAPI.loadPatches(); apps = await patcherAPI.getFilteredInstalledApps(); } @@ -42,6 +41,7 @@ class AppSelectorViewModel extends BaseViewModel { patchDate: DateTime.now(), isRooted: isRooted, isFromStorage: isFromStorage, + appliedPatches: [], ); locator().selectedApp = app; locator().selectedPatches.clear(); @@ -70,6 +70,7 @@ class AppSelectorViewModel extends BaseViewModel { patchDate: DateTime.now(), isRooted: isRooted, isFromStorage: isFromStorage, + appliedPatches: [], ); locator().selectedApp = app; locator().selectedPatches.clear(); diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index 6978fd00..63fe1270 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -17,6 +17,8 @@ class HomeView extends StatelessWidget { Widget build(BuildContext context) { return ViewModelBuilder.reactive( disposeViewModel: false, + fireOnModelReadyOnce: true, + onModelReady: (model) => model.initialize(), viewModelBuilder: () => locator(), builder: (context, model, child) => Scaffold( body: SafeArea( diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 07a58c36..4a41df6b 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -1,17 +1,28 @@ import 'dart:convert'; import 'package:injectable/injectable.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/app/app.router.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/github_api.dart'; import 'package:revanced_manager/services/manager_api.dart'; +import 'package:revanced_manager/services/patcher_api.dart'; +import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; +import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; @lazySingleton class HomeViewModel extends BaseViewModel { + final _navigationService = locator(); final GithubAPI githubAPI = GithubAPI(); + final PatcherAPI patcherAPI = locator(); bool showUpdatableApps = true; + Future initialize() async { + await patcherAPI.loadPatches(); + } + void toggleUpdatableApps(bool value) { showUpdatableApps = value; notifyListeners(); @@ -20,6 +31,13 @@ class HomeViewModel extends BaseViewModel { Future downloadPatches() => locator().downloadPatches(); Future downloadIntegrations() => locator().downloadIntegrations(); + void navigateToInstaller(PatchedApplication app) async { + locator().selectedApp = app; + locator().selectedPatches = + await patcherAPI.getAppliedPatches(app); + _navigationService.navigateTo(Routes.installerView); + } + Future> getPatchedApps(bool isUpdatable) async { List list = []; SharedPreferences prefs = await SharedPreferences.getInstance(); diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index b95df9e6..edcfe06c 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -109,6 +109,8 @@ class InstallerViewModel extends BaseViewModel { void installResult() async { PatchedApplication? selectedApp = locator().selectedApp; + List selectedPatches = + locator().selectedPatches; if (selectedApp != null) { updateLog(selectedApp.isRooted ? 'Installing patched file using root method' @@ -116,6 +118,8 @@ class InstallerViewModel extends BaseViewModel { isInstalled = await locator().installPatchedFile(selectedApp); if (isInstalled) { updateLog('Done'); + selectedApp.appliedPatches + .addAll(selectedPatches.map((p) => p.name).toList()); await saveApp(selectedApp); } else { updateLog('An error occurred! Aborting'); @@ -153,9 +157,8 @@ class InstallerViewModel extends BaseViewModel { SharedPreferences prefs = await SharedPreferences.getInstance(); List patchedApps = prefs.getStringList('patchedApps') ?? []; String app = json.encode(selectedApp.toJson()); - if (!patchedApps.contains(app)) { - patchedApps.add(app); - prefs.setStringList('patchedApps', patchedApps); - } + patchedApps.remove(app); + patchedApps.add(app); + prefs.setStringList('patchedApps', patchedApps); } } diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index 6cd100de..752fd873 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -22,6 +22,7 @@ class _PatchesSelectorViewState extends State { Widget build(BuildContext context) { return ViewModelBuilder.reactive( disposeViewModel: false, + fireOnModelReadyOnce: true, onModelReady: (model) => model.initialize(), viewModelBuilder: () => locator(), builder: (context, model, child) => Scaffold( @@ -29,7 +30,7 @@ class _PatchesSelectorViewState extends State { child: Padding( padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), - child: model.patches != null && model.patches!.isNotEmpty + child: model.patches.isNotEmpty ? Column( children: [ SearchBar( @@ -84,16 +85,16 @@ class _PatchesSelectorViewState extends State { patches.clear(); return Expanded( child: ListView.builder( - itemCount: model.patches!.length, + itemCount: model.patches.length, itemBuilder: (context, index) { - model.patches!.sort((a, b) => a.simpleName.compareTo(b.simpleName)); + model.patches.sort((a, b) => a.simpleName.compareTo(b.simpleName)); PatchItem item = PatchItem( - name: model.patches![index].name, - simpleName: model.patches![index].simpleName, - version: model.patches![index].version, - description: model.patches![index].description, + name: model.patches[index].name, + simpleName: model.patches[index].simpleName, + version: model.patches[index].version, + description: model.patches[index].description, isSelected: model.selectedPatches.any( - (element) => element.name == model.patches![index].name, + (element) => element.name == model.patches[index].name, ), ); patches.add(item); @@ -107,19 +108,19 @@ class _PatchesSelectorViewState extends State { patches.clear(); return Expanded( child: ListView.builder( - itemCount: model.patches!.length, + itemCount: model.patches.length, itemBuilder: (context, index) { - model.patches!.sort((a, b) => a.simpleName.compareTo(b.simpleName)); - if (model.patches![index].simpleName.toLowerCase().contains( + model.patches.sort((a, b) => a.simpleName.compareTo(b.simpleName)); + if (model.patches[index].simpleName.toLowerCase().contains( query.toLowerCase(), )) { PatchItem item = PatchItem( - name: model.patches![index].name, - simpleName: model.patches![index].simpleName, - version: model.patches![index].version, - description: model.patches![index].description, + name: model.patches[index].name, + simpleName: model.patches[index].simpleName, + version: model.patches[index].version, + description: model.patches[index].description, isSelected: model.selectedPatches.any( - (element) => element.name == model.patches![index].name, + (element) => element.name == model.patches[index].name, ), ); patches.add(item); diff --git a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart index 23143dfa..22cc78d4 100644 --- a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart +++ b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart @@ -9,7 +9,7 @@ import 'package:stacked/stacked.dart'; class PatchesSelectorViewModel extends BaseViewModel { final PatcherAPI patcherAPI = locator(); - List? patches = []; + List patches = []; List selectedPatches = []; Future initialize() async { @@ -24,14 +24,12 @@ class PatchesSelectorViewModel extends BaseViewModel { void selectPatches(List patchItems) { selectedPatches.clear(); - if (patches != null) { - for (PatchItem item in patchItems) { - if (item.isSelected) { - Patch patch = - patches!.firstWhere((element) => element.name == item.name); - if (!selectedPatches.contains(patch)) { - selectedPatches.add(patch); - } + for (PatchItem item in patchItems) { + if (item.isSelected) { + Patch patch = + patches.firstWhere((element) => element.name == item.name); + if (!selectedPatches.contains(patch)) { + selectedPatches.add(patch); } } } diff --git a/lib/ui/widgets/available_updates_card.dart b/lib/ui/widgets/available_updates_card.dart index 662879b7..bb3f5ec2 100644 --- a/lib/ui/widgets/available_updates_card.dart +++ b/lib/ui/widgets/available_updates_card.dart @@ -39,7 +39,10 @@ class AvailableUpdatesCard extends StatelessWidget { patchDate: snapshot.data![index].patchDate, changelog: snapshot2.data!, isUpdatableApp: true, - onPressed: () => {}, + onPressed: () => + locator().navigateToInstaller( + snapshot.data![index], + ), ), ), ) diff --git a/lib/ui/widgets/installed_apps_card.dart b/lib/ui/widgets/installed_apps_card.dart index 4d985663..5593a3f5 100644 --- a/lib/ui/widgets/installed_apps_card.dart +++ b/lib/ui/widgets/installed_apps_card.dart @@ -39,7 +39,10 @@ class InstalledAppsCard extends StatelessWidget { patchDate: snapshot.data![index].patchDate, changelog: snapshot2.data!, isUpdatableApp: false, - onPressed: () => {}, + onPressed: () => + locator().navigateToInstaller( + snapshot.data![index], + ), ), ), )