fix: code refactoring (#5)

This commit is contained in:
Alberto Ponces
2022-08-18 15:33:33 +01:00
committed by GitHub
parent 6153e1f9e8
commit 389eae1447
31 changed files with 318 additions and 361 deletions

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/theme.dart';
import 'package:revanced_manager/ui/widgets/installed_app_item.dart';
import 'package:revanced_manager/ui/widgets/search_bar.dart';
@ -15,14 +14,13 @@ class AppSelectorView extends StatefulWidget {
}
class _AppSelectorViewState extends State<AppSelectorView> {
String query = '';
String _query = '';
@override
Widget build(BuildContext context) {
return ViewModelBuilder<AppSelectorViewModel>.reactive(
disposeViewModel: false,
onModelReady: (model) => model.initialize(),
viewModelBuilder: () => locator<AppSelectorViewModel>(),
viewModelBuilder: () => AppSelectorViewModel(),
builder: (context, model, child) => Scaffold(
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
@ -51,17 +49,17 @@ class _AppSelectorViewState extends State<AppSelectorView> {
hintTextColor: Theme.of(context).colorScheme.tertiary,
onQueryChanged: (searchQuery) {
setState(() {
query = searchQuery;
_query = searchQuery;
});
},
),
const SizedBox(height: 12),
query.isEmpty || query.length < 2
_query.isEmpty || _query.length < 2
? _getAllResults(model)
: _getFilteredResults(model)
],
)
: query.isEmpty || query.length < 2
: _query.isEmpty || _query.length < 2
? Center(
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
@ -105,7 +103,7 @@ class _AppSelectorViewState extends State<AppSelectorView> {
itemBuilder: (context, index) {
model.apps.sort((a, b) => a.appName.compareTo(b.appName));
if (model.apps[index].appName.toLowerCase().contains(
query.toLowerCase(),
_query.toLowerCase(),
)) {
return InkWell(
onTap: () {

View File

@ -8,30 +8,22 @@ import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/models/patched_application.dart';
import 'package:revanced_manager/services/patcher_api.dart';
import 'package:revanced_manager/ui/views/patcher/patcher_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';
class AppSelectorViewModel extends BaseViewModel {
final PatcherAPI patcherAPI = locator<PatcherAPI>();
bool isRooted = false;
bool isFromStorage = false;
List<ApplicationWithIcon> apps = [];
PatchedApplication? selectedApp;
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final List<ApplicationWithIcon> apps = [];
bool _isRooted = false;
Future<void> initialize() async {
await getApps();
apps.addAll(await _patcherAPI.getFilteredInstalledApps());
SharedPreferences prefs = await SharedPreferences.getInstance();
isRooted = prefs.getBool('isRooted') ?? false;
_isRooted = prefs.getBool('isRooted') ?? false;
notifyListeners();
}
Future<void> getApps() async {
apps = await patcherAPI.getFilteredInstalledApps();
}
void selectApp(ApplicationWithIcon application) async {
isFromStorage = false;
PatchedApplication app = PatchedApplication(
name: application.appName,
packageName: application.packageName,
@ -39,18 +31,16 @@ class AppSelectorViewModel extends BaseViewModel {
apkFilePath: application.apkFilePath,
icon: application.icon,
patchDate: DateTime.now(),
isRooted: isRooted,
isFromStorage: isFromStorage,
isRooted: _isRooted,
isFromStorage: false,
appliedPatches: [],
);
locator<AppSelectorViewModel>().selectedApp = app;
locator<PatchesSelectorViewModel>().selectedPatches.clear();
locator<PatchesSelectorViewModel>().notifyListeners();
locator<PatcherViewModel>().selectedApp = app;
locator<PatcherViewModel>().selectedPatches.clear();
locator<PatcherViewModel>().notifyListeners();
}
Future<void> selectAppFromStorage(BuildContext context) async {
isFromStorage = true;
try {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
@ -69,13 +59,12 @@ class AppSelectorViewModel extends BaseViewModel {
apkFilePath: result.files.single.path!,
icon: application.icon,
patchDate: DateTime.now(),
isRooted: isRooted,
isFromStorage: isFromStorage,
isRooted: _isRooted,
isFromStorage: true,
appliedPatches: [],
);
locator<AppSelectorViewModel>().selectedApp = app;
locator<PatchesSelectorViewModel>().selectedPatches.clear();
locator<PatchesSelectorViewModel>().notifyListeners();
locator<PatcherViewModel>().selectedApp = app;
locator<PatcherViewModel>().selectedPatches.clear();
locator<PatcherViewModel>().notifyListeners();
}
}

View File

@ -9,7 +9,6 @@ class ContributorsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ViewModelBuilder<ContributorsViewModel>.reactive(
disposeViewModel: false,
viewModelBuilder: () => ContributorsViewModel(),
onModelReady: (model) => model.getContributors(),
builder: (context, model, child) => Scaffold(

View File

@ -1,27 +1,36 @@
import 'package:github/github.dart';
import 'package:revanced_manager/constants.dart';
import 'package:revanced_manager/services/github_api.dart';
import 'package:stacked/stacked.dart';
class ContributorsViewModel extends BaseViewModel {
final GithubAPI githubAPI = GithubAPI();
final GithubAPI _githubAPI = GithubAPI();
List<Contributor> patchesContributors = [];
List<Contributor> integrationsContributors = [];
List<Contributor> patcherContributors = [];
List<Contributor> cliContributors = [];
List<Contributor> managerContributors = [];
Future<List<Contributor>> getContributors() async {
patchesContributors =
await githubAPI.getContributors('revanced', 'revanced-patches');
integrationsContributors =
await githubAPI.getContributors('revanced', 'revanced-integrations');
patcherContributors =
await githubAPI.getContributors('revanced', 'revanced-patcher');
cliContributors =
await githubAPI.getContributors('revanced', 'revanced-cli');
managerContributors =
await githubAPI.getContributors('revanced', 'revanced-manager');
return [];
Future<void> getContributors() async {
patchesContributors = await _githubAPI.getContributors(
ghOrg,
patchesRepo,
);
integrationsContributors = await _githubAPI.getContributors(
ghOrg,
integrationsRepo,
);
patcherContributors = await _githubAPI.getContributors(
ghOrg,
patcherRepo,
);
cliContributors = await _githubAPI.getContributors(
ghOrg,
cliRepo,
);
managerContributors = await _githubAPI.getContributors(
ghOrg,
managerRepo,
);
}
}

View File

@ -55,6 +55,7 @@ class HomeView extends StatelessWidget {
),
const SizedBox(height: 10),
LatestCommitCard(
onPressed: () => model.updateManager(context),
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 23),
@ -77,7 +78,7 @@ class HomeView extends StatelessWidget {
label: "homeView.updatesAvailable",
isSelected: model.showUpdatableApps,
onSelected: (value) {
model.toggleUpdatableApps(value);
model.toggleUpdatableApps(true);
},
),
const SizedBox(width: 10),

View File

@ -1,26 +1,41 @@
import 'dart:convert';
import 'dart:io';
import 'package:app_installer/app_installer.dart';
import 'package:device_apps/device_apps.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
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/constants.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:revanced_manager/ui/views/patcher/patcher_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<NavigationService>();
final GithubAPI githubAPI = GithubAPI();
final PatcherAPI patcherAPI = locator<PatcherAPI>();
final NavigationService _navigationService = locator<NavigationService>();
final ManagerAPI _managerAPI = ManagerAPI();
final GithubAPI _githubAPI = GithubAPI();
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
bool showUpdatableApps = true;
Future<void> initialize() async {
await patcherAPI.loadPatches();
await _patcherAPI.loadPatches();
await flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('ic_notification'),
),
onSelectNotification: (p) => DeviceApps.openApp('app.revanced.manager'),
);
}
void toggleUpdatableApps(bool value) {
@ -28,13 +43,10 @@ class HomeViewModel extends BaseViewModel {
notifyListeners();
}
Future downloadPatches() => locator<ManagerAPI>().downloadPatches();
Future downloadIntegrations() => locator<ManagerAPI>().downloadIntegrations();
void navigateToInstaller(PatchedApplication app) async {
locator<AppSelectorViewModel>().selectedApp = app;
locator<PatchesSelectorViewModel>().selectedPatches =
await patcherAPI.getAppliedPatches(app);
locator<PatcherViewModel>().selectedApp = app;
locator<PatcherViewModel>().selectedPatches =
await _patcherAPI.getAppliedPatches(app);
_navigationService.navigateTo(Routes.installerView);
}
@ -44,15 +56,37 @@ class HomeViewModel extends BaseViewModel {
List<String> patchedApps = prefs.getStringList('patchedApps') ?? [];
for (String str in patchedApps) {
PatchedApplication app = PatchedApplication.fromJson(json.decode(str));
bool hasUpdates = await githubAPI.hasUpdates(
app,
'revanced',
'revanced-patches',
);
bool hasUpdates = await _githubAPI.hasUpdates(app, ghOrg, patchesRepo);
if (hasUpdates == isUpdatable) {
list.add(app);
}
}
return list;
}
void updateManager(BuildContext context) async {
File? managerApk = await _managerAPI.downloadManager();
if (managerApk != null) {
flutterLocalNotificationsPlugin.show(
0,
// ignore: use_build_context_synchronously
FlutterI18n.translate(
context,
'homeView.notificationTitle',
),
// ignore: use_build_context_synchronously
FlutterI18n.translate(
context,
'homeView.notificationText',
),
const NotificationDetails(
android: AndroidNotificationDetails(
'revanced_manager_channel',
'ReVanced Manager Channel',
),
),
);
AppInstaller.installApk(managerApk.path);
}
}
}

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart';
import 'package:stacked/stacked.dart';
@ -15,9 +14,8 @@ class InstallerView extends StatelessWidget {
(_) => _controller.jumpTo(_controller.position.maxScrollExtent),
);
return ViewModelBuilder<InstallerViewModel>.reactive(
disposeViewModel: false,
onModelReady: (model) => model.initialize(),
viewModelBuilder: () => locator<InstallerViewModel>(),
onModelReady: (model) => model.initialize(context),
viewModelBuilder: () => InstallerViewModel(),
builder: (context, model, child) => WillPopScope(
child: Scaffold(
floatingActionButton: Visibility(

View File

@ -1,30 +1,43 @@
import 'dart:convert';
import 'package:device_apps/device_apps.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_background/flutter_background.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/models/patched_application.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/patcher/patcher_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';
class InstallerViewModel extends BaseViewModel {
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final PatchedApplication? _app = locator<PatcherViewModel>().selectedApp;
final List<Patch> _patches = locator<PatcherViewModel>().selectedPatches;
static const _installerChannel = MethodChannel(
'app.revanced.manager/installer',
);
double? progress = 0.0;
String logs = '';
bool isPatching = false;
bool isInstalled = false;
Future<void> initialize() async {
Future<void> initialize(BuildContext context) async {
try {
await FlutterBackground.initialize(
androidConfig: const FlutterBackgroundAndroidConfig(
notificationTitle: 'Patching',
notificationText: 'ReVanced Manager is patching',
androidConfig: FlutterBackgroundAndroidConfig(
notificationTitle: FlutterI18n.translate(
context,
'installerView.notificationTitle',
),
notificationText: FlutterI18n.translate(
context,
'installerView.notificationText',
),
notificationImportance: AndroidNotificationImportance.Default,
notificationIcon: AndroidResource(
notificationIcon: const AndroidResource(
name: 'ic_notification',
defType: 'drawable',
),
@ -32,11 +45,28 @@ class InstallerViewModel extends BaseViewModel {
);
await FlutterBackground.enableBackgroundExecution();
} finally {
await locator<PatcherAPI>().handlePlatformChannelMethods();
await handlePlatformChannelMethods();
await runPatcher();
}
}
Future<dynamic> handlePlatformChannelMethods() async {
_installerChannel.setMethodCallHandler((call) async {
switch (call.method) {
case 'updateProgress':
if (call.arguments != null) {
updateProgress(call.arguments);
}
break;
case 'updateLog':
if (call.arguments != null) {
updateLog(call.arguments);
}
break;
}
});
}
void updateProgress(double value) {
progress = value;
isInstalled = false;
@ -59,37 +89,32 @@ class InstallerViewModel extends BaseViewModel {
Future<void> runPatcher() async {
updateProgress(0.0);
PatchedApplication? selectedApp =
locator<AppSelectorViewModel>().selectedApp;
List<Patch> selectedPatches =
locator<PatchesSelectorViewModel>().selectedPatches;
if (selectedApp != null && selectedPatches.isNotEmpty) {
String apkFilePath = selectedApp.apkFilePath;
if (_app != null && _patches.isNotEmpty) {
String apkFilePath = _app!.apkFilePath;
try {
updateLog('Initializing installer');
if (selectedApp.isRooted && !selectedApp.isFromStorage) {
if (_app!.isRooted && !_app!.isFromStorage) {
updateLog('Checking if an old patched version exists');
bool oldExists =
await locator<PatcherAPI>().checkOldPatch(selectedApp);
bool oldExists = await _patcherAPI.checkOldPatch(_app!);
if (oldExists) {
updateLog('Deleting old patched version');
await locator<PatcherAPI>().deleteOldPatch(selectedApp);
await _patcherAPI.deleteOldPatch(_app!);
}
}
updateLog('Creating working directory');
bool mergeIntegrations = false;
bool resourcePatching = false;
if (selectedApp.packageName == 'com.google.android.youtube') {
if (_app!.packageName == 'com.google.android.youtube') {
mergeIntegrations = true;
resourcePatching = true;
} else if (selectedApp.packageName ==
} else if (_app!.packageName ==
'com.google.android.apps.youtube.music') {
resourcePatching = true;
}
await locator<PatcherAPI>().initPatcher(mergeIntegrations);
await locator<PatcherAPI>().runPatcher(
await _patcherAPI.initPatcher(mergeIntegrations);
await _patcherAPI.runPatcher(
apkFilePath,
selectedPatches,
_patches,
mergeIntegrations,
resourcePatching,
);
@ -107,21 +132,16 @@ class InstallerViewModel extends BaseViewModel {
}
void installResult() async {
PatchedApplication? selectedApp =
locator<AppSelectorViewModel>().selectedApp;
List<Patch> selectedPatches =
locator<PatchesSelectorViewModel>().selectedPatches;
if (selectedApp != null) {
updateLog(selectedApp.isRooted
if (_app != null) {
updateLog(_app!.isRooted
? 'Installing patched file using root method'
: 'Installing patched file using nonroot method');
isInstalled = await locator<PatcherAPI>().installPatchedFile(selectedApp);
isInstalled = await _patcherAPI.installPatchedFile(_app!);
if (isInstalled) {
updateLog('Done');
selectedApp.patchDate = DateTime.now();
selectedApp.appliedPatches
.addAll(selectedPatches.map((p) => p.name).toList());
await saveApp(selectedApp);
_app!.patchDate = DateTime.now();
_app!.appliedPatches.addAll(_patches.map((p) => p.name).toList());
await saveApp();
} else {
updateLog('An error occurred! Aborting');
}
@ -129,39 +149,33 @@ class InstallerViewModel extends BaseViewModel {
}
void shareResult() {
PatchedApplication? selectedApp =
locator<AppSelectorViewModel>().selectedApp;
if (selectedApp != null) {
locator<PatcherAPI>().sharePatchedFile(
selectedApp.name,
selectedApp.version,
);
if (_app != null) {
_patcherAPI.sharePatchedFile(_app!.name, _app!.version);
}
}
Future<void> cleanWorkplace() async {
locator<PatcherAPI>().cleanPatcher();
locator<AppSelectorViewModel>().selectedApp = null;
locator<PatchesSelectorViewModel>().selectedPatches.clear();
locator<PatchesSelectorViewModel>().notifyListeners();
_patcherAPI.cleanPatcher();
locator<PatcherViewModel>().selectedApp = null;
locator<PatcherViewModel>().selectedPatches.clear();
locator<PatcherViewModel>().notifyListeners();
}
void openApp() {
PatchedApplication? selectedApp =
locator<AppSelectorViewModel>().selectedApp;
if (selectedApp != null) {
DeviceApps.openApp(selectedApp.packageName);
if (_app != null) {
DeviceApps.openApp(_app!.packageName);
}
}
Future<void> saveApp(PatchedApplication selectedApp) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> patchedApps = prefs.getStringList('patchedApps') ?? [];
String app = json.encode(selectedApp.toJson());
patchedApps.removeWhere(
(a) => json.decode(a)['packageName'] == selectedApp.packageName);
patchedApps.add(app);
prefs.setStringList('patchedApps', patchedApps);
Future<void> saveApp() async {
if (_app != null) {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> patchedApps = prefs.getStringList('patchedApps') ?? [];
String appStr = json.encode(_app!.toJson());
patchedApps.removeWhere(
(a) => json.decode(a)['packageName'] == _app!.packageName);
patchedApps.add(appStr);
prefs.setStringList('patchedApps', patchedApps);
}
}
}

View File

@ -1,12 +1,17 @@
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/ui/views/app_selector/app_selector_viewmodel.dart';
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/models/patched_application.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
@lazySingleton
class PatcherViewModel extends BaseViewModel {
final _navigationService = locator<NavigationService>();
PatchedApplication? selectedApp;
List<Patch> selectedPatches = [];
final NavigationService _navigationService = locator<NavigationService>();
void navigateToAppSelector() {
_navigationService.navigateTo(Routes.appSelectorView);
@ -21,10 +26,10 @@ class PatcherViewModel extends BaseViewModel {
}
bool showFabButton() {
return locator<PatchesSelectorViewModel>().selectedPatches.isNotEmpty;
return selectedPatches.isNotEmpty;
}
bool dimPatchesCard() {
return locator<AppSelectorViewModel>().selectedApp == null;
return selectedApp == null;
}
}

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/theme.dart';
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/patch_item.dart';
@ -15,16 +14,14 @@ class PatchesSelectorView extends StatefulWidget {
}
class _PatchesSelectorViewState extends State<PatchesSelectorView> {
final List<PatchItem> patches = [];
final List<PatchItem> _items = [];
String query = '';
@override
Widget build(BuildContext context) {
return ViewModelBuilder<PatchesSelectorViewModel>.reactive(
disposeViewModel: false,
fireOnModelReadyOnce: true,
onModelReady: (model) => model.initialize(),
viewModelBuilder: () => locator<PatchesSelectorViewModel>(),
viewModelBuilder: () => PatchesSelectorViewModel(),
builder: (context, model, child) => Scaffold(
body: SafeArea(
child: Padding(
@ -62,7 +59,10 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
onPressed: () => Navigator.of(context).pop(),
onPressed: () {
model.selectPatches();
Navigator.of(context).pop();
},
child: I18nText('patchesSelectorView.fabButton'),
),
],
@ -79,7 +79,7 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
}
Widget _getAllResults(PatchesSelectorViewModel model) {
patches.clear();
_items.clear();
return Expanded(
child: ListView.builder(
itemCount: model.patches.length,
@ -93,8 +93,10 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
isSelected: model.selectedPatches.any(
(element) => element.name == model.patches[index].name,
),
onChanged: (value) =>
model.selectPatch(model.patches[index].name, value),
);
patches.add(item);
_items.add(item);
return item;
},
),
@ -102,7 +104,7 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
}
Widget _getFilteredResults(PatchesSelectorViewModel model) {
patches.clear();
_items.clear();
return Expanded(
child: ListView.builder(
itemCount: model.patches.length,
@ -119,8 +121,10 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
isSelected: model.selectedPatches.any(
(element) => element.name == model.patches[index].name,
),
onChanged: (value) =>
model.selectPatch(model.patches[index].name, value),
);
patches.add(item);
_items.add(item);
return item;
} else {
return const SizedBox();

View File

@ -1,38 +1,34 @@
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/models/patched_application.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/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/patch_item.dart';
import 'package:stacked/stacked.dart';
class PatchesSelectorViewModel extends BaseViewModel {
final PatcherAPI patcherAPI = locator<PatcherAPI>();
List<Patch> patches = [];
List<Patch> selectedPatches = [];
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final List<Patch> patches = [];
final List<Patch> selectedPatches =
locator<PatcherViewModel>().selectedPatches;
Future<void> initialize() async {
await getPatches();
patches.addAll(await _patcherAPI.getFilteredPatches(
locator<PatcherViewModel>().selectedApp,
));
notifyListeners();
}
Future<void> getPatches() async {
PatchedApplication? app = locator<AppSelectorViewModel>().selectedApp;
patches = await patcherAPI.getFilteredPatches(app);
void selectPatch(String name, bool isSelected) {
Patch patch = patches.firstWhere((p) => p.name == name);
if (isSelected && !selectedPatches.contains(patch)) {
selectedPatches.add(patch);
} else {
selectedPatches.remove(patch);
}
notifyListeners();
}
void selectPatch(PatchItem item) {
Patch patch = locator<PatchesSelectorViewModel>()
.patches
.firstWhere((p) => p.name == item.name);
if (item.isSelected &&
!locator<PatchesSelectorViewModel>().selectedPatches.contains(patch)) {
locator<PatchesSelectorViewModel>().selectedPatches.add(patch);
} else {
locator<PatchesSelectorViewModel>().selectedPatches.remove(patch);
}
locator<PatchesSelectorViewModel>().notifyListeners();
void selectPatches() {
locator<PatcherViewModel>().selectedPatches = selectedPatches;
locator<PatcherViewModel>().notifyListeners();
}
}

View File

@ -11,7 +11,6 @@ class RootCheckerView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ViewModelBuilder<RootCheckerViewModel>.reactive(
disposeViewModel: false,
viewModelBuilder: () => RootCheckerViewModel(),
builder: (context, model, child) => Scaffold(
floatingActionButton: Column(

View File

@ -6,12 +6,13 @@ import 'package:root/root.dart';
import 'package:stacked_services/stacked_services.dart';
class RootCheckerViewModel extends BaseViewModel {
final _navigationService = locator<NavigationService>();
bool? isRooted = false;
final NavigationService _navigationService = locator<NavigationService>();
bool isRooted = false;
Future<void> checkRoot() async {
isRooted = await Root.isRooted();
if (isRooted == true) {
bool? res = await Root.isRooted();
isRooted = res != null && res == true;
if (isRooted) {
navigateToHome();
}
notifyListeners();
@ -19,7 +20,7 @@ class RootCheckerViewModel extends BaseViewModel {
Future<void> navigateToHome() async {
final prefs = await SharedPreferences.getInstance();
prefs.setBool('isRooted', isRooted!);
prefs.setBool('isRooted', isRooted);
_navigationService.navigateTo(Routes.navigation);
notifyListeners();
}

View File

@ -4,7 +4,7 @@ import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
class SettingsViewModel extends BaseViewModel {
final _navigationService = locator<NavigationService>();
final NavigationService _navigationService = locator<NavigationService>();
void setLanguage(String language) {
notifyListeners();