diff --git a/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt b/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt index 6894c9f1ba..87b4f29d25 100644 --- a/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt +++ b/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt @@ -9,14 +9,15 @@ import android.os.Handler import android.os.Looper import app.revanced.library.ApkUtils import app.revanced.library.ApkUtils.applyTo +import app.revanced.library.installation.installer.LocalInstaller import app.revanced.manager.flutter.utils.Aapt import app.revanced.manager.flutter.utils.packageInstaller.InstallerReceiver import app.revanced.manager.flutter.utils.packageInstaller.UninstallerReceiver -import app.revanced.patcher.PatchBundleLoader -import app.revanced.patcher.PatchSet import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherConfig +import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.loadPatchesFromDex import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel @@ -37,7 +38,7 @@ class MainActivity : FlutterActivity() { private var cancel: Boolean = false private var stopResult: MethodChannel.Result? = null - private lateinit var patches: PatchSet + private lateinit var patches: Set> override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) @@ -70,7 +71,6 @@ class MainActivity : FlutterActivity() { "runPatcher" -> { val inFilePath = call.argument("inFilePath") val outFilePath = call.argument("outFilePath") - val integrationsPath = call.argument("integrationsPath") val selectedPatches = call.argument>("selectedPatches") val options = call.argument>>("options") val tmpDirPath = call.argument("tmpDirPath") @@ -80,7 +80,6 @@ class MainActivity : FlutterActivity() { if ( inFilePath != null && outFilePath != null && - integrationsPath != null && selectedPatches != null && options != null && tmpDirPath != null && @@ -92,14 +91,17 @@ class MainActivity : FlutterActivity() { result, inFilePath, outFilePath, - integrationsPath, selectedPatches, options, tmpDirPath, keyStoreFilePath, keystorePassword ) - } else result.notImplemented() + } else result.error( + "INVALID_ARGUMENTS", + "Invalid arguments", + "One or more arguments are missing" + ) } "stopPatcher" -> { @@ -113,14 +115,16 @@ class MainActivity : FlutterActivity() { try { val patchBundleFile = File(patchBundleFilePath) patchBundleFile.setWritable(false) - patches = PatchBundleLoader.Dex( - patchBundleFile, + patches = loadPatchesFromDex( + setOf(patchBundleFile), optimizedDexDirectory = codeCacheDir ) - } catch (ex: Exception) { - return@setMethodCallHandler result.notImplemented() - } catch (err: Error) { - return@setMethodCallHandler result.notImplemented() + } catch (t: Throwable) { + return@setMethodCallHandler result.error( + "PATCH_BUNDLE_ERROR", + "Failed to load patch bundle", + t.stackTraceToString() + ) } JSONArray().apply { @@ -130,13 +134,13 @@ class MainActivity : FlutterActivity() { put("description", it.description) put("excluded", !it.use) put("compatiblePackages", JSONArray().apply { - it.compatiblePackages?.forEach { compatiblePackage -> + it.compatiblePackages?.forEach { (name, versions) -> val compatiblePackageJson = JSONObject().apply { - put("name", compatiblePackage.name) + put("name", name) put( "versions", JSONArray().apply { - compatiblePackage.versions?.forEach { version -> + versions?.forEach { version -> put(version) } }) @@ -172,7 +176,7 @@ class MainActivity : FlutterActivity() { } }) } ?: put("values", null) - put("valueType", option.valueType) + put("type", option.type) }.let(::put) } }) @@ -211,7 +215,6 @@ class MainActivity : FlutterActivity() { result: MethodChannel.Result, inFilePath: String, outFilePath: String, - integrationsPath: String, selectedPatches: List, options: Map>, tmpDirPath: String, @@ -223,7 +226,6 @@ class MainActivity : FlutterActivity() { inFile.setWritable(true) inFile.setReadable(true) val outFile = File(outFilePath) - val integrations = File(integrationsPath) val keyStoreFile = File(keyStoreFilePath) val tmpDir = File(tmpDirPath) @@ -289,8 +291,8 @@ class MainActivity : FlutterActivity() { updateProgress(0.02, "Loading patches...", "Loading patches") val patches = patches.filter { patch -> - val isCompatible = patch.compatiblePackages?.any { - it.name == patcher.context.packageMetadata.packageName + val isCompatible = patch.compatiblePackages?.any { (name, _) -> + name == patcher.context.packageMetadata.packageName } ?: false val compatibleOrUniversal = @@ -307,10 +309,7 @@ class MainActivity : FlutterActivity() { updateProgress(0.05, "Executing...", "") val patcherResult = patcher.use { - patcher.apply { - acceptIntegrations(setOf(integrations)) - acceptPatches(patches) - } + it += patches runBlocking { // Update the progress bar every time a patch is executed from 0.15 to 0.7 @@ -318,7 +317,7 @@ class MainActivity : FlutterActivity() { val progressStep = 0.55 / totalPatchesCount var progress = 0.05 - patcher.apply(false).collect(FlowCollector { patchResult: PatchResult -> + patcher().collect(FlowCollector { patchResult: PatchResult -> if (cancel(patcher::close)) return@FlowCollector val msg = patchResult.exception?.let { @@ -346,10 +345,11 @@ class MainActivity : FlutterActivity() { if (cancel(patcher::close)) return@Thread - ApkUtils.sign( + ApkUtils.signApk( inFile, outFile, - ApkUtils.SigningOptions( + "ReVanced", + ApkUtils.KeyStoreDetails( keyStoreFile, keystorePassword, "alias", diff --git a/android/build.gradle.kts b/android/build.gradle.kts index f5512069db..b454af29f4 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -21,7 +21,8 @@ subprojects { afterEvaluate { extensions.findByName("android")?.let { it as CommonExtension<*, *, *, *, *, *> - it.compileSdk = 34 + if (it.compileSdk != null && it.compileSdk!! < 31) + it.compileSdk = 34 } } diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index f6ab96e266..1ac691b778 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] -revanced-patcher = "19.3.1" # TODO: Update to non-dev -revanced-library = "2.2.1" +revanced-patcher = "20.0.2" +revanced-library = "3.0.1" desugar_jdk_libs = "2.1.2" [libraries] diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 09ac9dd67a..9444e03e66 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -17,7 +17,7 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false + id("com.android.application") version "8.5.0" apply false id("org.jetbrains.kotlin.android") version "2.0.20" apply false } diff --git a/assets/i18n/strings.i18n.json b/assets/i18n/strings.i18n.json index e1b9d4128c..a6e618ea5c 100755 --- a/assets/i18n/strings.i18n.json +++ b/assets/i18n/strings.i18n.json @@ -158,20 +158,18 @@ "languageLabel": "Language", "languageUpdated": "Language updated", "sourcesLabel": "Alternative sources", - "sourcesLabelHint": "Configure the alternative sources for ReVanced Patches and ReVanced Integrations", - "sourcesIntegrationsLabel": "Integrations source", + "sourcesLabelHint": "Configure the alternative sources for ReVanced Patches", "useAlternativeSources": "Use alternative sources", - "useAlternativeSourcesHint": "Use alternative sources for ReVanced Patches and ReVanced Integrations instead of the API", + "useAlternativeSourcesHint": "Use alternative sources for ReVanced Patches instead of the API", "sourcesResetDialogTitle": "Reset", "sourcesResetDialogText": "Are you sure you want to reset your sources to their default values?", "apiURLResetDialogText": "Are you sure you want to reset your API URL to its default value?", - "sourcesUpdateNote": "Note: This will automatically download ReVanced Patches and ReVanced Integrations from the alternative sources.\n\nThis will connect you to the alternative source.", + "sourcesUpdateNote": "Note: This will automatically download ReVanced Patches from the alternative sources.\n\nThis will connect you to the alternative source.", "apiURLLabel": "API URL", "apiURLHint": "Configure the API URL of ReVanced Manager", "selectApiURL": "API URL", "orgPatchesLabel": "Patches organization", "sourcesPatchesLabel": "Patches source", - "orgIntegrationsLabel": "Integrations organization", "contributorsLabel": "Contributors", "contributorsHint": "A list of contributors of ReVanced", "logsLabel": "Share logs", diff --git a/lib/models/patch.dart b/lib/models/patch.dart index 1b86ba5b50..730df32681 100644 --- a/lib/models/patch.dart +++ b/lib/models/patch.dart @@ -62,11 +62,12 @@ class Option { required this.value, required this.values, required this.required, - required this.valueType, + required this.type, }); factory Option.fromJson(Map json) { _migrateV17ToV19(json); + _migrateV19ToV20(json); return _$OptionFromJson(json); } @@ -83,13 +84,25 @@ class Option { } } + static void _migrateV19ToV20(Map json) { + if (json['valueType'] != null) { + final String type = json['valueType']; + + json['type'] = type.endsWith('Array') + ? 'kotlin.collections.List' + : 'kotlin.$type'; + + json['valueType'] = null; + } + } + final String key; final String title; final String description; final dynamic value; final Map? values; final bool required; - final String valueType; + final String type; Map toJson() => _$OptionToJson(this); } diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index ed8d3be5d6..fb9cd4f942 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -111,11 +111,7 @@ class GithubAPI { ); if (asset != null) { final String downloadUrl = asset['browser_download_url']; - if (extension == '.apk') { - _managerAPI.setIntegrationsDownloadURL(downloadUrl); - } else { - _managerAPI.setPatchesDownloadURL(downloadUrl); - } + _managerAPI.setPatchesDownloadURL(downloadUrl); return await _downloadManager.getSingleFile( downloadUrl, ); diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 3875d333ff..a0a6a92373 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -44,15 +44,13 @@ class ManagerAPI { String keystoreFile = '/sdcard/Android/data/app.revanced.manager.flutter/files/revanced-manager.keystore'; String defaultKeystorePassword = 's3cur3p@ssw0rd'; - String defaultApiUrl = 'https://api.revanced.app/'; + String defaultApiUrl = 'https://api.revanced.app/v3'; String defaultRepoUrl = 'https://api.github.com'; String defaultPatcherRepo = 'revanced/revanced-patcher'; String defaultPatchesRepo = 'revanced/revanced-patches'; - String defaultIntegrationsRepo = 'revanced/revanced-integrations'; String defaultCliRepo = 'revanced/revanced-cli'; String defaultManagerRepo = 'revanced/revanced-manager'; String? patchesVersion = ''; - String? integrationsVersion = ''; Future initialize() async { _prefs = await SharedPreferences.getInstance(); @@ -69,13 +67,15 @@ class ManagerAPI { } // Migrate to new API URL if not done yet as the old one is sunset. - final bool hasMigratedToNewApi = - _prefs.getBool('migratedToNewApiUrl') ?? false; - if (!hasMigratedToNewApi) { + final bool hasMigratedToLatestApi = + _prefs.getBool('migratedToLatestApiUrl') ?? false; + if (!hasMigratedToLatestApi) { final String apiUrl = getApiUrl().toLowerCase(); - if (apiUrl.contains('releases.revanced.app')) { + if (apiUrl.contains('releases.revanced.app') || + (apiUrl.contains('api.revanced.app') && + !apiUrl.contains('v3'))) { await setApiUrl(''); // Reset to default. - _prefs.setBool('migratedToNewApiUrl', true); + _prefs.setBool('migratedToLatestApiUrl', true); } } @@ -83,10 +83,8 @@ class ManagerAPI { _prefs.getBool('migratedToAlternativeSource') ?? false; if (!hasMigratedToAlternativeSource) { final String patchesRepo = getPatchesRepo(); - final String integrationsRepo = getIntegrationsRepo(); final bool usingAlternativeSources = - patchesRepo.toLowerCase() != defaultPatchesRepo || - integrationsRepo.toLowerCase() != defaultIntegrationsRepo; + patchesRepo.toLowerCase() != defaultPatchesRepo; _prefs.setBool('useAlternativeSources', usingAlternativeSources); _prefs.setBool('migratedToAlternativeSource', true); } @@ -200,14 +198,6 @@ class ManagerAPI { await _prefs.setStringList('savedPatches-$packageName', patchesJson); } - String getIntegrationsDownloadURL() { - return _prefs.getString('integrationsDownloadURL') ?? ''; - } - - Future setIntegrationsDownloadURL(String value) async { - await _prefs.setString('integrationsDownloadURL', value); - } - List getUsedPatches(String packageName) { final List patchesJson = _prefs.getStringList('usedPatches-$packageName') ?? []; @@ -256,17 +246,6 @@ class ManagerAPI { _prefs.remove('patchOption-$packageName-$patchName-$key'); } - String getIntegrationsRepo() { - return _prefs.getString('integrationsRepo') ?? defaultIntegrationsRepo; - } - - Future setIntegrationsRepo(String value) async { - if (value.isEmpty || value.startsWith('/') || value.endsWith('/')) { - value = defaultIntegrationsRepo; - } - await _prefs.setString('integrationsRepo', value); - } - bool getUseDynamicTheme() { return _prefs.getBool('useDynamicTheme') ?? false; } @@ -464,28 +443,7 @@ class ManagerAPI { final String currentVersion = await getCurrentPatchesVersion(); final String url = getPatchesDownloadURL(); return await _githubAPI.getReleaseFile( - '.jar', - repoName, - currentVersion, - url, - ); - } on Exception catch (e) { - if (kDebugMode) { - print(e); - } - return null; - } - } - - Future downloadIntegrations() async { - try { - final String repoName = !isUsingAlternativeSources() - ? defaultIntegrationsRepo - : getIntegrationsRepo(); - final String currentVersion = await getCurrentIntegrationsVersion(); - final String url = getIntegrationsDownloadURL(); - return await _githubAPI.getReleaseFile( - '.apk', + '.rvp', repoName, currentVersion, url, @@ -499,18 +457,12 @@ class ManagerAPI { } Future downloadManager() async { - return await _revancedAPI.getLatestReleaseFile( - '.apk', - defaultManagerRepo, - ); + return await _revancedAPI.getLatestReleaseFile('manager'); } Future getLatestPatchesReleaseTime() async { if (!isUsingAlternativeSources()) { - return await _revancedAPI.getLatestReleaseTime( - '.json', - defaultPatchesRepo, - ); + return await _revancedAPI.getLatestReleaseTime('patches'); } else { final release = await _githubAPI.getLatestRelease(getPatchesRepo()); if (release != null) { @@ -525,39 +477,20 @@ class ManagerAPI { Future getLatestManagerReleaseTime() async { return await _revancedAPI.getLatestReleaseTime( - '.apk', - defaultManagerRepo, + 'manager', ); } Future getLatestManagerVersion() async { return await _revancedAPI.getLatestReleaseVersion( - '.apk', - defaultManagerRepo, + 'manager', ); } - Future getLatestIntegrationsVersion() async { - if (!isUsingAlternativeSources()) { - return await _revancedAPI.getLatestReleaseVersion( - '.apk', - defaultIntegrationsRepo, - ); - } else { - final release = await _githubAPI.getLatestRelease(getIntegrationsRepo()); - if (release != null) { - return release['tag_name']; - } else { - return null; - } - } - } - Future getLatestPatchesVersion() async { if (!isUsingAlternativeSources()) { return await _revancedAPI.getLatestReleaseVersion( - '.json', - defaultPatchesRepo, + 'patches', ); } else { final release = await _githubAPI.getLatestRelease(getPatchesRepo()); @@ -620,25 +553,6 @@ class ManagerAPI { await downloadPatches(); } - Future getCurrentIntegrationsVersion() async { - integrationsVersion = _prefs.getString('integrationsVersion') ?? '0.0.0'; - if (integrationsVersion == '0.0.0' || isPatchesAutoUpdate()) { - final String newIntegrationsVersion = - await getLatestIntegrationsVersion() ?? '0.0.0'; - if (integrationsVersion != newIntegrationsVersion && - newIntegrationsVersion != '0.0.0') { - await setCurrentIntegrationsVersion(newIntegrationsVersion); - } - } - return integrationsVersion!; - } - - Future setCurrentIntegrationsVersion(String version) async { - await _prefs.setString('integrationsVersion', version); - await setIntegrationsDownloadURL(''); - await downloadIntegrations(); - } - Future> getAppsToRemove( List patchedApps, ) async { diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index 018d227e6c..1245cec68d 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -33,7 +33,6 @@ class PatcherAPI { Future initialize() async { await loadPatches(); - await _managerAPI.downloadIntegrations(); final Directory appCache = await getApplicationSupportDirectory(); _dataDir = await getExternalStorageDirectory() ?? appCache; _tmpDir = Directory('${appCache.path}/patcher'); @@ -153,7 +152,6 @@ class PatcherAPI { List selectedPatches, bool isFromStorage, ) async { - final File? integrationsFile = await _managerAPI.downloadIntegrations(); final Map> options = {}; for (final patch in selectedPatches) { if (patch.options.isNotEmpty) { @@ -169,44 +167,41 @@ class PatcherAPI { } } - if (integrationsFile != null) { - _dataDir.createSync(); - _tmpDir.createSync(); - final Directory workDir = await _tmpDir.createTemp('tmp-'); + _dataDir.createSync(); + _tmpDir.createSync(); + final Directory workDir = await _tmpDir.createTemp('tmp-'); - final File inApkFile = File('${workDir.path}/in.apk'); - await File(apkFilePath).copy(inApkFile.path); + final File inApkFile = File('${workDir.path}/in.apk'); + await File(apkFilePath).copy(inApkFile.path); - if (isFromStorage) { - // The selected apk was copied to cacheDir by the file picker, so it's not needed anymore. - // rename() can't be used here, as Android system also counts the size of files moved out from cacheDir - // as part of the app's cache size. - File(apkFilePath).delete(); - } + if (isFromStorage) { + // The selected apk was copied to cacheDir by the file picker, so it's not needed anymore. + // rename() can't be used here, as Android system also counts the size of files moved out from cacheDir + // as part of the app's cache size. + File(apkFilePath).delete(); + } - outFile = File('${workDir.path}/out.apk'); + outFile = File('${workDir.path}/out.apk'); - final Directory tmpDir = - Directory('${workDir.path}/revanced-temporary-files'); + final Directory tmpDir = + Directory('${workDir.path}/revanced-temporary-files'); - try { - await patcherChannel.invokeMethod( - 'runPatcher', - { - 'inFilePath': inApkFile.path, - 'outFilePath': outFile!.path, - 'integrationsPath': integrationsFile.path, - 'selectedPatches': selectedPatches.map((p) => p.name).toList(), - 'options': options, - 'tmpDirPath': tmpDir.path, - 'keyStoreFilePath': _keyStoreFile.path, - 'keystorePassword': _managerAPI.getKeystorePassword(), - }, - ); - } on Exception catch (e) { - if (kDebugMode) { - print(e); - } + try { + await patcherChannel.invokeMethod( + 'runPatcher', + { + 'inFilePath': inApkFile.path, + 'outFilePath': outFile!.path, + 'selectedPatches': selectedPatches.map((p) => p.name).toList(), + 'options': options, + 'tmpDirPath': tmpDir.path, + 'keyStoreFilePath': _keyStoreFile.path, + 'keystorePassword': _managerAPI.getKeystorePassword(), + }, + ); + } on Exception catch (e) { + if (kDebugMode) { + print(e); } } } diff --git a/lib/services/revanced_api.dart b/lib/services/revanced_api.dart index cc62f0d592..020922824e 100644 --- a/lib/services/revanced_api.dart +++ b/lib/services/revanced_api.dart @@ -1,7 +1,5 @@ import 'dart:async'; import 'dart:io'; - -import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; @@ -31,7 +29,7 @@ class RevancedAPI { final Map> contributors = {}; try { final response = await _dio.get('/contributors'); - final List repositories = response.data['repositories']; + final List repositories = response.data; for (final Map repo in repositories) { final String name = repo['name']; contributors[name] = repo['contributors']; @@ -46,21 +44,15 @@ class RevancedAPI { } Future?> _getLatestRelease( - String extension, - String repoName, + String toolName, ) { if (!locator().getDownloadConsent()) { return Future(() => null); } return getToolsLock.synchronized(() async { try { - final response = await _dio.get('/tools'); - final List tools = response.data['tools']; - return tools.firstWhereOrNull( - (t) => - (t['repository'] as String) == repoName && - (t['name'] as String).endsWith(extension), - ); + final response = await _dio.get('/$toolName/latest'); + return response.data; } on Exception catch (e) { if (kDebugMode) { print(e); @@ -71,13 +63,11 @@ class RevancedAPI { } Future getLatestReleaseVersion( - String extension, - String repoName, + String toolName, ) async { try { final Map? release = await _getLatestRelease( - extension, - repoName, + toolName, ); if (release != null) { return release['version']; @@ -92,16 +82,14 @@ class RevancedAPI { } Future getLatestReleaseFile( - String extension, - String repoName, + String toolName, ) async { try { final Map? release = await _getLatestRelease( - extension, - repoName, + toolName, ); if (release != null) { - final String url = release['browser_download_url']; + final String url = release['assets'][0]['download_url']; return await _downloadManager.getSingleFile(url); } } on Exception catch (e) { @@ -129,13 +117,10 @@ class RevancedAPI { } Future downloadManager() async { - final Map? release = await _getLatestRelease( - '.apk', - 'revanced/revanced-manager', - ); + final Map? release = await _getLatestRelease('manager'); File? outputFile; await for (final result in _downloadManager.getFileStream( - release!['browser_download_url'] as String, + release!['download_url'] as String, )) { if (result is DownloadProgress) { final totalSize = result.totalSize ?? 10000000; @@ -152,17 +137,15 @@ class RevancedAPI { } Future getLatestReleaseTime( - String extension, - String repoName, + String toolName, ) async { try { final Map? release = await _getLatestRelease( - extension, - repoName, + toolName, ); if (release != null) { final DateTime timestamp = - DateTime.parse(release['timestamp'] as String); + DateTime.parse(release['created_at'] as String); return format(timestamp, locale: 'en_short'); } } on Exception catch (e) { diff --git a/lib/ui/views/contributors/contributors_view.dart b/lib/ui/views/contributors/contributors_view.dart index c2b91b3ac6..847e0cf2b6 100644 --- a/lib/ui/views/contributors/contributors_view.dart +++ b/lib/ui/views/contributors/contributors_view.dart @@ -40,11 +40,6 @@ class ContributorsView extends StatelessWidget { contributors: model.patchesContributors, ), const SizedBox(height: 20), - ContributorsCard( - title: 'ReVanced Integrations', - contributors: model.integrationsContributors, - ), - const SizedBox(height: 20), ContributorsCard( title: 'ReVanced CLI', contributors: model.cliContributors, diff --git a/lib/ui/views/contributors/contributors_viewmodel.dart b/lib/ui/views/contributors/contributors_viewmodel.dart index 785148f5a6..0272232202 100644 --- a/lib/ui/views/contributors/contributors_viewmodel.dart +++ b/lib/ui/views/contributors/contributors_viewmodel.dart @@ -6,19 +6,18 @@ class ContributorsViewModel extends BaseViewModel { final ManagerAPI _managerAPI = locator(); List patcherContributors = []; List patchesContributors = []; - List integrationsContributors = []; List cliContributors = []; List managerContributors = []; + String repoName(String repo) => repo.split('/').last; + Future getContributors() async { final Map> contributors = await _managerAPI.getContributors(); - patcherContributors = contributors[_managerAPI.defaultPatcherRepo] ?? []; - patchesContributors = contributors[_managerAPI.defaultPatchesRepo] ?? []; - integrationsContributors = - contributors[_managerAPI.defaultIntegrationsRepo] ?? []; - cliContributors = contributors[_managerAPI.defaultCliRepo] ?? []; - managerContributors = contributors[_managerAPI.defaultManagerRepo] ?? []; + patcherContributors = contributors[repoName(_managerAPI.defaultPatcherRepo)] ?? []; + patchesContributors = contributors[repoName(_managerAPI.defaultPatchesRepo)] ?? []; + cliContributors = contributors[repoName(_managerAPI.defaultCliRepo)] ?? []; + managerContributors = contributors[repoName(_managerAPI.defaultManagerRepo)] ?? []; notifyListeners(); } } diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 8271f96b71..444b9fea50 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -311,11 +311,8 @@ class HomeViewModel extends BaseViewModel { _toast.showBottom(t.homeView.downloadingMessage); final String patchesVersion = await _managerAPI.getLatestPatchesVersion() ?? '0.0.0'; - final String integrationsVersion = - await _managerAPI.getLatestIntegrationsVersion() ?? '0.0.0'; - if (patchesVersion != '0.0.0' && integrationsVersion != '0.0.0') { + if (patchesVersion != '0.0.0') { await _managerAPI.setCurrentPatchesVersion(patchesVersion); - await _managerAPI.setCurrentIntegrationsVersion(integrationsVersion); _toast.showBottom(t.homeView.downloadedMessage); forceRefresh(context); } else { diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 2bc9fb5b29..65cbf513ce 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -330,7 +330,6 @@ class InstallerViewModel extends BaseViewModel { 'Version compatibility check: ${_managerAPI.isVersionCompatibilityCheckEnabled()}', 'Show universal patches: ${_managerAPI.areUniversalPatchesEnabled()}', 'Patches source: ${_managerAPI.getPatchesRepo()}', - 'Integration source: ${_managerAPI.getIntegrationsRepo()}', // '\n- Logs', logsTrimmed.join('\n'), diff --git a/lib/ui/views/patch_options/patch_options_view.dart b/lib/ui/views/patch_options/patch_options_view.dart index 986c76fb40..4f27fbece2 100644 --- a/lib/ui/views/patch_options/patch_options_view.dart +++ b/lib/ui/views/patch_options/patch_options_view.dart @@ -44,20 +44,20 @@ class PatchOptionsView extends StatelessWidget { child: Column( children: [ for (final Option option in model.modifiedOptions) - if (option.valueType == 'String' || - option.valueType == 'Int') + if (option.type == 'kotlin.String' || + option.type == 'kotlin.Int') IntAndStringPatchOption( patchOption: option, model: model, ) - else if (option.valueType == 'Boolean') + else if (option.type == 'kotlin.Boolean') BooleanPatchOption( patchOption: option, model: model, ) - else if (option.valueType == 'StringArray' || - option.valueType == 'IntArray' || - option.valueType == 'LongArray') + else if (option.type == 'kotlin.collections.List' || + option.type == 'kotlin.collections.List' || + option.type == 'kotlin.collections.List') IntStringLongListPatchOption( patchOption: option, model: model, diff --git a/lib/ui/views/patch_options/patch_options_viewmodel.dart b/lib/ui/views/patch_options/patch_options_viewmodel.dart index 3fabeb8bdf..3aa11bb34f 100644 --- a/lib/ui/views/patch_options/patch_options_viewmodel.dart +++ b/lib/ui/views/patch_options/patch_options_viewmodel.dart @@ -74,7 +74,7 @@ class PatchOptionsViewModel extends BaseViewModel { title: option.title, description: option.description, values: option.values, - valueType: option.valueType, + type: option.type, value: value, required: option.required, key: option.key, @@ -90,7 +90,7 @@ class PatchOptionsViewModel extends BaseViewModel { title: option.title, description: option.description, values: option.values, - valueType: option.valueType, + type: option.type, value: option.value is List ? option.value.toList() : option.value, required: option.required, key: option.key, diff --git a/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart b/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart index 2a7b2d4e43..c1faeacf40 100644 --- a/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart +++ b/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart @@ -14,16 +14,11 @@ class SManageSources extends BaseViewModel { final TextEditingController _orgPatSourceController = TextEditingController(); final TextEditingController _patSourceController = TextEditingController(); - final TextEditingController _orgIntSourceController = TextEditingController(); - final TextEditingController _intSourceController = TextEditingController(); Future showSourcesDialog(BuildContext context) async { final String patchesRepo = _managerAPI.getPatchesRepo(); - final String integrationsRepo = _managerAPI.getIntegrationsRepo(); _orgPatSourceController.text = patchesRepo.split('/')[0]; _patSourceController.text = patchesRepo.split('/')[1]; - _orgIntSourceController.text = integrationsRepo.split('/')[0]; - _intSourceController.text = integrationsRepo.split('/')[1]; return showDialog( context: context, builder: (context) => AlertDialog( @@ -72,38 +67,6 @@ class SManageSources extends BaseViewModel { hintText: patchesRepo.split('/')[1], ), ), - const SizedBox(height: 8), - // Integrations owner's name - TextField( - controller: _orgIntSourceController, - autocorrect: false, - onChanged: (value) => notifyListeners(), - decoration: InputDecoration( - icon: Icon( - Icons.merge_outlined, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - border: const OutlineInputBorder(), - labelText: t.settingsView.orgIntegrationsLabel, - hintText: integrationsRepo.split('/')[0], - ), - ), - const SizedBox(height: 8), - // Integrations repository's name - TextField( - controller: _intSourceController, - autocorrect: false, - onChanged: (value) => notifyListeners(), - decoration: InputDecoration( - icon: const Icon( - Icons.merge_outlined, - color: Colors.transparent, - ), - border: const OutlineInputBorder(), - labelText: t.settingsView.sourcesIntegrationsLabel, - hintText: integrationsRepo.split('/')[1], - ), - ), const SizedBox(height: 20), Text(t.settingsView.sourcesUpdateNote), ], @@ -113,8 +76,6 @@ class SManageSources extends BaseViewModel { onPressed: () { _orgPatSourceController.clear(); _patSourceController.clear(); - _orgIntSourceController.clear(); - _intSourceController.clear(); Navigator.of(context).pop(); }, child: Text(t.cancelButton), @@ -124,11 +85,7 @@ class SManageSources extends BaseViewModel { _managerAPI.setPatchesRepo( '${_orgPatSourceController.text.trim()}/${_patSourceController.text.trim()}', ); - _managerAPI.setIntegrationsRepo( - '${_orgIntSourceController.text.trim()}/${_intSourceController.text.trim()}', - ); _managerAPI.setCurrentPatchesVersion('0.0.0'); - _managerAPI.setCurrentIntegrationsVersion('0.0.0'); _managerAPI.setLastUsedPatchesVersion(); _toast.showBottom(t.settingsView.restartAppForChanges); Navigator.of(context).pop(); @@ -154,9 +111,7 @@ class SManageSources extends BaseViewModel { FilledButton( onPressed: () { _managerAPI.setPatchesRepo(''); - _managerAPI.setIntegrationsRepo(''); _managerAPI.setCurrentPatchesVersion('0.0.0'); - _managerAPI.setCurrentIntegrationsVersion('0.0.0'); _toast.showBottom(t.settingsView.restartAppForChanges); Navigator.of(context) ..pop() diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 533f2257fc..7ebd0d0d52 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -56,7 +56,6 @@ class SettingsViewModel extends BaseViewModel { void useAlternativeSources(bool value) { _managerAPI.useAlternativeSources(value); _managerAPI.setCurrentPatchesVersion('0.0.0'); - _managerAPI.setCurrentIntegrationsVersion('0.0.0'); _managerAPI.setLastUsedPatchesVersion(); notifyListeners(); } diff --git a/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart b/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart index 19213a4538..081231600a 100644 --- a/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart +++ b/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart @@ -138,7 +138,7 @@ class IntStringLongListPatchOption extends StatelessWidget { Widget build(BuildContext context) { final List values = List.from(patchOption.value ?? []); final ValueNotifier patchOptionValue = ValueNotifier(values); - final String type = patchOption.valueType; + final String type = patchOption.type; String getKey(dynamic value) { if (value != null && patchOption.values != null) { @@ -408,12 +408,12 @@ class _TextFieldForPatchOptionState extends State { @override Widget build(BuildContext context) { - final bool isStringOption = widget.patchOption.valueType.contains('String'); - final bool isArrayOption = widget.patchOption.valueType.contains('Array'); + final bool isStringOption = widget.patchOption.type.contains('String'); + final bool isListOption = widget.patchOption.type.contains('List'); selectedKey = selectedKey == '' ? selectedKey : widget.selectedKey; final bool isValueArray = widget.value?.startsWith('[') ?? false; final bool shouldResetValue = - !isStringOption && isArrayOption && selectedKey == '' && isValueArray; + !isStringOption && isListOption && selectedKey == '' && isValueArray; controller.text = shouldResetValue ? '' : widget.value ?? ''; defaultValue ??= controller.text; return Column( @@ -479,7 +479,7 @@ class _TextFieldForPatchOptionState extends State { } else { controller.text = widget.patchOption.values![value].toString(); widget.onChanged( - isArrayOption + isListOption ? widget.patchOption.values![value] : controller.text, ); @@ -492,9 +492,9 @@ class _TextFieldForPatchOptionState extends State { if (selectedKey == '') TextFormField( inputFormatters: [ - if (widget.patchOption.valueType.contains('Int')) + if (widget.patchOption.type.contains('Int')) FilteringTextInputFormatter.allow(RegExp(r'[0-9]')), - if (widget.patchOption.valueType.contains('Long')) + if (widget.patchOption.type.contains('Long')) FilteringTextInputFormatter.allow(RegExp(r'^[0-9]*\.?[0-9]*')), ], controller: controller, @@ -505,7 +505,7 @@ class _TextFieldForPatchOptionState extends State { tooltip: t.patchOptionsView.tooltip, itemBuilder: (BuildContext context) { return [ - if (isArrayOption) + if (isListOption) PopupMenuItem( value: 'remove', child: Text(t.remove), diff --git a/lib/utils/check_for_supported_patch.dart b/lib/utils/check_for_supported_patch.dart index 5cb311c610..f5c4ecbab9 100644 --- a/lib/utils/check_for_supported_patch.dart +++ b/lib/utils/check_for_supported_patch.dart @@ -33,7 +33,7 @@ bool hasUnsupportedRequiredOption(List