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 00000000..941a12e6
Binary files /dev/null and b/assets/images/reddit.png differ
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