From 03b45e0db0777b9d2632d46514deec1c2444743c Mon Sep 17 00:00:00 2001 From: Alberto Ponces Date: Mon, 29 Aug 2022 17:44:45 +0100 Subject: [PATCH] feat: use provided patches.json to load patches --- .../app/revanced/manager/MainActivity.kt | 207 +++++---------- lib/main.dart | 2 + lib/models/patch.dart | 44 ++- lib/models/patched_application.dart | 2 +- lib/services/github_api.dart | 10 +- lib/services/patcher_api.dart | 251 +++++++----------- lib/ui/views/home/home_viewmodel.dart | 3 +- .../views/installer/installer_viewmodel.dart | 17 +- .../patches_selector_view.dart | 2 +- .../patches_selector_viewmodel.dart | 8 +- .../patcherView/patch_selector_card.dart | 2 +- 11 files changed, 210 insertions(+), 338 deletions(-) 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 d6d93081..9e2f2ca8 100644 --- a/android/app/src/main/kotlin/app/revanced/manager/MainActivity.kt +++ b/android/app/src/main/kotlin/app/revanced/manager/MainActivity.kt @@ -10,13 +10,7 @@ import app.revanced.manager.utils.zip.ZipFile import app.revanced.manager.utils.zip.structures.ZipEntry import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherOptions -import app.revanced.patcher.data.Data -import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages -import app.revanced.patcher.extensions.PatchExtensions.description -import app.revanced.patcher.extensions.PatchExtensions.include import app.revanced.patcher.extensions.PatchExtensions.patchName -import app.revanced.patcher.extensions.PatchExtensions.version -import app.revanced.patcher.patch.Patch import app.revanced.patcher.util.patch.impl.DexPatchBundle import dalvik.system.DexClassLoader import io.flutter.embedding.android.FlutterActivity @@ -30,7 +24,6 @@ import java.nio.file.StandardCopyOption class MainActivity : FlutterActivity() { private val PATCHER_CHANNEL = "app.revanced.manager/patcher" private val INSTALLER_CHANNEL = "app.revanced.manager/installer" - private var patches = mutableListOf>>() private val handler = Handler(Looper.getMainLooper()) private lateinit var installerChannel: MethodChannel @@ -41,27 +34,8 @@ class MainActivity : FlutterActivity() { MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL) mainChannel.setMethodCallHandler { call, result -> when (call.method) { - "loadPatches" -> { - val jarPatchBundlePath = call.argument("jarPatchBundlePath") - val cacheDirPath = call.argument("cacheDirPath") - if (jarPatchBundlePath != null && cacheDirPath != null) { - loadPatches(result, jarPatchBundlePath, cacheDirPath) - } else { - result.notImplemented() - } - } - "getCompatiblePackages" -> getCompatiblePackages(result) - "getFilteredPatches" -> { - val targetPackage = call.argument("targetPackage") - val targetVersion = call.argument("targetVersion") - val ignoreVersion = call.argument("ignoreVersion") - if (targetPackage != null && targetVersion != null && ignoreVersion != null) { - getFilteredPatches(result, targetPackage, targetVersion, ignoreVersion) - } else { - result.notImplemented() - } - } "runPatcher" -> { + val patchBundleFilePath = call.argument("patchBundleFilePath") val originalFilePath = call.argument("originalFilePath") val inputFilePath = call.argument("inputFilePath") val patchedFilePath = call.argument("patchedFilePath") @@ -71,7 +45,8 @@ class MainActivity : FlutterActivity() { val cacheDirPath = call.argument("cacheDirPath") val mergeIntegrations = call.argument("mergeIntegrations") val resourcePatching = call.argument("resourcePatching") - if (originalFilePath != null && + if (patchBundleFilePath != null && + originalFilePath != null && inputFilePath != null && patchedFilePath != null && outFilePath != null && @@ -83,6 +58,7 @@ class MainActivity : FlutterActivity() { ) { runPatcher( result, + patchBundleFilePath, originalFilePath, inputFilePath, patchedFilePath, @@ -102,79 +78,9 @@ class MainActivity : FlutterActivity() { } } - fun loadPatches( - result: MethodChannel.Result, - jarPatchBundlePath: String, - cacheDirPath: String - ) { - Thread( - Runnable { - patches.addAll( - DexPatchBundle( - jarPatchBundlePath, - DexClassLoader( - jarPatchBundlePath, - cacheDirPath, - null, - javaClass.classLoader - ) - ) - .loadPatches() - ) - handler.post { result.success(null) } - } - ) - .start() - } - - fun getCompatiblePackages(result: MethodChannel.Result) { - Thread( - Runnable { - val filteredPackages = mutableListOf() - patches.forEach patch@{ patch -> - patch.compatiblePackages?.forEach { pkg -> - filteredPackages.add(pkg.name) - } - } - handler.post { result.success(filteredPackages.distinct()) } - } - ) - .start() - } - - fun getFilteredPatches( - result: MethodChannel.Result, - targetPackage: String, - targetVersion: String, - ignoreVersion: Boolean - ) { - Thread( - Runnable { - val filteredPatches = mutableListOf>() - patches.forEach patch@{ patch -> - patch.compatiblePackages?.forEach { pkg -> - if (pkg.name == targetPackage && - (ignoreVersion || - pkg.versions.isNotEmpty() || - pkg.versions.contains(targetVersion)) - ) { - var p = mutableMapOf() - p.put("name", patch.patchName) - p.put("version", patch.version) - p.put("description", patch.description) - p.put("include", patch.include) - filteredPatches.add(p) - } - } - } - handler.post { result.success(filteredPatches) } - } - ) - .start() - } - fun runPatcher( result: MethodChannel.Result, + patchBundleFilePath: String, originalFilePath: String, inputFilePath: String, patchedFilePath: String, @@ -190,8 +96,19 @@ class MainActivity : FlutterActivity() { val patchedFile = File(patchedFilePath) val outFile = File(outFilePath) val integrations = File(integrationsPath) - val filteredPatches = - patches.filter { patch -> selectedPatches.any { it == patch.patchName } } + + val patches = + DexPatchBundle( + patchBundleFilePath, + DexClassLoader( + patchBundleFilePath, + cacheDirPath, + null, + javaClass.classLoader + ) + ) + .loadPatches() + .filter { patch -> selectedPatches.any { it == patch.patchName } } Thread( Runnable { @@ -234,53 +151,69 @@ class MainActivity : FlutterActivity() { app.revanced.patcher.logging.Logger { override fun error(msg: String) { handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.2, - "header" to "", - "log" to msg + installerChannel + .invokeMethod( + "update", + mapOf( + "progress" to + 0.2, + "header" to + "", + "log" to + msg + ) ) - ) } } override fun warn(msg: String) { handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.2, - "header" to "", - "log" to msg + installerChannel + .invokeMethod( + "update", + mapOf( + "progress" to + 0.2, + "header" to + "", + "log" to + msg + ) ) - ) } } override fun info(msg: String) { handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.2, - "header" to "", - "log" to msg + installerChannel + .invokeMethod( + "update", + mapOf( + "progress" to + 0.2, + "header" to + "", + "log" to + msg + ) ) - ) } } override fun trace(msg: String) { handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.2, - "header" to "", - "log" to msg + installerChannel + .invokeMethod( + "update", + mapOf( + "progress" to + 0.2, + "header" to + "", + "log" to + msg + ) ) - ) } } } @@ -289,12 +222,8 @@ class MainActivity : FlutterActivity() { handler.post { installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.3, - "header" to "", - "log" to "" - ) + "update", + mapOf("progress" to 0.3, "header" to "", "log" to "") ) } if (mergeIntegrations) { @@ -321,7 +250,7 @@ class MainActivity : FlutterActivity() { ) ) } - patcher.addPatches(filteredPatches) + patcher.addPatches(patches) patcher.applyPatches().forEach { (patch, res) -> if (res.isSuccess) { val msg = "[success] $patch" @@ -341,11 +270,7 @@ class MainActivity : FlutterActivity() { handler.post { installerChannel.invokeMethod( "update", - mapOf( - "progress" to 0.5, - "header" to "", - "log" to msg - ) + mapOf("progress" to 0.5, "header" to "", "log" to msg) ) } } diff --git a/lib/main.dart b/lib/main.dart index a70f56de..026c7ff2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; import 'package:revanced_manager/main_viewmodel.dart'; import 'package:revanced_manager/services/manager_api.dart'; +import 'package:revanced_manager/services/patcher_api.dart'; import 'package:revanced_manager/theme.dart'; import 'package:revanced_manager/ui/views/home/home_view.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_view.dart'; @@ -69,6 +70,7 @@ class MyApp extends StatelessWidget { Future _init() async { await locator().initialize(); + await locator().initialize(); bool? isRooted = locator().isRooted(); if (isRooted != null) { return const Navigation(); diff --git a/lib/models/patch.dart b/lib/models/patch.dart index 6fa3da9f..eb7d2540 100644 --- a/lib/models/patch.dart +++ b/lib/models/patch.dart @@ -1,15 +1,47 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:revanced_manager/utils/string.dart'; + +part 'patch.g.dart'; + +@JsonSerializable() class Patch { final String name; - final String simpleName; - final String version; final String description; - final bool include; + final String version; + final bool excluded; + final List dependencies; + final List compatiblePackages; Patch({ required this.name, - required this.simpleName, - required this.version, required this.description, - required this.include, + required this.version, + required this.excluded, + required this.dependencies, + required this.compatiblePackages, }); + + factory Patch.fromJson(Map json) => _$PatchFromJson(json); + + Map toJson() => _$PatchToJson(this); + + String getSimpleName() { + return name.replaceAll('-', ' ').split('-').join(' ').toTitleCase(); + } +} + +@JsonSerializable() +class Package { + final String name; + final List versions; + + Package({ + required this.name, + required this.versions, + }); + + factory Package.fromJson(Map json) => + _$PackageFromJson(json); + + Map toJson() => _$PackageToJson(this); } diff --git a/lib/models/patched_application.dart b/lib/models/patched_application.dart index 65054796..2a3747fe 100644 --- a/lib/models/patched_application.dart +++ b/lib/models/patched_application.dart @@ -39,7 +39,7 @@ class PatchedApplication { factory PatchedApplication.fromJson(Map json) => _$PatchedApplicationFromJson(json); - Map toJson() => _$PatchedApplicationToJson(this); + Map toJson() => _$PatchedApplicationToJson(this); static Uint8List decodeBase64(String icon) => base64.decode(icon); diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index fdfdc6be..1a718b4a 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -6,7 +6,7 @@ import 'package:timeago/timeago.dart'; class GithubAPI { final GitHub _github = GitHub(); - Future latestReleaseVersion(String org, repoName) async { + Future latestReleaseVersion(String org, String repoName) async { try { var latestRelease = await _github.repositories.getLatestRelease( RepositorySlug(org, repoName), @@ -20,7 +20,7 @@ class GithubAPI { Future latestReleaseFile( String extension, String org, - repoName, + String repoName, ) async { try { var latestRelease = await _github.repositories.getLatestRelease( @@ -42,7 +42,7 @@ class GithubAPI { return null; } - Future latestCommitTime(String org, repoName) async { + Future latestCommitTime(String org, String repoName) async { try { var repo = await _github.repositories.getRepository( RepositorySlug(org, repoName), @@ -55,13 +55,13 @@ class GithubAPI { } } - Future> getContributors(String org, repoName) async { + Future> getContributors(String org, String repoName) async { return await (_github.repositories.listContributors( RepositorySlug(org, repoName), )).toList(); } - Future> getCommits(String org, repoName) async { + Future> getCommits(String org, String repoName) async { return await (_github.repositories.listCommits( RepositorySlug(org, repoName), )).toList(); diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index c4c81c10..fd94e01c 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:app_installer/app_installer.dart'; import 'package:device_apps/device_apps.dart'; @@ -9,7 +10,6 @@ import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/root_api.dart'; -import 'package:revanced_manager/utils/string.dart'; import 'package:share_extend/share_extend.dart'; @lazySingleton @@ -19,194 +19,123 @@ class PatcherAPI { ); final ManagerAPI _managerAPI = locator(); final RootAPI _rootAPI = RootAPI(); + List _patches = []; Directory? _tmpDir; - Directory? _workDir; - Directory? _cacheDir; - File? _jarPatchBundleFile; - File? _integrations; - File? _inputFile; - File? _patchedFile; File? _outFile; - Future initPatcher() async { - Directory appCache = await getTemporaryDirectory(); - _tmpDir = Directory('${appCache.path}/patcher'); - _tmpDir!.createSync(); - _workDir = _tmpDir!.createTempSync('tmp-'); - _inputFile = File('${_workDir!.path}/base.apk'); - _patchedFile = File('${_workDir!.path}/patched.apk'); - _outFile = File('${_workDir!.path}/out.apk'); - _cacheDir = Directory('${_workDir!.path}/cache'); - _cacheDir!.createSync(); + Future initialize() async { + await _loadPatches(); } - Future loadPatches() async { - if (_tmpDir == null) { - await initPatcher(); - } - if (_jarPatchBundleFile == null) { - _jarPatchBundleFile = await _managerAPI.downloadPatches('.jar'); - if (_jarPatchBundleFile != null) { - try { - await patcherChannel.invokeMethod( - 'loadPatches', - { - 'jarPatchBundlePath': _jarPatchBundleFile!.path, - 'cacheDirPath': _cacheDir!.path, - }, - ); - } on Exception { - return false; + Future _loadPatches() async { + try { + if (_patches.isEmpty) { + File? patchJsonFile = await _managerAPI.downloadPatches('.json'); + if (patchJsonFile != null) { + List list = json.decode(patchJsonFile.readAsStringSync()); + _patches = list.map((patch) => Patch.fromJson(patch)).toList(); } } + } on Exception { + _patches = List.empty(); } - return _jarPatchBundleFile != null; } Future> getFilteredInstalledApps() async { - List filteredPackages = []; - bool isLoaded = await loadPatches(); - if (isLoaded) { - try { - List? patchesPackages = await patcherChannel - .invokeListMethod('getCompatiblePackages'); - if (patchesPackages != null) { - for (String package in patchesPackages) { - try { - ApplicationWithIcon? app = await DeviceApps.getApp(package, true) - as ApplicationWithIcon?; - if (app != null) { - filteredPackages.add(app); - } - } catch (e) { - continue; - } - } - } - } on Exception { - return List.empty(); - } - } - return filteredPackages; - } - - Future> getFilteredPatches( - PatchedApplication? selectedApp, - ) async { - List filteredPatches = []; - if (selectedApp != null) { - bool isLoaded = await loadPatches(); - if (isLoaded) { + List filteredApps = []; + await _loadPatches(); + for (Patch patch in _patches) { + for (Package package in patch.compatiblePackages) { 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', - include: patch['include'] ?? true, - ), - ); - } + if (!filteredApps.any((app) => app.packageName == package.name)) { + ApplicationWithIcon? app = + await DeviceApps.getApp(package.name, true) + as ApplicationWithIcon?; + if (app != null) { + filteredApps.add(app); } } - } on Exception { - return List.empty(); + } catch (e) { + continue; } } } - return filteredPatches; + return filteredApps; } - Future> getAppliedPatches( - PatchedApplication? selectedApp, - ) async { - List appliedPatches = []; - if (selectedApp != null) { - bool isLoaded = await loadPatches(); - if (isLoaded) { - 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', - include: patch['include'] ?? true, - ), - ); - } - } - } - } on Exception { - return List.empty(); - } - } - } - return appliedPatches; + Future> getFilteredPatches(String packageName) async { + await _loadPatches(); + return _patches + .where((patch) => + !patch.name.contains('settings') && + patch.compatiblePackages.any((pack) => pack.name == packageName)) + .toList(); } - Future mergeIntegrations(bool mergeIntegrations) async { - if (mergeIntegrations) { - _integrations = await _managerAPI.downloadIntegrations('.apk'); - } else { - _integrations = null; - } + Future> getAppliedPatches(List appliedPatches) async { + await _loadPatches(); + return _patches + .where((patch) => appliedPatches.contains(patch.name)) + .toList(); } Future runPatcher( + String packageName, String originalFilePath, List selectedPatches, - bool mergeIntegrations, - bool resourcePatching, ) async { - await patcherChannel.invokeMethod( - 'runPatcher', - { - 'originalFilePath': originalFilePath, - 'inputFilePath': _inputFile!.path, - 'patchedFilePath': _patchedFile!.path, - 'outFilePath': _outFile!.path, - 'integrationsPath': _integrations != null ? _integrations!.path : '', - 'selectedPatches': selectedPatches.map((p) => p.name).toList(), - 'cacheDirPath': _cacheDir!.path, - 'mergeIntegrations': mergeIntegrations, - 'resourcePatching': resourcePatching, - }, + bool mergeIntegrations = selectedPatches.any( + (patch) => patch.dependencies.contains('integrations'), ); + bool resourcePatching = selectedPatches.any( + (patch) => patch.dependencies.any((dep) => dep.contains('resource-')), + ); + bool includeSettings = selectedPatches.any( + (patch) => patch.dependencies.contains('settings'), + ); + if (includeSettings) { + try { + Patch settingsPatch = _patches.firstWhere( + (patch) => + patch.name.contains('settings') && + patch.compatiblePackages.any((pack) => pack.name == packageName), + ); + selectedPatches.add(settingsPatch); + } catch (e) { + // ignore + } + } + File? patchBundleFile = await _managerAPI.downloadPatches('.jar'); + File? integrationsFile; + if (mergeIntegrations) { + integrationsFile = await _managerAPI.downloadIntegrations('.apk'); + } + if (patchBundleFile != null) { + Directory appCache = await getTemporaryDirectory(); + _tmpDir = Directory('${appCache.path}/patcher'); + _tmpDir!.createSync(); + Directory workDir = _tmpDir!.createTempSync('tmp-'); + File inputFile = File('${workDir.path}/base.apk'); + File patchedFile = File('${workDir.path}/patched.apk'); + _outFile = File('${workDir.path}/out.apk'); + Directory cacheDir = Directory('${workDir.path}/cache'); + cacheDir.createSync(); + await patcherChannel.invokeMethod( + 'runPatcher', + { + 'patchBundleFilePath': patchBundleFile.path, + 'originalFilePath': originalFilePath, + 'inputFilePath': inputFile.path, + 'patchedFilePath': patchedFile.path, + 'outFilePath': _outFile!.path, + 'integrationsPath': mergeIntegrations ? integrationsFile!.path : '', + 'selectedPatches': selectedPatches.map((p) => p.name).toList(), + 'cacheDirPath': cacheDir.path, + 'mergeIntegrations': mergeIntegrations, + 'resourcePatching': resourcePatching, + }, + ); + } } Future installPatchedFile(PatchedApplication patchedApp) async { diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 49b46bd1..5d4be131 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -27,7 +27,6 @@ class HomeViewModel extends BaseViewModel { Future initialize() async { await _getPatchedApps(); - await _patcherAPI.loadPatches(); await flutterLocalNotificationsPlugin.initialize( const InitializationSettings( android: AndroidInitializationSettings('ic_notification'), @@ -45,7 +44,7 @@ class HomeViewModel extends BaseViewModel { void navigateToPatcher(PatchedApplication app) async { locator().selectedApp = app; locator().selectedPatches = - await _patcherAPI.getAppliedPatches(app); + await _patcherAPI.getAppliedPatches(app.appliedPatches); locator().notifyListeners(); locator().setIndex(1); } diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index cd75b581..5752d35b 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -108,22 +108,7 @@ class InstallerViewModel extends BaseViewModel { } } update(0.0, '', 'Creating working directory'); - bool mergeIntegrations = false; - bool resourcePatching = false; - if (_app!.packageName == 'com.google.android.youtube') { - mergeIntegrations = true; - resourcePatching = true; - } else if (_app!.packageName == - 'com.google.android.apps.youtube.music') { - resourcePatching = true; - } - await _patcherAPI.mergeIntegrations(mergeIntegrations); - await _patcherAPI.runPatcher( - apkFilePath, - _patches, - mergeIntegrations, - resourcePatching, - ); + await _patcherAPI.runPatcher(_app!.packageName, apkFilePath, _patches); } on Exception { update(1.0, 'Aborting...', 'An error occurred! Aborting'); } diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index 5f47094b..d1db6ee2 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -57,7 +57,7 @@ class _PatchesSelectorViewState extends State { .getQueriedPatches(_query) .map((patch) => PatchItem( name: patch.name, - simpleName: patch.simpleName, + simpleName: patch.getSimpleName(), version: patch.version, description: patch.description, isSelected: model.isSelected(patch), diff --git a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart index a644e361..75b55d14 100644 --- a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart +++ b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart @@ -12,11 +12,11 @@ class PatchesSelectorViewModel extends BaseViewModel { Future initialize() async { patches.addAll(await _patcherAPI.getFilteredPatches( - locator().selectedApp, + locator().selectedApp!.packageName, )); - patches.sort((a, b) => a.simpleName.compareTo(b.simpleName)); + patches.sort((a, b) => a.name.compareTo(b.name)); for (Patch p in patches) { - if (p.include) { + if (!p.excluded) { selectedPatches.add(p); } } @@ -56,7 +56,7 @@ class PatchesSelectorViewModel extends BaseViewModel { .where((patch) => query.isEmpty || query.length < 2 || - patch.simpleName.toLowerCase().contains( + patch.name.toLowerCase().contains( query.toLowerCase(), )) .toList(); diff --git a/lib/ui/widgets/patcherView/patch_selector_card.dart b/lib/ui/widgets/patcherView/patch_selector_card.dart index 42339b56..f0b99af0 100644 --- a/lib/ui/widgets/patcherView/patch_selector_card.dart +++ b/lib/ui/widgets/patcherView/patch_selector_card.dart @@ -72,7 +72,7 @@ class PatchSelectorCard extends StatelessWidget { String _getPatchesSelection() { String text = ''; for (Patch p in locator().selectedPatches) { - text += '${p.simpleName} (v${p.version})\n'; + text += '${p.getSimpleName()} (v${p.version})\n'; } return text.substring(0, text.length - 1); }