From cd1610d84710c23b5bf3334f9af7c3389573b066 Mon Sep 17 00:00:00 2001 From: Alberto Ponces Date: Tue, 16 Aug 2022 12:12:10 +0100 Subject: [PATCH] Revert "fix: save patched and installed apps on prefs, improve installer log, improve dashboard with real data (wip)" This reverts commit ce09a5264a69f18ffa9ecc391effe9ebef9d7af9. --- .github/workflows/release-build.yml | 2 - .gitignore | 2 - .vscode/tasks.json | 8 +- .../app/revanced/manager/MainActivity.kt | 35 +-- assets/images/reddit.png | Bin 0 -> 22247 bytes assets/images/revanced.svg | 6 + lib/app/app.dart | 2 - lib/app/app.locator.dart | 39 +++ lib/app/app.router.dart | 231 ++++++++++++++++++ lib/models/patched_application.dart | 28 +-- .../app_selector/app_selector_viewmodel.dart | 36 ++- lib/ui/views/home/home_view.dart | 4 +- lib/ui/views/home/home_viewmodel.dart | 14 -- lib/ui/views/installer/installer_view.dart | 6 +- .../views/installer/installer_viewmodel.dart | 52 ++-- lib/ui/widgets/application_item.dart | 26 +- lib/ui/widgets/available_updates_card.dart | 27 +- lib/ui/widgets/installed_apps_card.dart | 21 +- pubspec.yaml | 6 +- 19 files changed, 365 insertions(+), 180 deletions(-) create mode 100644 assets/images/reddit.png create mode 100644 assets/images/revanced.svg create mode 100644 lib/app/app.locator.dart create mode 100644 lib/app/app.router.dart diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 261a84bb..201a79ff 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -19,8 +19,6 @@ jobs: channel: 'stable' - name: Set up Flutter run: flutter pub get - - name: Generate files with Builder - run: flutter packages pub run build_runner build --delete-conflicting-outputs - name: Build with Flutter env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index a78395b8..ab6de429 100644 --- a/.gitignore +++ b/.gitignore @@ -42,8 +42,6 @@ version # Flutter/Dart/Pub related **/doc/api/ **/*.g.dart -**/*.locator.dart -**/*.router.dart .dart_tool/ .flutter-plugins .flutter-plugins-dependencies diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 0fa4713f..490ed99c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,7 @@ "version": "2.0.0", "tasks": [ { - "label": "Generate (Builder)", + "label": "Build (Serializer)", "type": "shell", "command": "flutter packages pub run build_runner build --delete-conflicting-outputs", "problemMatcher": [] @@ -30,7 +30,7 @@ "problemMatcher": [] }, { - "label": "Clean (Builder)", + "label": "Clean (Serializer)", "type": "shell", "command": "flutter packages pub run build_runner clean", "problemMatcher": [] @@ -39,7 +39,7 @@ "label": "Build all (Android)", "dependsOrder": "sequence", "dependsOn": [ - "Generate (Builder)", + "Build (Serializer)", "Build (Android)" ], "problemMatcher": [] @@ -49,7 +49,7 @@ "dependsOrder": "sequence", "dependsOn": [ "Clean (Flutter)", - "Clean (Builder)" + "Clean (Serializer)" ], "problemMatcher": [] }, diff --git a/android/app/src/main/kotlin/app/revanced/manager/MainActivity.kt b/android/app/src/main/kotlin/app/revanced/manager/MainActivity.kt index ba725783..971836df 100644 --- a/android/app/src/main/kotlin/app/revanced/manager/MainActivity.kt +++ b/android/app/src/main/kotlin/app/revanced/manager/MainActivity.kt @@ -179,41 +179,10 @@ class MainActivity : FlutterActivity() { return true } - fun createPatcher( - inputFilePath: String, - cacheDirPath: String, - resourcePatching: Boolean - ): Boolean { + fun createPatcher(inputFilePath: String, cacheDirPath: String, resourcePatching: Boolean): Boolean { val inputFile = File(inputFilePath) val aaptPath = Aapt.binary(applicationContext).absolutePath - patcher = - Patcher( - PatcherOptions( - inputFile, - cacheDirPath, - resourcePatching, - aaptPath, - cacheDirPath, - logger = - object : app.revanced.patcher.logging.Logger { - override fun error(msg: String) { - methodChannel.invokeMethod("updateInstallerLog", msg) - } - - override fun warn(msg: String) { - methodChannel.invokeMethod("updateInstallerLog", msg) - } - - override fun info(msg: String) { - methodChannel.invokeMethod("updateInstallerLog", msg) - } - - override fun trace(msg: String) { - methodChannel.invokeMethod("updateInstallerLog", msg) - } - } - ) - ) + patcher = Patcher(PatcherOptions(inputFile, cacheDirPath, resourcePatching, aaptPath, cacheDirPath)) return true } diff --git a/assets/images/reddit.png b/assets/images/reddit.png new file mode 100644 index 0000000000000000000000000000000000000000..941a12e6c3a588bee3fe6e097300b1a4018249a4 GIT binary patch literal 22247 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 E031{A9RL6T literal 0 HcmV?d00001 diff --git a/assets/images/revanced.svg b/assets/images/revanced.svg new file mode 100644 index 00000000..7318abbd --- /dev/null +++ b/assets/images/revanced.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/lib/app/app.dart b/lib/app/app.dart index 8765ae4f..6d7ab8ec 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -5,7 +5,6 @@ import 'package:revanced_manager/services/root_api.dart'; import 'package:revanced_manager/ui/views/app_selector/app_selector_view.dart'; import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; import 'package:revanced_manager/ui/views/contributors/contributors_view.dart'; -import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/views/installer/installer_view.dart'; import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; @@ -32,7 +31,6 @@ import 'package:stacked_themes/stacked_themes.dart'; LazySingleton(classType: PatcherAPI), LazySingleton(classType: ManagerAPI), LazySingleton(classType: RootAPI), - LazySingleton(classType: HomeViewModel), LazySingleton(classType: PatcherViewModel), LazySingleton(classType: AppSelectorViewModel), LazySingleton(classType: PatchesSelectorViewModel), diff --git a/lib/app/app.locator.dart b/lib/app/app.locator.dart new file mode 100644 index 00000000..6476d9a5 --- /dev/null +++ b/lib/app/app.locator.dart @@ -0,0 +1,39 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// StackedLocatorGenerator +// ************************************************************************** + +// ignore_for_file: public_member_api_docs, depend_on_referenced_packages + +import 'package:stacked_core/stacked_core.dart'; +import 'package:stacked_services/stacked_services.dart'; +import 'package:stacked_themes/stacked_themes.dart'; + +import '../services/manager_api.dart'; +import '../services/patcher_api.dart'; +import '../services/root_api.dart'; +import '../ui/views/app_selector/app_selector_viewmodel.dart'; +import '../ui/views/installer/installer_viewmodel.dart'; +import '../ui/views/patcher/patcher_viewmodel.dart'; +import '../ui/views/patches_selector/patches_selector_viewmodel.dart'; + +final locator = StackedLocator.instance; + +Future setupLocator( + {String? environment, EnvironmentFilter? environmentFilter}) async { +// Register environments + locator.registerEnvironment( + environment: environment, environmentFilter: environmentFilter); + +// Register dependencies + locator.registerLazySingleton(() => NavigationService()); + locator.registerLazySingleton(() => PatcherAPI()); + locator.registerLazySingleton(() => ManagerAPI()); + locator.registerLazySingleton(() => RootAPI()); + locator.registerLazySingleton(() => PatcherViewModel()); + locator.registerLazySingleton(() => AppSelectorViewModel()); + locator.registerLazySingleton(() => PatchesSelectorViewModel()); + locator.registerLazySingleton(() => InstallerViewModel()); + locator.registerLazySingleton(() => ThemeService.getInstance()); +} diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart new file mode 100644 index 00000000..62e381df --- /dev/null +++ b/lib/app/app.router.dart @@ -0,0 +1,231 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// StackedRouterGenerator +// ************************************************************************** + +// ignore_for_file: public_member_api_docs, unused_import, non_constant_identifier_names + +import 'package:flutter/material.dart'; +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; + +import '../main.dart'; +import '../ui/views/app_selector/app_selector_view.dart'; +import '../ui/views/contributors/contributors_view.dart'; +import '../ui/views/installer/installer_view.dart'; +import '../ui/views/patches_selector/patches_selector_view.dart'; +import '../ui/views/root_checker/root_checker_view.dart'; +import '../ui/views/settings/settings_view.dart'; + +class Routes { + static const String navigation = '/Navigation'; + static const String appSelectorView = '/app-selector-view'; + static const String patchesSelectorView = '/patches-selector-view'; + static const String installerView = '/installer-view'; + static const String settingsView = '/settings-view'; + static const String contributorsView = '/contributors-view'; + static const String rootCheckerView = '/root-checker-view'; + static const all = { + navigation, + appSelectorView, + patchesSelectorView, + installerView, + settingsView, + contributorsView, + rootCheckerView, + }; +} + +class StackedRouter extends RouterBase { + @override + List get routes => _routes; + final _routes = [ + RouteDef(Routes.navigation, page: Navigation), + RouteDef(Routes.appSelectorView, page: AppSelectorView), + RouteDef(Routes.patchesSelectorView, page: PatchesSelectorView), + RouteDef(Routes.installerView, page: InstallerView), + RouteDef(Routes.settingsView, page: SettingsView), + RouteDef(Routes.contributorsView, page: ContributorsView), + RouteDef(Routes.rootCheckerView, page: RootCheckerView), + ]; + @override + Map get pagesMap => _pagesMap; + final _pagesMap = { + Navigation: (data) { + return MaterialPageRoute( + builder: (context) => const Navigation(), + settings: data, + ); + }, + AppSelectorView: (data) { + return MaterialPageRoute( + builder: (context) => const AppSelectorView(), + settings: data, + ); + }, + PatchesSelectorView: (data) { + return MaterialPageRoute( + builder: (context) => const PatchesSelectorView(), + settings: data, + ); + }, + InstallerView: (data) { + var args = data.getArgs( + orElse: () => InstallerViewArguments(), + ); + return MaterialPageRoute( + builder: (context) => InstallerView(key: args.key), + settings: data, + ); + }, + SettingsView: (data) { + return MaterialPageRoute( + builder: (context) => const SettingsView(), + settings: data, + ); + }, + ContributorsView: (data) { + return MaterialPageRoute( + builder: (context) => const ContributorsView(), + settings: data, + ); + }, + RootCheckerView: (data) { + return MaterialPageRoute( + builder: (context) => const RootCheckerView(), + settings: data, + ); + }, + }; +} + +/// ************************************************************************ +/// Arguments holder classes +/// ************************************************************************* + +/// InstallerView arguments holder class +class InstallerViewArguments { + final Key? key; + InstallerViewArguments({this.key}); +} + +/// ************************************************************************ +/// Extension for strongly typed navigation +/// ************************************************************************* + +extension NavigatorStateExtension on NavigationService { + Future navigateToNavigation({ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.navigation, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } + + Future navigateToAppSelectorView({ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.appSelectorView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } + + Future navigateToPatchesSelectorView({ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.patchesSelectorView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } + + Future navigateToInstallerView({ + Key? key, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.installerView, + arguments: InstallerViewArguments(key: key), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } + + Future navigateToSettingsView({ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.settingsView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } + + Future navigateToContributorsView({ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.contributorsView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } + + Future navigateToRootCheckerView({ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo( + Routes.rootCheckerView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition, + ); + } +} diff --git a/lib/models/patched_application.dart b/lib/models/patched_application.dart index ea530fa6..ecb7a62c 100644 --- a/lib/models/patched_application.dart +++ b/lib/models/patched_application.dart @@ -1,43 +1,21 @@ -import 'dart:typed_data'; -import 'package:json_annotation/json_annotation.dart'; +import 'package:revanced_manager/models/patch.dart'; -part 'patched_application.g.dart'; - -@JsonSerializable() class PatchedApplication { final String name; final String packageName; final String version; final String apkFilePath; - @JsonKey( - fromJson: bytesFromString, - toJson: bytesToString, - ) - final Uint8List icon; - final DateTime patchDate; final bool isRooted; final bool isFromStorage; - final List appliedPatches; + final List appliedPatches; PatchedApplication({ required this.name, required this.packageName, required this.version, required this.apkFilePath, - required this.icon, - required this.patchDate, required this.isRooted, required this.isFromStorage, - this.appliedPatches = const [], + this.appliedPatches = const [], }); - - factory PatchedApplication.fromJson(Map json) => - _$PatchedApplicationFromJson(json); - - Map toJson() => _$PatchedApplicationToJson(this); - - static Uint8List bytesFromString(String pictureUrl) => - Uint8List.fromList(pictureUrl.codeUnits); - - static String bytesToString(Uint8List bytes) => String.fromCharCodes(bytes); } diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index 27cf1c4a..a3541144 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -4,6 +4,7 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:package_archive_info/package_archive_info.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/patcher_api.dart'; @@ -38,8 +39,6 @@ class AppSelectorViewModel extends BaseViewModel { packageName: application.packageName, version: application.versionName!, apkFilePath: application.apkFilePath, - icon: application.icon, - patchDate: DateTime.now(), isRooted: isRooted, isFromStorage: isFromStorage, ); @@ -58,25 +57,20 @@ class AppSelectorViewModel extends BaseViewModel { ); if (result != null && result.files.single.path != null) { File apkFile = File(result.files.single.path!); - ApplicationWithIcon? application = - await DeviceApps.getAppFromStorage(apkFile.path, true) - as ApplicationWithIcon?; - if (application != null) { - PatchedApplication app = PatchedApplication( - name: application.appName, - packageName: application.packageName, - version: application.versionName!, - apkFilePath: result.files.single.path!, - icon: application.icon, - patchDate: DateTime.now(), - isRooted: isRooted, - isFromStorage: isFromStorage, - ); - locator().selectedApp = app; - locator().selectedPatches.clear(); - locator().dimPatchCard = false; - locator().notifyListeners(); - } + PackageArchiveInfo? packageArchiveInfo = + await PackageArchiveInfo.fromPath(apkFile.path); + PatchedApplication app = PatchedApplication( + name: packageArchiveInfo.appName, + packageName: packageArchiveInfo.packageName, + version: packageArchiveInfo.version, + apkFilePath: result.files.single.path!, + isRooted: isRooted, + isFromStorage: isFromStorage, + ); + locator().selectedApp = app; + locator().selectedPatches.clear(); + locator().dimPatchCard = false; + locator().notifyListeners(); } } on Exception { Fluttertoast.showToast( diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index 295380ba..551f0c48 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -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/theme.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/available_updates_card.dart'; @@ -15,8 +14,7 @@ class HomeView extends StatelessWidget { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - disposeViewModel: false, - viewModelBuilder: () => locator(), + viewModelBuilder: () => HomeViewModel(), builder: (context, model, child) => Scaffold( body: SafeArea( child: SingleChildScrollView( diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index c2e958e2..79882510 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -1,22 +1,8 @@ -import 'dart:convert'; - -import 'package:injectable/injectable.dart'; import 'package:revanced_manager/app/app.locator.dart'; -import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:stacked/stacked.dart'; -@lazySingleton class HomeViewModel extends BaseViewModel { Future downloadPatches() => locator().downloadPatches(); Future downloadIntegrations() => locator().downloadIntegrations(); - - Future> getPatchedApps() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - List patchedApps = prefs.getStringList('patchedApps') ?? []; - return patchedApps - .map((app) => PatchedApplication.fromJson(json.decode(app))) - .toList(); - } } diff --git a/lib/ui/views/installer/installer_view.dart b/lib/ui/views/installer/installer_view.dart index ef359925..f915a568 100644 --- a/lib/ui/views/installer/installer_view.dart +++ b/lib/ui/views/installer/installer_view.dart @@ -1,6 +1,5 @@ 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'; @@ -82,8 +81,9 @@ class InstallerView extends StatelessWidget { ), child: SelectableText( model.logs, - style: GoogleFonts.jetBrainsMono( - fontSize: 12, + style: const TextStyle( + fontFamily: 'monospace', + fontSize: 15, height: 1.5, ), ), diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 7c30088a..708c3ff4 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -7,7 +7,6 @@ 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 { @@ -62,25 +61,29 @@ class InstallerViewModel extends BaseViewModel { List selectedPatches = locator().selectedPatches; if (selectedPatches.isNotEmpty) { - addLog('Initializing installer'); + addLog('Initializing installer...'); if (selectedApp.isRooted && !selectedApp.isFromStorage) { - addLog('Checking if an old patched version exists'); + addLog('Checking if an old patched version exists...'); bool oldExists = await locator().checkOldPatch(selectedApp); + addLog('Done'); if (oldExists) { - addLog('Deleting old patched version'); + addLog('Deleting old patched version...'); await locator().deleteOldPatch(selectedApp); + addLog('Done'); } } - addLog('Creating working directory'); + addLog('Creating working directory...'); bool? isSuccess = await locator().initPatcher(); if (isSuccess != null && isSuccess) { + addLog('Done'); updateProgress(0.1); - addLog('Copying original apk'); + addLog('Copying original apk...'); isSuccess = await locator().copyInputFile(apkFilePath); if (isSuccess != null && isSuccess) { + addLog('Done'); updateProgress(0.2); - addLog('Creating patcher'); + addLog('Creating patcher...'); bool resourcePatching = false; if (selectedApp.packageName == 'com.google.android.youtube' || selectedApp.packageName == @@ -92,23 +95,29 @@ class InstallerViewModel extends BaseViewModel { ); if (isSuccess != null && isSuccess) { if (selectedApp.packageName == 'com.google.android.youtube') { + addLog('Done'); updateProgress(0.3); - addLog('Merging integrations'); + addLog('Merging integrations...'); isSuccess = await locator().mergeIntegrations(); } if (isSuccess != null && isSuccess) { + addLog('Done'); updateProgress(0.5); + addLog('Applying patches...'); isSuccess = await locator().applyPatches(selectedPatches); if (isSuccess != null && isSuccess) { + addLog('Done'); updateProgress(0.7); - addLog('Repacking patched apk'); + addLog('Repacking patched apk...'); isSuccess = await locator().repackPatchedFile(); if (isSuccess != null && isSuccess) { + addLog('Done'); updateProgress(0.9); - addLog('Signing patched apk'); + addLog('Signing patched apk...'); isSuccess = await locator().signPatchedFile(); if (isSuccess != null && isSuccess) { + addLog('Done'); showButtons = true; updateProgress(1.0); } @@ -119,13 +128,13 @@ class InstallerViewModel extends BaseViewModel { } } if (isSuccess == null || !isSuccess) { - addLog('An error occurred! Aborting'); + addLog('An error occurred! Aborting...'); } } else { - addLog('No patches selected! Aborting'); + addLog('No patches selected! Aborting...'); } } else { - addLog('No app selected! Aborting'); + addLog('No app selected! Aborting...'); } await FlutterBackground.disableBackgroundExecution(); isPatching = false; @@ -136,14 +145,13 @@ class InstallerViewModel extends BaseViewModel { locator().selectedApp; if (selectedApp != null) { addLog(selectedApp.isRooted - ? 'Installing patched file using root method' - : 'Installing patched file using nonroot method'); + ? 'Installing patched file using root method...' + : 'Installing patched file using nonroot method...'); isInstalled = await locator().installPatchedFile(selectedApp); if (isInstalled) { addLog('Done'); - await saveApp(selectedApp); } else { - addLog('An error occurred! Aborting'); + addLog('An error occurred! Aborting...'); } } } @@ -173,14 +181,4 @@ class InstallerViewModel extends BaseViewModel { DeviceApps.openApp(selectedApp.packageName); } } - - Future saveApp(PatchedApplication selectedApp) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - List patchedApps = prefs.getStringList('patchedApps') ?? []; - String app = selectedApp.toJson().toString(); - if (!patchedApps.contains(app)) { - patchedApps.add(app); - prefs.setStringList('patchedApps', patchedApps); - } - } } diff --git a/lib/ui/widgets/application_item.dart b/lib/ui/widgets/application_item.dart index 4c5c49db..805e8a24 100644 --- a/lib/ui/widgets/application_item.dart +++ b/lib/ui/widgets/application_item.dart @@ -1,30 +1,40 @@ -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:revanced_manager/constants.dart'; import 'package:revanced_manager/ui/widgets/patch_text_button.dart'; -import 'package:timeago/timeago.dart'; class ApplicationItem extends StatelessWidget { - final Uint8List icon; + final String asset; final String name; - final DateTime patchDate; + final String releaseDate; final Function()? onPressed; const ApplicationItem({ Key? key, - required this.icon, + required this.asset, required this.name, - required this.patchDate, + required this.releaseDate, required this.onPressed, }) : super(key: key); @override Widget build(BuildContext context) { + final isSVG = asset.endsWith('.svg'); return ListTile( horizontalTitleGap: 12.0, - leading: Image.memory(icon), + leading: isSVG + ? SvgPicture.asset( + asset, + height: 26, + width: 26, + ) + : Image.asset( + asset, + height: 39, + width: 39, + ), title: Text( name, style: GoogleFonts.roboto( @@ -33,7 +43,7 @@ class ApplicationItem extends StatelessWidget { ), ), subtitle: Text( - format(patchDate), + releaseDate, style: robotoTextStyle, ), trailing: PatchTextButton( diff --git a/lib/ui/widgets/available_updates_card.dart b/lib/ui/widgets/available_updates_card.dart index 075e578d..d2e05b7f 100644 --- a/lib/ui/widgets/available_updates_card.dart +++ b/lib/ui/widgets/available_updates_card.dart @@ -1,9 +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/models/patched_application.dart'; -import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/application_item.dart'; import 'package:revanced_manager/ui/widgets/patch_text_button.dart'; @@ -53,19 +50,17 @@ class AvailableUpdatesCard extends StatelessWidget { ], ), ), - FutureBuilder>( - future: locator().getPatchedApps(), - builder: (context, snapshot) => - snapshot.hasData && snapshot.data!.length > 1 - ? ListView.builder( - itemBuilder: (context, index) => ApplicationItem( - icon: snapshot.data![index].icon, - name: snapshot.data![index].name, - patchDate: snapshot.data![index].patchDate, - onPressed: () => {}, - ), - ) - : Container(), + ApplicationItem( + asset: 'assets/images/revanced.svg', + name: 'ReVanced', + releaseDate: '2 days ago', + onPressed: () => {}, + ), + ApplicationItem( + asset: 'assets/images/reddit.png', + name: 'ReReddit', + releaseDate: 'Released 1 month ago', + onPressed: () => {}, ), const SizedBox(height: 4), I18nText( diff --git a/lib/ui/widgets/installed_apps_card.dart b/lib/ui/widgets/installed_apps_card.dart index a69971b8..b77deba3 100644 --- a/lib/ui/widgets/installed_apps_card.dart +++ b/lib/ui/widgets/installed_apps_card.dart @@ -1,9 +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/models/patched_application.dart'; -import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/application_item.dart'; class InstalledAppsCard extends StatelessWidget { @@ -36,19 +33,11 @@ class InstalledAppsCard extends StatelessWidget { ), ), ), - FutureBuilder>( - future: locator().getPatchedApps(), - builder: (context, snapshot) => - snapshot.hasData && snapshot.data!.length > 1 - ? ListView.builder( - itemBuilder: (context, index) => ApplicationItem( - icon: snapshot.data![index].icon, - name: snapshot.data![index].name, - patchDate: snapshot.data![index].patchDate, - onPressed: () => {}, - ), - ) - : Container(), + ApplicationItem( + asset: 'assets/images/revanced.svg', + name: 'ReVanced', + releaseDate: '2 days ago', + onPressed: () => {}, ), I18nText( 'installedAppsCard.changelogLabel', diff --git a/pubspec.yaml b/pubspec.yaml index 09ee05e3..bb504833 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,10 +12,7 @@ environment: dependencies: app_installer: ^1.1.0 cupertino_icons: ^1.0.2 - device_apps: - git: - url: https://github.com/ponces/flutter_plugin_device_apps - ref: appinfo-from-storage + device_apps: ^2.2.0 dio: ^4.0.6 file_picker: ^5.0.1 flutter: @@ -31,6 +28,7 @@ dependencies: http: ^0.13.4 injectable: ^1.5.3 json_annotation: ^4.6.0 + package_archive_info: ^0.1.0 path_provider: ^2.0.11 root: ^2.0.2 share_extend: ^2.0.0