From 8d0ee814fc7a2c4fdd7b7ffbfbe2748ded972ada Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 8 Jan 2026 22:00:04 +0100 Subject: [PATCH] Merge synonym plugin to downloader --- README.md | 2 +- api/api/api.api | 104 ++++++++--------- api/build.gradle.kts | 4 +- .../manager/downloader/webview/IWebView.aidl | 8 ++ .../downloader/webview/IWebViewEvents.aidl | 11 ++ .../plugin/downloader/webview/IWebView.aidl | 8 -- .../downloader/webview/IWebViewEvents.aidl | 11 -- .../revanced/manager/downloader/Constants.kt | 7 ++ .../{plugin => }/downloader/Downloader.kt | 34 +++--- .../{plugin => }/downloader/Extensions.kt | 6 +- .../{plugin => }/downloader/Parcelables.kt | 4 +- .../{plugin => }/downloader/webview/API.kt | 20 ++-- .../downloader/webview/WebViewActivity.kt | 12 +- .../manager/plugin/downloader/Constants.kt | 7 -- app/proguard-rules.pro | 2 +- .../1.json | 30 ++--- app/src/main/AndroidManifest.xml | 10 +- .../java/app/revanced/manager/MainActivity.kt | 2 +- .../revanced/manager/ManagerApplication.kt | 6 +- .../revanced/manager/data/room/AppDatabase.kt | 8 +- .../TrustedDownloader.kt} | 6 +- .../room/downloader/TrustedDownloaderDao.kt | 22 ++++ .../plugins/TrustedDownloaderPluginDao.kt | 22 ---- .../revanced/manager/di/RepositoryModule.kt | 2 +- .../domain/manager/PreferencesManager.kt | 2 +- .../repository/DownloadedAppRepository.kt | 10 +- ...nRepository.kt => DownloaderRepository.kt} | 106 +++++++++--------- .../downloader/DownloaderPluginState.kt | 9 -- .../network/downloader/DownloaderState.kt | 9 ++ ...ownloaderPlugin.kt => LoadedDownloader.kt} | 6 +- .../downloader/ParceledDownloaderData.kt | 12 +- .../manager/patcher/worker/PatcherWorker.kt | 36 +++--- .../manager/ui/screen/DashboardScreen.kt | 12 +- .../manager/ui/screen/PatcherScreen.kt | 2 +- .../ui/screen/SelectedAppInfoScreen.kt | 36 +++--- .../settings/DownloadsSettingsScreen.kt | 56 ++++----- .../ui/viewmodel/DashboardViewModel.kt | 16 +-- .../ui/viewmodel/DownloadsViewModel.kt | 25 ++--- .../manager/ui/viewmodel/PatcherViewModel.kt | 10 +- .../ui/viewmodel/SelectedAppInfoViewModel.kt | 50 ++++----- app/src/main/res/values/strings.xml | 38 +++---- 41 files changed, 384 insertions(+), 399 deletions(-) create mode 100644 api/src/main/aidl/app/revanced/manager/downloader/webview/IWebView.aidl create mode 100644 api/src/main/aidl/app/revanced/manager/downloader/webview/IWebViewEvents.aidl delete mode 100644 api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebView.aidl delete mode 100644 api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebViewEvents.aidl create mode 100644 api/src/main/kotlin/app/revanced/manager/downloader/Constants.kt rename api/src/main/kotlin/app/revanced/manager/{plugin => }/downloader/Downloader.kt (80%) rename api/src/main/kotlin/app/revanced/manager/{plugin => }/downloader/Extensions.kt (83%) rename api/src/main/kotlin/app/revanced/manager/{plugin => }/downloader/Parcelables.kt (84%) rename api/src/main/kotlin/app/revanced/manager/{plugin => }/downloader/webview/API.kt (90%) rename api/src/main/kotlin/app/revanced/manager/{plugin => }/downloader/webview/WebViewActivity.kt (95%) delete mode 100644 api/src/main/kotlin/app/revanced/manager/plugin/downloader/Constants.kt rename app/src/main/java/app/revanced/manager/data/room/{plugins/TrustedDownloaderPlugin.kt => downloader/TrustedDownloader.kt} (64%) create mode 100644 app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloaderDao.kt delete mode 100644 app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPluginDao.kt rename app/src/main/java/app/revanced/manager/domain/repository/{DownloaderPluginRepository.kt => DownloaderRepository.kt} (52%) delete mode 100644 app/src/main/java/app/revanced/manager/network/downloader/DownloaderPluginState.kt create mode 100644 app/src/main/java/app/revanced/manager/network/downloader/DownloaderState.kt rename app/src/main/java/app/revanced/manager/network/downloader/{LoadedDownloaderPlugin.kt => LoadedDownloader.kt} (73%) diff --git a/README.md b/README.md index 91e70d8c..0400bd74 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ ReVanced Manager is an application that uses [ReVanced Patcher](https://github.c Some of the features ReVanced Manager provides are: -- ⬇️ **Download**: Automatically download apps using the ReVanced Manager downloader plugin system +- ⬇️ **Download**: Automatically download apps using the ReVanced Manager downloader system - 💉 **Patch**: Select and apply patches to any Android app - 🛠️ **Customize**: Manage patches, apps, signing, themes, updates, and many more settings diff --git a/api/api/api.api b/api/api/api.api index eccdb145..f5c8aefc 100644 --- a/api/api/api.api +++ b/api/api/api.api @@ -1,19 +1,19 @@ -public abstract interface class app/revanced/manager/plugin/downloader/BaseDownloadScope : app/revanced/manager/plugin/downloader/Scope { +public abstract interface class app/revanced/manager/downloader/BaseDownloadScope : app/revanced/manager/downloader/Scope { } -public final class app/revanced/manager/plugin/downloader/ConstantsKt { - public static final field PLUGIN_HOST_PERMISSION Ljava/lang/String; +public final class app/revanced/manager/downloader/ConstantsKt { + public static final field DOWNLOADER_HOST_PERMISSION Ljava/lang/String; } -public final class app/revanced/manager/plugin/downloader/DownloadUrl : android/os/Parcelable { +public final class app/revanced/manager/downloader/DownloadUrl : android/os/Parcelable { public static final field $stable I public static final field CREATOR Landroid/os/Parcelable$Creator; public fun (Ljava/lang/String;Ljava/util/Map;)V public synthetic fun (Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/util/Map; - public final fun copy (Ljava/lang/String;Ljava/util/Map;)Lapp/revanced/manager/plugin/downloader/DownloadUrl; - public static synthetic fun copy$default (Lapp/revanced/manager/plugin/downloader/DownloadUrl;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lapp/revanced/manager/plugin/downloader/DownloadUrl; + public final fun copy (Ljava/lang/String;Ljava/util/Map;)Lapp/revanced/manager/downloader/DownloadUrl; + public static synthetic fun copy$default (Lapp/revanced/manager/downloader/DownloadUrl;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lapp/revanced/manager/downloader/DownloadUrl; public final fun describeContents ()I public fun equals (Ljava/lang/Object;)Z public final fun getHeaders ()Ljava/util/Map; @@ -24,58 +24,61 @@ public final class app/revanced/manager/plugin/downloader/DownloadUrl : android/ public final fun writeToParcel (Landroid/os/Parcel;I)V } -public final class app/revanced/manager/plugin/downloader/DownloadUrl$Creator : android/os/Parcelable$Creator { +public final class app/revanced/manager/downloader/DownloadUrl$Creator : android/os/Parcelable$Creator { public fun ()V - public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/DownloadUrl; + public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/downloader/DownloadUrl; public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; - public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/DownloadUrl; + public final fun newArray (I)[Lapp/revanced/manager/downloader/DownloadUrl; public synthetic fun newArray (I)[Ljava/lang/Object; } -public final class app/revanced/manager/plugin/downloader/Downloader { +public final class app/revanced/manager/downloader/Downloader { public static final field $stable I } -public final class app/revanced/manager/plugin/downloader/DownloaderBuilder { +public final class app/revanced/manager/downloader/DownloaderBuilder { public static final field $stable I } -public final class app/revanced/manager/plugin/downloader/DownloaderKt { - public static final fun Downloader (Lkotlin/jvm/functions/Function1;)Lapp/revanced/manager/plugin/downloader/DownloaderBuilder; +public abstract interface annotation class app/revanced/manager/downloader/DownloaderHostApi : java/lang/annotation/Annotation { } -public final class app/revanced/manager/plugin/downloader/DownloaderScope : app/revanced/manager/plugin/downloader/Scope { +public final class app/revanced/manager/downloader/DownloaderKt { + public static final fun Downloader (Lkotlin/jvm/functions/Function1;)Lapp/revanced/manager/downloader/DownloaderBuilder; +} + +public final class app/revanced/manager/downloader/DownloaderScope : app/revanced/manager/downloader/Scope { public static final field $stable I public final fun download (Lkotlin/jvm/functions/Function3;)V public final fun get (Lkotlin/jvm/functions/Function4;)V + public fun getDownloaderPackageName ()Ljava/lang/String; public fun getHostPackageName ()Ljava/lang/String; - public fun getPluginPackageName ()Ljava/lang/String; public final fun useService (Landroid/content/Intent;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class app/revanced/manager/plugin/downloader/ExtensionsKt { - public static final fun download (Lapp/revanced/manager/plugin/downloader/DownloaderScope;Lkotlin/jvm/functions/Function4;)V +public final class app/revanced/manager/downloader/ExtensionsKt { + public static final fun download (Lapp/revanced/manager/downloader/DownloaderScope;Lkotlin/jvm/functions/Function4;)V } -public abstract interface class app/revanced/manager/plugin/downloader/GetScope : app/revanced/manager/plugin/downloader/Scope { +public abstract interface class app/revanced/manager/downloader/GetScope : app/revanced/manager/downloader/Scope { public abstract fun requestStartActivity (Landroid/content/Intent;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public abstract interface class app/revanced/manager/plugin/downloader/InputDownloadScope : app/revanced/manager/plugin/downloader/BaseDownloadScope { +public abstract interface class app/revanced/manager/downloader/InputDownloadScope : app/revanced/manager/downloader/BaseDownloadScope { } -public abstract interface class app/revanced/manager/plugin/downloader/OutputDownloadScope : app/revanced/manager/plugin/downloader/BaseDownloadScope { +public abstract interface class app/revanced/manager/downloader/OutputDownloadScope : app/revanced/manager/downloader/BaseDownloadScope { public abstract fun reportSize (JLkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class app/revanced/manager/plugin/downloader/Package : android/os/Parcelable { +public final class app/revanced/manager/downloader/Package : android/os/Parcelable { public static final field $stable I public static final field CREATOR Landroid/os/Parcelable$Creator; public fun (Ljava/lang/String;Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/manager/plugin/downloader/Package; - public static synthetic fun copy$default (Lapp/revanced/manager/plugin/downloader/Package;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lapp/revanced/manager/plugin/downloader/Package; + public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/manager/downloader/Package; + public static synthetic fun copy$default (Lapp/revanced/manager/downloader/Package;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lapp/revanced/manager/downloader/Package; public final fun describeContents ()I public fun equals (Ljava/lang/Object;)Z public final fun getName ()Ljava/lang/String; @@ -85,98 +88,95 @@ public final class app/revanced/manager/plugin/downloader/Package : android/os/P public final fun writeToParcel (Landroid/os/Parcel;I)V } -public final class app/revanced/manager/plugin/downloader/Package$Creator : android/os/Parcelable$Creator { +public final class app/revanced/manager/downloader/Package$Creator : android/os/Parcelable$Creator { public fun ()V - public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/Package; + public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/downloader/Package; public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; - public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/Package; + public final fun newArray (I)[Lapp/revanced/manager/downloader/Package; public synthetic fun newArray (I)[Ljava/lang/Object; } -public abstract interface annotation class app/revanced/manager/plugin/downloader/PluginHostApi : java/lang/annotation/Annotation { -} - -public abstract interface class app/revanced/manager/plugin/downloader/Scope { +public abstract interface class app/revanced/manager/downloader/Scope { + public abstract fun getDownloaderPackageName ()Ljava/lang/String; public abstract fun getHostPackageName ()Ljava/lang/String; - public abstract fun getPluginPackageName ()Ljava/lang/String; } -public abstract class app/revanced/manager/plugin/downloader/UserInteractionException : java/lang/Exception { +public abstract class app/revanced/manager/downloader/UserInteractionException : java/lang/Exception { public static final field $stable I public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V } -public abstract class app/revanced/manager/plugin/downloader/UserInteractionException$Activity : app/revanced/manager/plugin/downloader/UserInteractionException { +public abstract class app/revanced/manager/downloader/UserInteractionException$Activity : app/revanced/manager/downloader/UserInteractionException { public static final field $stable I public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V } -public final class app/revanced/manager/plugin/downloader/UserInteractionException$Activity$Cancelled : app/revanced/manager/plugin/downloader/UserInteractionException$Activity { +public final class app/revanced/manager/downloader/UserInteractionException$Activity$Cancelled : app/revanced/manager/downloader/UserInteractionException$Activity { public static final field $stable I } -public final class app/revanced/manager/plugin/downloader/UserInteractionException$Activity$NotCompleted : app/revanced/manager/plugin/downloader/UserInteractionException$Activity { +public final class app/revanced/manager/downloader/UserInteractionException$Activity$NotCompleted : app/revanced/manager/downloader/UserInteractionException$Activity { public static final field $stable I public final fun getIntent ()Landroid/content/Intent; public final fun getResultCode ()I } -public final class app/revanced/manager/plugin/downloader/UserInteractionException$RequestDenied : app/revanced/manager/plugin/downloader/UserInteractionException { +public final class app/revanced/manager/downloader/UserInteractionException$RequestDenied : app/revanced/manager/downloader/UserInteractionException { public static final field $stable I } -public final class app/revanced/manager/plugin/downloader/webview/APIKt { - public static final fun WebViewDownloader (Lkotlin/jvm/functions/Function4;)Lapp/revanced/manager/plugin/downloader/DownloaderBuilder; - public static final fun runWebView (Lapp/revanced/manager/plugin/downloader/GetScope;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +public final class app/revanced/manager/downloader/webview/APIKt { + public static final fun WebViewDownloader (Lkotlin/jvm/functions/Function4;)Lapp/revanced/manager/downloader/DownloaderBuilder; + public static final fun runWebView (Lapp/revanced/manager/downloader/GetScope;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public class app/revanced/manager/plugin/downloader/webview/IWebView$Default : app/revanced/manager/plugin/downloader/webview/IWebView { +public class app/revanced/manager/downloader/webview/IWebView$Default : app/revanced/manager/downloader/webview/IWebView { public fun ()V public fun asBinder ()Landroid/os/IBinder; public fun finish ()V public fun load (Ljava/lang/String;)V } -public abstract class app/revanced/manager/plugin/downloader/webview/IWebView$Stub : android/os/Binder, app/revanced/manager/plugin/downloader/webview/IWebView { +public abstract class app/revanced/manager/downloader/webview/IWebView$Stub : android/os/Binder, app/revanced/manager/downloader/webview/IWebView { public fun ()V public fun asBinder ()Landroid/os/IBinder; - public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/manager/plugin/downloader/webview/IWebView; + public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/manager/downloader/webview/IWebView; public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z } -public class app/revanced/manager/plugin/downloader/webview/IWebViewEvents$Default : app/revanced/manager/plugin/downloader/webview/IWebViewEvents { +public class app/revanced/manager/downloader/webview/IWebViewEvents$Default : app/revanced/manager/downloader/webview/IWebViewEvents { public fun ()V public fun asBinder ()Landroid/os/IBinder; public fun download (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V public fun pageLoad (Ljava/lang/String;)V - public fun ready (Lapp/revanced/manager/plugin/downloader/webview/IWebView;)V + public fun ready (Lapp/revanced/manager/downloader/webview/IWebView;)V } -public abstract class app/revanced/manager/plugin/downloader/webview/IWebViewEvents$Stub : android/os/Binder, app/revanced/manager/plugin/downloader/webview/IWebViewEvents { +public abstract class app/revanced/manager/downloader/webview/IWebViewEvents$Stub : android/os/Binder, app/revanced/manager/downloader/webview/IWebViewEvents { public fun ()V public fun asBinder ()Landroid/os/IBinder; - public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/manager/plugin/downloader/webview/IWebViewEvents; + public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/manager/downloader/webview/IWebViewEvents; public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z } -public final class app/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters$Creator : android/os/Parcelable$Creator { +public final class app/revanced/manager/downloader/webview/WebViewActivity$Parameters$Creator : android/os/Parcelable$Creator { public fun ()V - public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters; + public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/downloader/webview/WebViewActivity$Parameters; public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; - public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters; + public final fun newArray (I)[Lapp/revanced/manager/downloader/webview/WebViewActivity$Parameters; public synthetic fun newArray (I)[Ljava/lang/Object; } -public abstract interface class app/revanced/manager/plugin/downloader/webview/WebViewCallbackScope : app/revanced/manager/plugin/downloader/Scope { +public abstract interface class app/revanced/manager/downloader/webview/WebViewCallbackScope : app/revanced/manager/downloader/Scope { public abstract fun finish (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun load (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class app/revanced/manager/plugin/downloader/webview/WebViewScope : app/revanced/manager/plugin/downloader/Scope { +public final class app/revanced/manager/downloader/webview/WebViewScope : app/revanced/manager/downloader/Scope { public static final field $stable I public final fun download (Lkotlin/jvm/functions/Function5;)V + public fun getDownloaderPackageName ()Ljava/lang/String; public fun getHostPackageName ()Ljava/lang/String; - public fun getPluginPackageName ()Ljava/lang/String; public final fun pageLoad (Lkotlin/jvm/functions/Function3;)V } diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 4e4392af..30ab7c80 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { } android { - namespace = "app.revanced.manager.plugin.downloader" + namespace = "app.revanced.manager.downloader" compileSdk = 35 defaultConfig { @@ -52,7 +52,7 @@ android { } apiValidation { - nonPublicMarkers += "app.revanced.manager.plugin.downloader.PluginHostApi" + nonPublicMarkers += "app.revanced.manager.downloader.DownloaderHostApi" } publishing { diff --git a/api/src/main/aidl/app/revanced/manager/downloader/webview/IWebView.aidl b/api/src/main/aidl/app/revanced/manager/downloader/webview/IWebView.aidl new file mode 100644 index 00000000..eb5f05ae --- /dev/null +++ b/api/src/main/aidl/app/revanced/manager/downloader/webview/IWebView.aidl @@ -0,0 +1,8 @@ +// IWebView.aidl +package app.revanced.manager.downloader.webview; + +@JavaPassthrough(annotation="@app.revanced.manager.downloader.DownloaderHostApi") +oneway interface IWebView { + void load(String url); + void finish(); +} \ No newline at end of file diff --git a/api/src/main/aidl/app/revanced/manager/downloader/webview/IWebViewEvents.aidl b/api/src/main/aidl/app/revanced/manager/downloader/webview/IWebViewEvents.aidl new file mode 100644 index 00000000..fc3c5b66 --- /dev/null +++ b/api/src/main/aidl/app/revanced/manager/downloader/webview/IWebViewEvents.aidl @@ -0,0 +1,11 @@ +// IWebViewEvents.aidl +package app.revanced.manager.downloader.webview; + +import app.revanced.manager.downloader.webview.IWebView; + +@JavaPassthrough(annotation="@app.revanced.manager.downloader.DownloaderHostApi") +oneway interface IWebViewEvents { + void ready(IWebView iface); + void pageLoad(String url); + void download(String url, String mimetype, String userAgent); +} \ No newline at end of file diff --git a/api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebView.aidl b/api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebView.aidl deleted file mode 100644 index d657fcc3..00000000 --- a/api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebView.aidl +++ /dev/null @@ -1,8 +0,0 @@ -// IWebView.aidl -package app.revanced.manager.plugin.downloader.webview; - -@JavaPassthrough(annotation="@app.revanced.manager.plugin.downloader.PluginHostApi") -oneway interface IWebView { - void load(String url); - void finish(); -} \ No newline at end of file diff --git a/api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebViewEvents.aidl b/api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebViewEvents.aidl deleted file mode 100644 index b0237de2..00000000 --- a/api/src/main/aidl/app/revanced/manager/plugin/downloader/webview/IWebViewEvents.aidl +++ /dev/null @@ -1,11 +0,0 @@ -// IWebViewEvents.aidl -package app.revanced.manager.plugin.downloader.webview; - -import app.revanced.manager.plugin.downloader.webview.IWebView; - -@JavaPassthrough(annotation="@app.revanced.manager.plugin.downloader.PluginHostApi") -oneway interface IWebViewEvents { - void ready(IWebView iface); - void pageLoad(String url); - void download(String url, String mimetype, String userAgent); -} \ No newline at end of file diff --git a/api/src/main/kotlin/app/revanced/manager/downloader/Constants.kt b/api/src/main/kotlin/app/revanced/manager/downloader/Constants.kt new file mode 100644 index 00000000..4f96167e --- /dev/null +++ b/api/src/main/kotlin/app/revanced/manager/downloader/Constants.kt @@ -0,0 +1,7 @@ +package app.revanced.manager.downloader + +/** + * The permission ID of the special downloader host permission. Only ReVanced Manager will have this permission. + * Downloader UI activities and internal services can be protected using this permission. + */ +const val DOWNLOADER_HOST_PERMISSION = "app.revanced.manager.permission.DOWNLOADER_HOST" \ No newline at end of file diff --git a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Downloader.kt b/api/src/main/kotlin/app/revanced/manager/downloader/Downloader.kt similarity index 80% rename from api/src/main/kotlin/app/revanced/manager/plugin/downloader/Downloader.kt rename to api/src/main/kotlin/app/revanced/manager/downloader/Downloader.kt index bf0a219b..57fc17db 100644 --- a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Downloader.kt +++ b/api/src/main/kotlin/app/revanced/manager/downloader/Downloader.kt @@ -1,4 +1,4 @@ -package app.revanced.manager.plugin.downloader +package app.revanced.manager.downloader import android.content.ComponentName import android.content.Context @@ -15,10 +15,10 @@ import kotlin.coroutines.suspendCoroutine @RequiresOptIn( level = RequiresOptIn.Level.ERROR, - message = "This API is only intended for plugin hosts, don't use it in a plugin.", + message = "This API is only intended for downloader hosts, don't use it in a downloader.", ) @Retention(AnnotationRetention.BINARY) -annotation class PluginHostApi +annotation class DownloaderHostApi /** * The base interface for all DSL scopes. @@ -30,9 +30,9 @@ interface Scope { val hostPackageName: String /** - * The package name of the plugin. + * The package name of the downloader. */ - val pluginPackageName: String + val downloaderPackageName: String } /** @@ -43,7 +43,7 @@ interface GetScope : Scope { * Ask the user to perform some required interaction in the activity specified by the provided [Intent]. * This function returns normally with the resulting [Intent] when the activity finishes with code [Activity.RESULT_OK]. * - * @throws UserInteractionException.RequestDenied User decided to skip this plugin. + * @throws UserInteractionException.RequestDenied User decided to skip this downloader. * @throws UserInteractionException.Activity.Cancelled The activity was cancelled. * @throws UserInteractionException.Activity.NotCompleted The activity finished with an unknown result code. */ @@ -67,14 +67,14 @@ class DownloaderScope internal constructor( private val scopeImpl: Scope, internal val context: Context ) : Scope by scopeImpl { - // Returning an InputStream is the primary way for plugins to implement the download function, but we also want to offer an OutputStream API since using InputStream might not be convenient in all cases. - // It is much easier to implement the main InputStream API on top of OutputStreams compared to doing it the other way around, which is why we are using OutputStream here. This detail is not visible to plugins. + // Returning an InputStream is the primary way for downloader to implement the download function, but we also want to offer an OutputStream API since using InputStream might not be convenient in all cases. + // It is much easier to implement the main InputStream API on top of OutputStreams compared to doing it the other way around, which is why we are using OutputStream here. This detail is not visible to downloader. internal var download: (suspend OutputDownloadScope.(T, OutputStream) -> Unit)? = null internal var get: (suspend GetScope.(String, String?) -> GetResult?)? = null private val inputDownloadScopeImpl = object : InputDownloadScope, Scope by scopeImpl {} /** - * Define the download block of the plugin. + * Define the download block of the downloader. */ fun download(block: suspend InputDownloadScope.(data: T) -> DownloadResult) { download = { app, outputStream -> @@ -88,7 +88,7 @@ class DownloaderScope internal constructor( } /** - * Define the get block of the plugin. + * Define the get block of the downloader. * The block should return null if the app cannot be found. The version in the result must match the version argument unless it is null. */ fun get(block: suspend GetScope.(packageName: String, version: String?) -> GetResult?) { @@ -123,7 +123,7 @@ class DownloaderScope internal constructor( } class DownloaderBuilder internal constructor(private val block: DownloaderScope.() -> Unit) { - @PluginHostApi + @DownloaderHostApi fun build(scopeImpl: Scope, context: Context) = with(DownloaderScope(scopeImpl, context)) { block() @@ -136,12 +136,12 @@ class DownloaderBuilder internal constructor(private val block: } class Downloader internal constructor( - @property:PluginHostApi val get: suspend GetScope.(packageName: String, version: String?) -> GetResult?, - @property:PluginHostApi val download: suspend OutputDownloadScope.(data: T, outputStream: OutputStream) -> Unit + @property:DownloaderHostApi val get: suspend GetScope.(packageName: String, version: String?) -> GetResult?, + @property:DownloaderHostApi val download: suspend OutputDownloadScope.(data: T, outputStream: OutputStream) -> Unit ) /** - * Define a downloader plugin. + * Define a downloader. */ fun Downloader(block: DownloaderScope.() -> Unit) = DownloaderBuilder(block) @@ -149,17 +149,17 @@ fun Downloader(block: DownloaderScope.() -> Unit) = Download * @see GetScope.requestStartActivity */ sealed class UserInteractionException(message: String) : Exception(message) { - class RequestDenied @PluginHostApi constructor() : + class RequestDenied @DownloaderHostApi constructor() : UserInteractionException("Request denied by user") sealed class Activity(message: String) : UserInteractionException(message) { - class Cancelled @PluginHostApi constructor() : Activity("Interaction cancelled") + class Cancelled @DownloaderHostApi constructor() : Activity("Interaction cancelled") /** * @param resultCode The result code of the activity. * @param intent The [Intent] of the activity. */ - class NotCompleted @PluginHostApi constructor(val resultCode: Int, val intent: Intent?) : + class NotCompleted @DownloaderHostApi constructor(val resultCode: Int, val intent: Intent?) : Activity("Unexpected activity result code: $resultCode") } } \ No newline at end of file diff --git a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Extensions.kt b/api/src/main/kotlin/app/revanced/manager/downloader/Extensions.kt similarity index 83% rename from api/src/main/kotlin/app/revanced/manager/plugin/downloader/Extensions.kt rename to api/src/main/kotlin/app/revanced/manager/downloader/Extensions.kt index a1e6bf79..e5a56327 100644 --- a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Extensions.kt +++ b/api/src/main/kotlin/app/revanced/manager/downloader/Extensions.kt @@ -1,4 +1,4 @@ -package app.revanced.manager.plugin.downloader +package app.revanced.manager.downloader import android.app.Activity import android.app.Service @@ -28,7 +28,7 @@ fun DownloaderScope.download(block: suspend OutputDownloadSc */ suspend inline fun GetScope.requestStartActivity() = requestStartActivity( - Intent().apply { setClassName(pluginPackageName, ACTIVITY::class.qualifiedName!!) } + Intent().apply { setClassName(downloaderPackageName, ACTIVITY::class.qualifiedName!!) } ) /** @@ -38,5 +38,5 @@ suspend inline fun GetScope.requestStartActivity() suspend inline fun DownloaderScope<*>.useService( noinline block: suspend (IBinder) -> R ) = useService( - Intent().apply { setClassName(pluginPackageName, SERVICE::class.qualifiedName!!) }, block + Intent().apply { setClassName(downloaderPackageName, SERVICE::class.qualifiedName!!) }, block ) \ No newline at end of file diff --git a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Parcelables.kt b/api/src/main/kotlin/app/revanced/manager/downloader/Parcelables.kt similarity index 84% rename from api/src/main/kotlin/app/revanced/manager/plugin/downloader/Parcelables.kt rename to api/src/main/kotlin/app/revanced/manager/downloader/Parcelables.kt index 414ad889..10771d63 100644 --- a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Parcelables.kt +++ b/api/src/main/kotlin/app/revanced/manager/downloader/Parcelables.kt @@ -1,4 +1,4 @@ -package app.revanced.manager.plugin.downloader +package app.revanced.manager.downloader import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -7,7 +7,7 @@ import java.net.URI /** * A simple parcelable data class for storing a package name and version. - * This can be used as the data type for plugins that only need a name and version to implement their [DownloaderScope.download] function. + * This can be used as the data type for downloader that only need a name and version to implement their [DownloaderScope.download] function. * * @param name The package name. * @param version The version. diff --git a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/webview/API.kt b/api/src/main/kotlin/app/revanced/manager/downloader/webview/API.kt similarity index 90% rename from api/src/main/kotlin/app/revanced/manager/plugin/downloader/webview/API.kt rename to api/src/main/kotlin/app/revanced/manager/downloader/webview/API.kt index 2e5034e1..1f4f4313 100644 --- a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/webview/API.kt +++ b/api/src/main/kotlin/app/revanced/manager/downloader/webview/API.kt @@ -1,12 +1,14 @@ -package app.revanced.manager.plugin.downloader.webview +package app.revanced.manager.downloader.webview import android.content.Intent -import app.revanced.manager.plugin.downloader.DownloadUrl -import app.revanced.manager.plugin.downloader.DownloaderScope -import app.revanced.manager.plugin.downloader.GetScope -import app.revanced.manager.plugin.downloader.Scope -import app.revanced.manager.plugin.downloader.Downloader -import app.revanced.manager.plugin.downloader.PluginHostApi +import app.revanced.manager.downloader.DownloadUrl +import app.revanced.manager.downloader.DownloaderScope +import app.revanced.manager.downloader.GetScope +import app.revanced.manager.downloader.Scope +import app.revanced.manager.downloader.Downloader +import app.revanced.manager.downloader.DownloaderHostApi +import app.revanced.manager.downloader.webview.IWebView +import app.revanced.manager.downloader.webview.IWebViewEvents import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -32,7 +34,7 @@ interface WebViewCallbackScope : Scope { suspend fun load(url: String) } -@OptIn(PluginHostApi::class) +@OptIn(DownloaderHostApi::class) class WebViewScope internal constructor( coroutineScope: CoroutineScope, private val scopeImpl: Scope, @@ -110,7 +112,7 @@ private value class Container(val value: U) * @param title The string displayed in the action bar. * @param block The control block. */ -@OptIn(PluginHostApi::class) +@OptIn(DownloaderHostApi::class) suspend fun GetScope.runWebView( title: String, block: suspend WebViewScope.() -> InitialUrl diff --git a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/webview/WebViewActivity.kt b/api/src/main/kotlin/app/revanced/manager/downloader/webview/WebViewActivity.kt similarity index 95% rename from api/src/main/kotlin/app/revanced/manager/plugin/downloader/webview/WebViewActivity.kt rename to api/src/main/kotlin/app/revanced/manager/downloader/webview/WebViewActivity.kt index aff01337..318719ec 100644 --- a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/webview/WebViewActivity.kt +++ b/api/src/main/kotlin/app/revanced/manager/downloader/webview/WebViewActivity.kt @@ -1,4 +1,4 @@ -package app.revanced.manager.plugin.downloader.webview +package app.revanced.manager.downloader.webview import android.annotation.SuppressLint import android.os.Bundle @@ -20,15 +20,15 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.viewModelScope -import app.revanced.manager.plugin.downloader.PluginHostApi -import app.revanced.manager.plugin.downloader.R +import app.revanced.manager.downloader.DownloaderHostApi +import app.revanced.manager.downloader.R import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize -@OptIn(PluginHostApi::class) -@PluginHostApi +@OptIn(DownloaderHostApi::class) +@DownloaderHostApi class WebViewActivity : ComponentActivity() { @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { @@ -110,7 +110,7 @@ class WebViewActivity : ComponentActivity() { } } -@OptIn(PluginHostApi::class) +@OptIn(DownloaderHostApi::class) internal class WebViewModel : ViewModel() { init { CookieManager.getInstance().apply { diff --git a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Constants.kt b/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Constants.kt deleted file mode 100644 index 469daaae..00000000 --- a/api/src/main/kotlin/app/revanced/manager/plugin/downloader/Constants.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.manager.plugin.downloader - -/** - * The permission ID of the special plugin host permission. Only ReVanced Manager will have this permission. - * Plugin UI activities and internal services can be protected using this permission. - */ -const val PLUGIN_HOST_PERMISSION = "app.revanced.manager.permission.PLUGIN_HOST" \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 2fc38c4f..3bb45d0e 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,7 +1,7 @@ -dontobfuscate -keep class app.revanced.manager.patcher.runtime.process.* { *; } --keep class app.revanced.manager.plugin.** { *; } +-keep class app.revanced.manager.downloader.** { *; } -keep class app.revanced.patcher.** { *; } -keep class com.android.tools.smali.** { *; } -keep class kotlin.** { *; } diff --git a/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json b/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json index fd83a51e..a6e13c49 100644 --- a/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json +++ b/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "d0119047505da435972c5247181de675", + "identityHash": "9a937123afc782978d185d00c35d20e0", "entities": [ { "tableName": "patch_bundles", @@ -21,10 +21,9 @@ "notNull": true }, { - "fieldPath": "version", + "fieldPath": "versionHash", "columnName": "version", - "affinity": "TEXT", - "notNull": false + "affinity": "TEXT" }, { "fieldPath": "source", @@ -44,9 +43,7 @@ "columnNames": [ "uid" ] - }, - "indices": [], - "foreignKeys": [] + } }, { "tableName": "patch_selections", @@ -127,7 +124,6 @@ "patch_name" ] }, - "indices": [], "foreignKeys": [ { "table": "patch_selections", @@ -177,9 +173,7 @@ "package_name", "version" ] - }, - "indices": [], - "foreignKeys": [] + } }, { "tableName": "installed_app", @@ -215,9 +209,7 @@ "columnNames": [ "current_package_name" ] - }, - "indices": [], - "foreignKeys": [] + } }, { "tableName": "applied_patch", @@ -378,7 +370,6 @@ "key" ] }, - "indices": [], "foreignKeys": [ { "table": "option_groups", @@ -394,7 +385,7 @@ ] }, { - "tableName": "trusted_downloader_plugins", + "tableName": "trusted_downloader", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `signature` BLOB NOT NULL, PRIMARY KEY(`package_name`))", "fields": [ { @@ -415,15 +406,12 @@ "columnNames": [ "package_name" ] - }, - "indices": [], - "foreignKeys": [] + } } ], - "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd0119047505da435972c5247181de675')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9a937123afc782978d185d00c35d20e0')" ] } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f6364fbc..4bbfdc71 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,13 +3,13 @@ xmlns:tools="http://schemas.android.com/tools"> - + @@ -49,7 +49,7 @@ - + diff --git a/app/src/main/java/app/revanced/manager/ManagerApplication.kt b/app/src/main/java/app/revanced/manager/ManagerApplication.kt index b5dec19b..80c256b6 100644 --- a/app/src/main/java/app/revanced/manager/ManagerApplication.kt +++ b/app/src/main/java/app/revanced/manager/ManagerApplication.kt @@ -7,7 +7,7 @@ import android.util.Log import app.revanced.manager.data.platform.Filesystem import app.revanced.manager.di.* import app.revanced.manager.domain.manager.PreferencesManager -import app.revanced.manager.domain.repository.DownloaderPluginRepository +import app.revanced.manager.domain.repository.DownloaderRepository import app.revanced.manager.domain.repository.PatchBundleRepository import app.revanced.manager.util.tag import kotlinx.coroutines.Dispatchers @@ -29,7 +29,7 @@ class ManagerApplication : Application() { private val scope = MainScope() private val prefs: PreferencesManager by inject() private val patchBundleRepository: PatchBundleRepository by inject() - private val downloaderPluginRepository: DownloaderPluginRepository by inject() + private val downloaderRepository: DownloaderRepository by inject() private val fs: Filesystem by inject() override fun onCreate() { @@ -70,7 +70,7 @@ class ManagerApplication : Application() { prefs.preload() } scope.launch(Dispatchers.Default) { - downloaderPluginRepository.reload() + downloaderRepository.reload() } scope.launch(Dispatchers.Default) { with(patchBundleRepository) { diff --git a/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt b/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt index 403bd1cf..65200333 100644 --- a/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt +++ b/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt @@ -16,12 +16,12 @@ import app.revanced.manager.data.room.bundles.PatchBundleEntity import app.revanced.manager.data.room.options.Option import app.revanced.manager.data.room.options.OptionDao import app.revanced.manager.data.room.options.OptionGroup -import app.revanced.manager.data.room.plugins.TrustedDownloaderPlugin -import app.revanced.manager.data.room.plugins.TrustedDownloaderPluginDao +import app.revanced.manager.data.room.downloader.TrustedDownloader +import app.revanced.manager.data.room.downloader.TrustedDownloaderDao import kotlin.random.Random @Database( - entities = [PatchBundleEntity::class, PatchSelection::class, SelectedPatch::class, DownloadedApp::class, InstalledApp::class, AppliedPatch::class, OptionGroup::class, Option::class, TrustedDownloaderPlugin::class], + entities = [PatchBundleEntity::class, PatchSelection::class, SelectedPatch::class, DownloadedApp::class, InstalledApp::class, AppliedPatch::class, OptionGroup::class, Option::class, TrustedDownloader::class], version = 1 ) @TypeConverters(Converters::class) @@ -31,7 +31,7 @@ abstract class AppDatabase : RoomDatabase() { abstract fun downloadedAppDao(): DownloadedAppDao abstract fun installedAppDao(): InstalledAppDao abstract fun optionDao(): OptionDao - abstract fun trustedDownloaderPluginDao(): TrustedDownloaderPluginDao + abstract fun trustedDownloaderDao(): TrustedDownloaderDao companion object { fun generateUid() = Random.Default.nextInt() diff --git a/app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPlugin.kt b/app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloader.kt similarity index 64% rename from app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPlugin.kt rename to app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloader.kt index 8e1b9c39..98fb465f 100644 --- a/app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPlugin.kt +++ b/app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloader.kt @@ -1,11 +1,11 @@ -package app.revanced.manager.data.room.plugins +package app.revanced.manager.data.room.downloader import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -@Entity(tableName = "trusted_downloader_plugins") -class TrustedDownloaderPlugin( +@Entity(tableName = "trusted_downloader") +class TrustedDownloader( @PrimaryKey @ColumnInfo(name = "package_name") val packageName: String, @ColumnInfo(name = "signature") val signature: ByteArray ) \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloaderDao.kt b/app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloaderDao.kt new file mode 100644 index 00000000..498d44cd --- /dev/null +++ b/app/src/main/java/app/revanced/manager/data/room/downloader/TrustedDownloaderDao.kt @@ -0,0 +1,22 @@ +package app.revanced.manager.data.room.downloader + +import androidx.room.Dao +import androidx.room.Query +import androidx.room.Transaction +import androidx.room.Upsert + +@Dao +interface TrustedDownloaderDao { + @Query("SELECT signature FROM trusted_downloader WHERE package_name = :packageName") + suspend fun getTrustedSignature(packageName: String): ByteArray? + + @Upsert + suspend fun upsertTrust(downloader: TrustedDownloader) + + @Query("DELETE FROM trusted_downloader WHERE package_name = :packageName") + suspend fun remove(packageName: String) + + @Transaction + @Query("DELETE FROM trusted_downloader WHERE package_name IN (:packageNames)") + suspend fun removeAll(packageNames: Set) +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPluginDao.kt b/app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPluginDao.kt deleted file mode 100644 index ad1845f7..00000000 --- a/app/src/main/java/app/revanced/manager/data/room/plugins/TrustedDownloaderPluginDao.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.manager.data.room.plugins - -import androidx.room.Dao -import androidx.room.Query -import androidx.room.Transaction -import androidx.room.Upsert - -@Dao -interface TrustedDownloaderPluginDao { - @Query("SELECT signature FROM trusted_downloader_plugins WHERE package_name = :packageName") - suspend fun getTrustedSignature(packageName: String): ByteArray? - - @Upsert - suspend fun upsertTrust(plugin: TrustedDownloaderPlugin) - - @Query("DELETE FROM trusted_downloader_plugins WHERE package_name = :packageName") - suspend fun remove(packageName: String) - - @Transaction - @Query("DELETE FROM trusted_downloader_plugins WHERE package_name IN (:packageNames)") - suspend fun removeAll(packageNames: Set) -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/di/RepositoryModule.kt b/app/src/main/java/app/revanced/manager/di/RepositoryModule.kt index 5fce77ec..ff5a69c2 100644 --- a/app/src/main/java/app/revanced/manager/di/RepositoryModule.kt +++ b/app/src/main/java/app/revanced/manager/di/RepositoryModule.kt @@ -21,7 +21,7 @@ val repositoryModule = module { // It is best to load patch bundles ASAP createdAtStart() } - singleOf(::DownloaderPluginRepository) + singleOf(::DownloaderRepository) singleOf(::WorkerRepository) singleOf(::DownloadedAppRepository) singleOf(::InstalledAppRepository) diff --git a/app/src/main/java/app/revanced/manager/domain/manager/PreferencesManager.kt b/app/src/main/java/app/revanced/manager/domain/manager/PreferencesManager.kt index c629370d..a4aab78b 100644 --- a/app/src/main/java/app/revanced/manager/domain/manager/PreferencesManager.kt +++ b/app/src/main/java/app/revanced/manager/domain/manager/PreferencesManager.kt @@ -31,7 +31,7 @@ class PreferencesManager( val disableUniversalPatchCheck = booleanPreference("disable_patch_universal_check", false) val suggestedVersionSafeguard = booleanPreference("suggested_version_safeguard", true) - val acknowledgedDownloaderPlugins = stringSetPreference("acknowledged_downloader_plugins", emptySet()) + val acknowledgedDownloader = stringSetPreference("acknowledged_downloader", emptySet()) val showDeveloperSettings = booleanPreference("show_developer_settings", context.isDebuggable) diff --git a/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt b/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt index e8536de1..f80ad6d4 100644 --- a/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt +++ b/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt @@ -6,8 +6,8 @@ import android.os.Parcelable import app.revanced.manager.data.room.AppDatabase import app.revanced.manager.data.room.AppDatabase.Companion.generateUid import app.revanced.manager.data.room.apps.downloaded.DownloadedApp -import app.revanced.manager.network.downloader.LoadedDownloaderPlugin -import app.revanced.manager.plugin.downloader.OutputDownloadScope +import app.revanced.manager.network.downloader.LoadedDownloader +import app.revanced.manager.downloader.OutputDownloadScope import app.revanced.manager.util.PM import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.channelFlow @@ -36,7 +36,7 @@ class DownloadedAppRepository( private fun getApkFileForDir(directory: File) = directory.listFiles()!!.first() suspend fun download( - plugin: LoadedDownloaderPlugin, + downloader: LoadedDownloader, data: Parcelable, expectedPackageName: String, expectedVersion: String?, @@ -55,7 +55,7 @@ class DownloadedAppRepository( channelFlow { val scope = object : OutputDownloadScope { - override val pluginPackageName = plugin.packageName + override val downloaderPackageName = downloader.packageName override val hostPackageName = app.packageName override suspend fun reportSize(size: Long) { require(size > 0) { "Size must be greater than zero" } @@ -87,7 +87,7 @@ class DownloadedAppRepository( ) } } - plugin.download(scope, data, stream) + downloader.download(scope, data, stream) } } .conflate() diff --git a/app/src/main/java/app/revanced/manager/domain/repository/DownloaderPluginRepository.kt b/app/src/main/java/app/revanced/manager/domain/repository/DownloaderRepository.kt similarity index 52% rename from app/src/main/java/app/revanced/manager/domain/repository/DownloaderPluginRepository.kt rename to app/src/main/java/app/revanced/manager/domain/repository/DownloaderRepository.kt index 791a09ac..e8421ee6 100644 --- a/app/src/main/java/app/revanced/manager/domain/repository/DownloaderPluginRepository.kt +++ b/app/src/main/java/app/revanced/manager/domain/repository/DownloaderRepository.kt @@ -5,14 +5,14 @@ import android.content.pm.PackageManager import android.os.Parcelable import android.util.Log import app.revanced.manager.data.room.AppDatabase -import app.revanced.manager.data.room.plugins.TrustedDownloaderPlugin +import app.revanced.manager.data.room.downloader.TrustedDownloader import app.revanced.manager.domain.manager.PreferencesManager -import app.revanced.manager.network.downloader.DownloaderPluginState -import app.revanced.manager.network.downloader.LoadedDownloaderPlugin +import app.revanced.manager.network.downloader.DownloaderState +import app.revanced.manager.network.downloader.LoadedDownloader import app.revanced.manager.network.downloader.ParceledDownloaderData -import app.revanced.manager.plugin.downloader.DownloaderBuilder -import app.revanced.manager.plugin.downloader.PluginHostApi -import app.revanced.manager.plugin.downloader.Scope +import app.revanced.manager.downloader.DownloaderBuilder +import app.revanced.manager.downloader.DownloaderHostApi +import app.revanced.manager.downloader.Scope import app.revanced.manager.util.PM import app.revanced.manager.util.tag import dalvik.system.PathClassLoader @@ -25,74 +25,74 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext import java.lang.reflect.Modifier -@OptIn(PluginHostApi::class) -class DownloaderPluginRepository( +@OptIn(DownloaderHostApi::class) +class DownloaderRepository( private val pm: PM, private val prefs: PreferencesManager, private val app: Application, db: AppDatabase ) { - private val trustDao = db.trustedDownloaderPluginDao() - private val _pluginStates = MutableStateFlow(emptyMap()) - val pluginStates = _pluginStates.asStateFlow() - val loadedPluginsFlow = pluginStates.map { states -> - states.values.filterIsInstance().map { it.plugin } + private val trustDao = db.trustedDownloaderDao() + private val _downloaderStates = MutableStateFlow(emptyMap()) + val downloaderStates = _downloaderStates.asStateFlow() + val loadedDownloaderFlow = downloaderStates.map { states -> + states.values.filterIsInstance().map { it.downloader } } - private val acknowledgedDownloaderPlugins = prefs.acknowledgedDownloaderPlugins - private val installedPluginPackageNames = MutableStateFlow(emptySet()) - val newPluginPackageNames = combine( - installedPluginPackageNames, - acknowledgedDownloaderPlugins.flow + private val acknowledgedDownloader = prefs.acknowledgedDownloader + private val installedDownloaderPackageNames = MutableStateFlow(emptySet()) + val newDownloaderPackageNames = combine( + installedDownloaderPackageNames, + acknowledgedDownloader.flow ) { installed, acknowledged -> installed subtract acknowledged } suspend fun reload() { - val plugins = + val downloader = withContext(Dispatchers.IO) { - pm.getPackagesWithFeature(PLUGIN_FEATURE) - .associate { it.packageName to loadPlugin(it.packageName) } + pm.getPackagesWithFeature(DOWNLOADER_FEATURE) + .associate { it.packageName to loadDownloader(it.packageName) } } - _pluginStates.value = plugins - installedPluginPackageNames.value = plugins.keys + _downloaderStates.value = downloader + installedDownloaderPackageNames.value = downloader.keys - val acknowledgedPlugins = acknowledgedDownloaderPlugins.get() - val uninstalledPlugins = acknowledgedPlugins subtract installedPluginPackageNames.value - if (uninstalledPlugins.isNotEmpty()) { - Log.d(tag, "Uninstalled plugins: ${uninstalledPlugins.joinToString(", ")}") - acknowledgedDownloaderPlugins.update(acknowledgedPlugins subtract uninstalledPlugins) - trustDao.removeAll(uninstalledPlugins) + val acknowledgedDownloader = this@DownloaderRepository.acknowledgedDownloader.get() + val uninstalledDownloader = acknowledgedDownloader subtract installedDownloaderPackageNames.value + if (uninstalledDownloader.isNotEmpty()) { + Log.d(tag, "Uninstalled downloader: ${uninstalledDownloader.joinToString(", ")}") + this@DownloaderRepository.acknowledgedDownloader.update(acknowledgedDownloader subtract uninstalledDownloader) + trustDao.removeAll(uninstalledDownloader) } } - fun unwrapParceledData(data: ParceledDownloaderData): Pair { - val plugin = - (_pluginStates.value[data.pluginPackageName] as? DownloaderPluginState.Loaded)?.plugin - ?: throw Exception("Downloader plugin with name ${data.pluginPackageName} is not available") + fun unwrapParceledData(data: ParceledDownloaderData): Pair { + val downloader = + (_downloaderStates.value[data.downloaderPackageName] as? DownloaderState.Loaded)?.downloader + ?: throw Exception("Downloader with name ${data.downloaderPackageName} is not available") - return plugin to data.unwrapWith(plugin) + return downloader to data.unwrapWith(downloader) } - private suspend fun loadPlugin(packageName: String): DownloaderPluginState { + private suspend fun loadDownloader(packageName: String): DownloaderState { try { - if (!verify(packageName)) return DownloaderPluginState.Untrusted + if (!verify(packageName)) return DownloaderState.Untrusted } catch (e: CancellationException) { throw e } catch (e: Exception) { - Log.e(tag, "Got exception while verifying plugin $packageName", e) - return DownloaderPluginState.Failed(e) + Log.e(tag, "Got exception while verifying downloader $packageName", e) + return DownloaderState.Failed(e) } return try { val packageInfo = pm.getPackageInfo(packageName, flags = PackageManager.GET_META_DATA)!! - val className = packageInfo.applicationInfo!!.metaData.getString(METADATA_PLUGIN_CLASS) - ?: throw Exception("Missing metadata attribute $METADATA_PLUGIN_CLASS") + val className = packageInfo.applicationInfo!!.metaData.getString(METADATA_DOWNLOADER_CLASS) + ?: throw Exception("Missing metadata attribute $METADATA_DOWNLOADER_CLASS") val classLoader = PathClassLoader(packageInfo.applicationInfo!!.sourceDir, app.classLoader) - val pluginContext = app.createPackageContext(packageName, 0) + val downloaderContext = app.createPackageContext(packageName, 0) val downloader = classLoader .loadClass(className) @@ -100,13 +100,13 @@ class DownloaderPluginRepository( .build( scopeImpl = object : Scope { override val hostPackageName = app.packageName - override val pluginPackageName = pluginContext.packageName + override val downloaderPackageName = downloaderContext.packageName }, - context = pluginContext + context = downloaderContext ) - DownloaderPluginState.Loaded( - LoadedDownloaderPlugin( + DownloaderState.Loaded( + LoadedDownloader( packageName, with(pm) { packageInfo.label() }, packageInfo.versionName!!, @@ -118,14 +118,14 @@ class DownloaderPluginRepository( } catch (e: CancellationException) { throw e } catch (t: Throwable) { - Log.e(tag, "Failed to load plugin $packageName", t) - DownloaderPluginState.Failed(t) + Log.e(tag, "Failed to load downloader $packageName", t) + DownloaderState.Failed(t) } } suspend fun trustPackage(packageName: String) { trustDao.upsertTrust( - TrustedDownloaderPlugin( + TrustedDownloader( packageName, pm.getSignature(packageName).toByteArray() ) @@ -133,15 +133,15 @@ class DownloaderPluginRepository( reload() prefs.edit { - acknowledgedDownloaderPlugins += packageName + acknowledgedDownloader += packageName } } suspend fun revokeTrustForPackage(packageName: String) = trustDao.remove(packageName).also { reload() } - suspend fun acknowledgeAllNewPlugins() = - acknowledgedDownloaderPlugins.update(installedPluginPackageNames.value) + suspend fun acknowledgeAllNewDownloader() = + acknowledgedDownloader.update(installedDownloaderPackageNames.value) private suspend fun verify(packageName: String): Boolean { val expectedSignature = @@ -151,8 +151,8 @@ class DownloaderPluginRepository( } private companion object { - const val PLUGIN_FEATURE = "app.revanced.manager.plugin.downloader" - const val METADATA_PLUGIN_CLASS = "app.revanced.manager.plugin.downloader.class" + const val DOWNLOADER_FEATURE = "app.revanced.manager.downloader" + const val METADATA_DOWNLOADER_CLASS = "app.revanced.manager.downloader.class" const val PUBLIC_STATIC = Modifier.PUBLIC or Modifier.STATIC val Int.isPublicStatic get() = (this and PUBLIC_STATIC) == PUBLIC_STATIC diff --git a/app/src/main/java/app/revanced/manager/network/downloader/DownloaderPluginState.kt b/app/src/main/java/app/revanced/manager/network/downloader/DownloaderPluginState.kt deleted file mode 100644 index a72d60c7..00000000 --- a/app/src/main/java/app/revanced/manager/network/downloader/DownloaderPluginState.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.manager.network.downloader - -sealed interface DownloaderPluginState { - data object Untrusted : DownloaderPluginState - - data class Loaded(val plugin: LoadedDownloaderPlugin) : DownloaderPluginState - - data class Failed(val throwable: Throwable) : DownloaderPluginState -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/network/downloader/DownloaderState.kt b/app/src/main/java/app/revanced/manager/network/downloader/DownloaderState.kt new file mode 100644 index 00000000..6c35d7b0 --- /dev/null +++ b/app/src/main/java/app/revanced/manager/network/downloader/DownloaderState.kt @@ -0,0 +1,9 @@ +package app.revanced.manager.network.downloader + +sealed interface DownloaderState { + data object Untrusted : DownloaderState + + data class Loaded(val downloader: LoadedDownloader) : DownloaderState + + data class Failed(val throwable: Throwable) : DownloaderState +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/network/downloader/LoadedDownloaderPlugin.kt b/app/src/main/java/app/revanced/manager/network/downloader/LoadedDownloader.kt similarity index 73% rename from app/src/main/java/app/revanced/manager/network/downloader/LoadedDownloaderPlugin.kt rename to app/src/main/java/app/revanced/manager/network/downloader/LoadedDownloader.kt index 50ddd561..696addc7 100644 --- a/app/src/main/java/app/revanced/manager/network/downloader/LoadedDownloaderPlugin.kt +++ b/app/src/main/java/app/revanced/manager/network/downloader/LoadedDownloader.kt @@ -1,11 +1,11 @@ package app.revanced.manager.network.downloader import android.os.Parcelable -import app.revanced.manager.plugin.downloader.OutputDownloadScope -import app.revanced.manager.plugin.downloader.GetScope +import app.revanced.manager.downloader.OutputDownloadScope +import app.revanced.manager.downloader.GetScope import java.io.OutputStream -class LoadedDownloaderPlugin( +class LoadedDownloader( val packageName: String, val name: String, val version: String, diff --git a/app/src/main/java/app/revanced/manager/network/downloader/ParceledDownloaderData.kt b/app/src/main/java/app/revanced/manager/network/downloader/ParceledDownloaderData.kt index 160d2231..4ebda0ab 100644 --- a/app/src/main/java/app/revanced/manager/network/downloader/ParceledDownloaderData.kt +++ b/app/src/main/java/app/revanced/manager/network/downloader/ParceledDownloaderData.kt @@ -10,20 +10,20 @@ import kotlinx.parcelize.Parcelize * A container for [Parcelable] data returned from downloader. Instances of this class can be safely stored in a bundle without needing to set the [ClassLoader]. */ class ParceledDownloaderData private constructor( - val pluginPackageName: String, + val downloaderPackageName: String, private val bundle: Bundle ) : Parcelable { - constructor(plugin: LoadedDownloaderPlugin, data: Parcelable) : this( - plugin.packageName, + constructor(downloader: LoadedDownloader, data: Parcelable) : this( + downloader.packageName, createBundle(data) ) - fun unwrapWith(plugin: LoadedDownloaderPlugin): Parcelable { - bundle.classLoader = plugin.classLoader + fun unwrapWith(downloader: LoadedDownloader): Parcelable { + bundle.classLoader = downloader.classLoader return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { val className = bundle.getString(CLASS_NAME_KEY)!! - val clazz = plugin.classLoader.loadClass(className) + val clazz = downloader.classLoader.loadClass(className) bundle.getParcelable(DATA_KEY, clazz)!! as Parcelable } else @Suppress("Deprecation") bundle.getParcelable(DATA_KEY)!! diff --git a/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt b/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt index 7076e122..07983e54 100644 --- a/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt +++ b/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt @@ -24,11 +24,11 @@ import app.revanced.manager.domain.installer.RootInstaller import app.revanced.manager.domain.manager.KeystoreManager import app.revanced.manager.domain.manager.PreferencesManager import app.revanced.manager.domain.repository.DownloadedAppRepository -import app.revanced.manager.domain.repository.DownloaderPluginRepository +import app.revanced.manager.domain.repository.DownloaderRepository import app.revanced.manager.domain.repository.InstalledAppRepository import app.revanced.manager.domain.worker.Worker import app.revanced.manager.domain.worker.WorkerRepository -import app.revanced.manager.network.downloader.LoadedDownloaderPlugin +import app.revanced.manager.network.downloader.LoadedDownloader import app.revanced.manager.patcher.ProgressEvent import app.revanced.manager.patcher.StepId import app.revanced.manager.patcher.logger.Logger @@ -36,9 +36,9 @@ import app.revanced.manager.patcher.runStep import app.revanced.manager.patcher.runtime.CoroutineRuntime import app.revanced.manager.patcher.runtime.ProcessRuntime import app.revanced.manager.patcher.toRemoteError -import app.revanced.manager.plugin.downloader.GetScope -import app.revanced.manager.plugin.downloader.PluginHostApi -import app.revanced.manager.plugin.downloader.UserInteractionException +import app.revanced.manager.downloader.GetScope +import app.revanced.manager.downloader.DownloaderHostApi +import app.revanced.manager.downloader.UserInteractionException import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.util.Options import app.revanced.manager.util.PM @@ -51,7 +51,7 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.inject import java.io.File -@OptIn(PluginHostApi::class) +@OptIn(DownloaderHostApi::class) class PatcherWorker( context: Context, parameters: WorkerParameters @@ -59,7 +59,7 @@ class PatcherWorker( private val workerRepository: WorkerRepository by inject() private val prefs: PreferencesManager by inject() private val keystoreManager: KeystoreManager by inject() - private val downloaderPluginRepository: DownloaderPluginRepository by inject() + private val downloaderRepository: DownloaderRepository by inject() private val downloadedAppRepository: DownloadedAppRepository by inject() private val pm: PM by inject() private val fs: Filesystem by inject() @@ -72,7 +72,7 @@ class PatcherWorker( val selectedPatches: PatchSelection, val options: Options, val logger: Logger, - val handleStartActivityRequest: suspend (LoadedDownloaderPlugin, Intent) -> ActivityResult, + val handleStartActivityRequest: suspend (LoadedDownloader, Intent) -> ActivityResult, val setInputFile: suspend (File) -> Unit, val onEvent: (ProgressEvent) -> Unit, ) { @@ -150,9 +150,9 @@ class PatcherWorker( } } - suspend fun download(plugin: LoadedDownloaderPlugin, data: Parcelable) = + suspend fun download(downloader: LoadedDownloader, data: Parcelable) = downloadedAppRepository.download( - plugin, + downloader, data, args.packageName, args.input.version, @@ -172,27 +172,27 @@ class PatcherWorker( val inputFile = when (val selectedApp = args.input) { is SelectedApp.Download -> { runStep(StepId.DownloadAPK, args.onEvent) { - val (plugin, data) = downloaderPluginRepository.unwrapParceledData( + val (downloader, data) = downloaderRepository.unwrapParceledData( selectedApp.data ) - download(plugin, data) + download(downloader, data) } } is SelectedApp.Search -> { runStep(StepId.DownloadAPK, args.onEvent) { - downloaderPluginRepository.loadedPluginsFlow.first() - .firstNotNullOfOrNull { plugin -> + downloaderRepository.loadedDownloaderFlow.first() + .firstNotNullOfOrNull { downloader -> try { val getScope = object : GetScope { - override val pluginPackageName = plugin.packageName + override val downloaderPackageName = downloader.packageName override val hostPackageName = applicationContext.packageName override suspend fun requestStartActivity(intent: Intent): Intent? { val result = - args.handleStartActivityRequest(plugin, intent) + args.handleStartActivityRequest(downloader, intent) return when (result.resultCode) { Activity.RESULT_OK -> result.data Activity.RESULT_CANCELED -> throw UserInteractionException.Activity.Cancelled() @@ -204,7 +204,7 @@ class PatcherWorker( } } withContext(Dispatchers.IO) { - plugin.get( + downloader.get( getScope, selectedApp.packageName, selectedApp.version @@ -214,7 +214,7 @@ class PatcherWorker( throw e } catch (_: UserInteractionException) { null - }?.let { (data, _) -> download(plugin, data) } + }?.let { (data, _) -> download(downloader, data) } } ?: throw Exception("App is not available.") } } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt index 0496c1a9..ac24ddad 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt @@ -90,13 +90,13 @@ fun DashboardScreen( onAppSelectorClick: () -> Unit, onSettingsClick: () -> Unit, onUpdateClick: () -> Unit, - onDownloaderPluginClick: () -> Unit, + onDownloaderClick: () -> Unit, onAppClick: (String) -> Unit ) { var selectedSourceCount by rememberSaveable { mutableIntStateOf(0) } val bundlesSelectable by remember { derivedStateOf { selectedSourceCount > 0 } } val availablePatches by vm.availablePatches.collectAsStateWithLifecycle(0) - val showNewDownloaderPluginsNotification by vm.newDownloaderPluginsAvailable.collectAsStateWithLifecycle( + val showNewDownloaderNotification by vm.newDownloaderAvailable.collectAsStateWithLifecycle( false ) val androidContext = LocalContext.current @@ -307,14 +307,14 @@ fun DashboardScreen( ) } } else null, - if (showNewDownloaderPluginsNotification) { + if (showNewDownloaderNotification) { { NotificationCard( - text = stringResource(R.string.new_downloader_plugins_notification), + text = stringResource(R.string.new_downloader_notification), icon = Icons.Outlined.Download, - modifier = Modifier.clickable(onClick = onDownloaderPluginClick), + modifier = Modifier.clickable(onClick = onDownloaderClick), actions = { - TextButton(onClick = vm::ignoreNewDownloaderPlugins) { + TextButton(onClick = vm::ignoreNewDownloader) { Text(stringResource(R.string.dismiss)) } } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt index f3a9f059..75f03b2c 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt @@ -148,7 +148,7 @@ fun PatcherScreen( }, title = { Text(title) }, text = { - Text(stringResource(R.string.plugin_activity_dialog_body)) + Text(stringResource(R.string.downloader_activity_dialog_body)) } ) } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt index 6c668870..3a0a14a5 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt @@ -39,7 +39,7 @@ import app.revanced.manager.R import app.revanced.manager.data.platform.NetworkInfo import app.revanced.manager.data.room.apps.installed.InstallType import app.revanced.manager.data.room.apps.installed.InstalledApp -import app.revanced.manager.network.downloader.LoadedDownloaderPlugin +import app.revanced.manager.network.downloader.LoadedDownloader import app.revanced.manager.ui.component.AlertDialogExtended import app.revanced.manager.ui.component.AppInfo import app.revanced.manager.ui.component.AppTopBar @@ -86,7 +86,7 @@ fun SelectedAppInfoScreen( val launcher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartActivityForResult(), - onResult = vm::handlePluginActivityResult + onResult = vm::handleDownloaderActivityResult ) EventEffect(flow = vm.launchActivityFlow) { intent -> launcher.launch(intent) @@ -140,22 +140,22 @@ fun SelectedAppInfoScreen( }, modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), ) { paddingValues -> - val plugins by vm.plugins.collectAsStateWithLifecycle(emptyList()) + val downloader by vm.downloader.collectAsStateWithLifecycle(emptyList()) if (vm.showSourceSelector) { val requiredVersion by vm.requiredVersion.collectAsStateWithLifecycle(null) AppSourceSelectorDialog( - plugins = plugins, + downloader = downloader, installedApp = vm.installedAppData, searchApp = SelectedApp.Search( vm.packageName, vm.desiredVersion ), - activeSearchJob = vm.activePluginAction, + activeSearchJob = vm.activeDownloaderAction, hasRoot = vm.hasRoot, onDismissRequest = vm::dismissSourceSelector, - onSelectPlugin = vm::searchUsingPlugin, + onSelectDownloader = vm::searchUsingDownloader, requiredVersion = requiredVersion, onSelect = { vm.selectedApp = it @@ -201,8 +201,8 @@ fun SelectedAppInfoScreen( is SelectedApp.Installed -> stringResource(R.string.apk_source_installed) is SelectedApp.Download -> stringResource( R.string.apk_source_downloader, - plugins.find { it.packageName == app.data.pluginPackageName }?.name - ?: app.data.pluginPackageName + downloader.find { it.packageName == app.data.downloaderPackageName }?.name + ?: app.data.downloaderPackageName ) is SelectedApp.Local -> stringResource(R.string.apk_source_local) @@ -279,14 +279,14 @@ private fun PageItem(@StringRes title: Int, description: String, onClick: () -> @Composable private fun AppSourceSelectorDialog( - plugins: List, + downloader: List, installedApp: Pair?, searchApp: SelectedApp.Search, activeSearchJob: String?, hasRoot: Boolean, requiredVersion: String?, onDismissRequest: () -> Unit, - onSelectPlugin: (LoadedDownloaderPlugin) -> Unit, + onSelectDownloader: (LoadedDownloader) -> Unit, onSelect: (SelectedApp) -> Unit, ) { val canSelect = activeSearchJob == null @@ -303,15 +303,15 @@ private fun AppSourceSelectorDialog( text = { LazyColumn { item(key = "auto") { - val hasPlugins = plugins.isNotEmpty() + val hasDownloader = downloader.isNotEmpty() ListItem( modifier = Modifier - .clickable(enabled = canSelect && hasPlugins) { onSelect(searchApp) } - .enabled(hasPlugins), + .clickable(enabled = canSelect && hasDownloader) { onSelect(searchApp) } + .enabled(hasDownloader), headlineContent = { Text(stringResource(R.string.app_source_dialog_option_auto)) }, supportingContent = { Text( - if (hasPlugins) + if (hasDownloader) stringResource(R.string.app_source_dialog_option_auto_description) else stringResource(R.string.app_source_dialog_option_auto_unavailable) @@ -349,11 +349,11 @@ private fun AppSourceSelectorDialog( } } - items(plugins, key = { "plugin_${it.packageName}" }) { plugin -> + items(downloader, key = { "downloader_${it.packageName}" }) { downloader -> ListItem( - modifier = Modifier.clickable(enabled = canSelect) { onSelectPlugin(plugin) }, - headlineContent = { Text(plugin.name) }, - trailingContent = (@Composable { LoadingIndicator() }).takeIf { activeSearchJob == plugin.packageName }, + modifier = Modifier.clickable(enabled = canSelect) { onSelectDownloader(downloader) }, + headlineContent = { Text(downloader.name) }, + trailingContent = (@Composable { LoadingIndicator() }).takeIf { activeSearchJob == downloader.packageName }, colors = transparentListItemColors ) } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/DownloadsSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/DownloadsSettingsScreen.kt index c6cf7316..1173b388 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/DownloadsSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/DownloadsSettingsScreen.kt @@ -39,7 +39,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.revanced.manager.R -import app.revanced.manager.network.downloader.DownloaderPluginState +import app.revanced.manager.network.downloader.DownloaderState import app.revanced.manager.ui.component.AppLabel import app.revanced.manager.ui.component.AppTopBar import app.revanced.manager.ui.component.ConfirmDialog @@ -60,7 +60,7 @@ fun DownloadsSettingsScreen( ) { val context = LocalContext.current val downloadedApps by viewModel.downloadedApps.collectAsStateWithLifecycle(emptyList()) - val pluginStates by viewModel.downloaderPluginStates.collectAsStateWithLifecycle() + val downloaderStates by viewModel.downloaderStates.collectAsStateWithLifecycle() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) var showDeleteConfirmationDialog by rememberSaveable { mutableStateOf(false) } @@ -68,8 +68,8 @@ fun DownloadsSettingsScreen( ConfirmDialog( onDismiss = { showDeleteConfirmationDialog = false }, onConfirm = { viewModel.deleteApps() }, - title = stringResource(R.string.downloader_plugin_delete_apps_title), - description = stringResource(R.string.downloader_plugin_delete_apps_description), + title = stringResource(R.string.downloader_delete_apps_title), + description = stringResource(R.string.downloader_delete_apps_description), icon = Icons.Outlined.Delete ) } @@ -92,17 +92,17 @@ fun DownloadsSettingsScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), ) { paddingValues -> PullToRefreshBox( - onRefresh = viewModel::refreshPlugins, - isRefreshing = viewModel.isRefreshingPlugins, + onRefresh = viewModel::refreshDownloader, + isRefreshing = viewModel.isRefreshingDownloader, modifier = Modifier.padding(paddingValues) ) { LazyColumnWithScrollbar( modifier = Modifier.fillMaxSize() ) { item { - GroupHeader(stringResource(R.string.downloader_plugins)) + GroupHeader(stringResource(R.string.downloader)) } - pluginStates.forEach { (packageName, state) -> + downloaderStates.forEach { (packageName, state) -> item(key = packageName) { var showDialog by rememberSaveable { mutableStateOf(false) @@ -135,39 +135,39 @@ fun DownloadsSettingsScreen( } when (state) { - is DownloaderPluginState.Loaded -> TrustDialog( - title = R.string.downloader_plugin_revoke_trust_dialog_title, + is DownloaderState.Loaded -> TrustDialog( + title = R.string.downloader_revoke_trust_dialog_title, body = stringResource( - R.string.downloader_plugin_trust_dialog_body, + R.string.downloader_trust_dialog_body, packageName, signature ), - pluginName = appName, + downloaderName = appName, signature = signature, onDismiss = ::dismiss, onConfirm = { - viewModel.revokePluginTrust(packageName) + viewModel.revokeDownloaderTrust(packageName) dismiss() } ) - is DownloaderPluginState.Failed -> ExceptionViewerDialog( + is DownloaderState.Failed -> ExceptionViewerDialog( text = remember(state.throwable) { state.throwable.stackTraceToString() }, onDismiss = ::dismiss ) - is DownloaderPluginState.Untrusted -> TrustDialog( - title = R.string.downloader_plugin_trust_dialog_title, + is DownloaderState.Untrusted -> TrustDialog( + title = R.string.downloader_trust_dialog_title, body = stringResource( - R.string.downloader_plugin_trust_dialog_body + R.string.downloader_trust_dialog_body ), - pluginName = appName, + downloaderName = appName, signature = signature, onDismiss = ::dismiss, onConfirm = { - viewModel.trustPlugin(packageName) + viewModel.trustDownloader(packageName) dismiss() } ) @@ -184,19 +184,19 @@ fun DownloadsSettingsScreen( }, supportingContent = stringResource( when (state) { - is DownloaderPluginState.Loaded -> R.string.downloader_plugin_state_trusted - is DownloaderPluginState.Failed -> R.string.downloader_plugin_state_failed - is DownloaderPluginState.Untrusted -> R.string.downloader_plugin_state_untrusted + is DownloaderState.Loaded -> R.string.downloader_state_trusted + is DownloaderState.Failed -> R.string.downloader_state_failed + is DownloaderState.Untrusted -> R.string.downloader_state_untrusted } ), trailingContent = { Text(packageInfo.versionName!!) } ) } } - if (pluginStates.isEmpty()) { + if (downloaderStates.isEmpty()) { item { Text( - stringResource(R.string.downloader_no_plugins_installed), + stringResource(R.string.no_downloader_installed), modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center ) @@ -240,7 +240,7 @@ fun DownloadsSettingsScreen( private fun TrustDialog( @StringRes title: Int, body: String, - pluginName: String, + downloaderName: String, signature: String, onDismiss: () -> Unit, onConfirm: () -> Unit @@ -268,8 +268,8 @@ private fun TrustDialog( ) { Text( stringResource( - R.string.downloader_plugin_trust_dialog_plugin, - pluginName + R.string.downloader_trust_dialog_name, + downloaderName ), ) OutlinedCard( @@ -279,7 +279,7 @@ private fun TrustDialog( ) { Text( stringResource( - R.string.downloader_plugin_trust_dialog_signature, + R.string.downloader_trust_dialog_signature, signature.chunked(2).joinToString(" ") ), modifier = Modifier.padding(12.dp) ) diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt index 26f86092..0929c304 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt @@ -7,7 +7,6 @@ import android.net.Uri import android.os.Build import android.os.PowerManager import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.core.content.getSystemService @@ -15,15 +14,12 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import app.revanced.manager.R import app.revanced.manager.data.platform.NetworkInfo -import app.revanced.manager.domain.bundles.PatchBundleSource import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.asRemoteOrNull -import app.revanced.manager.domain.bundles.RemotePatchBundle import app.revanced.manager.domain.manager.PreferencesManager -import app.revanced.manager.domain.repository.DownloaderPluginRepository +import app.revanced.manager.domain.repository.DownloaderRepository import app.revanced.manager.domain.repository.PatchBundleRepository import app.revanced.manager.network.api.ReVancedAPI import app.revanced.manager.util.PM -import app.revanced.manager.util.toast import app.revanced.manager.util.uiSafe import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.first @@ -34,7 +30,7 @@ import kotlinx.coroutines.launch class DashboardViewModel( private val app: Application, private val patchBundleRepository: PatchBundleRepository, - private val downloaderPluginRepository: DownloaderPluginRepository, + private val downloaderRepository: DownloaderRepository, private val reVancedAPI: ReVancedAPI, private val networkInfo: NetworkInfo, val prefs: PreferencesManager, @@ -45,8 +41,8 @@ class DashboardViewModel( private val contentResolver: ContentResolver = app.contentResolver private val powerManager = app.getSystemService()!! - val newDownloaderPluginsAvailable = - downloaderPluginRepository.newPluginPackageNames.map { it.isNotEmpty() } + val newDownloaderAvailable = + downloaderRepository.newDownloaderPackageNames.map { it.isNotEmpty() } /** * Android 11 kills the app process after granting the "install apps" permission, which is a problem for the patcher screen. @@ -71,8 +67,8 @@ class DashboardViewModel( } } - fun ignoreNewDownloaderPlugins() = viewModelScope.launch { - downloaderPluginRepository.acknowledgeAllNewPlugins() + fun ignoreNewDownloader() = viewModelScope.launch { + downloaderRepository.acknowledgeAllNewDownloader() } private suspend fun checkForManagerUpdates() { diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/DownloadsViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/DownloadsViewModel.kt index e2c750df..a6f4bbad 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/DownloadsViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/DownloadsViewModel.kt @@ -1,6 +1,5 @@ package app.revanced.manager.ui.viewmodel -import android.content.pm.PackageInfo import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue @@ -8,7 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import app.revanced.manager.data.room.apps.downloaded.DownloadedApp import app.revanced.manager.domain.repository.DownloadedAppRepository -import app.revanced.manager.domain.repository.DownloaderPluginRepository +import app.revanced.manager.domain.repository.DownloaderRepository import app.revanced.manager.util.PM import app.revanced.manager.util.mutableStateSetOf import kotlinx.coroutines.Dispatchers @@ -19,10 +18,10 @@ import kotlinx.coroutines.withContext class DownloadsViewModel( private val downloadedAppRepository: DownloadedAppRepository, - private val downloaderPluginRepository: DownloaderPluginRepository, + private val downloaderRepository: DownloaderRepository, val pm: PM ) : ViewModel() { - val downloaderPluginStates = downloaderPluginRepository.pluginStates + val downloaderStates = downloaderRepository.downloaderStates val downloadedApps = downloadedAppRepository.getAll().map { downloadedApps -> downloadedApps.sortedWith( compareBy { @@ -32,7 +31,7 @@ class DownloadsViewModel( } val appSelection = mutableStateSetOf() - var isRefreshingPlugins by mutableStateOf(false) + var isRefreshingDownloader by mutableStateOf(false) private set fun toggleApp(downloadedApp: DownloadedApp) { @@ -52,17 +51,17 @@ class DownloadsViewModel( } } - fun refreshPlugins() = viewModelScope.launch { - isRefreshingPlugins = true - downloaderPluginRepository.reload() - isRefreshingPlugins = false + fun refreshDownloader() = viewModelScope.launch { + isRefreshingDownloader = true + downloaderRepository.reload() + isRefreshingDownloader = false } - fun trustPlugin(packageName: String) = viewModelScope.launch { - downloaderPluginRepository.trustPackage(packageName) + fun trustDownloader(packageName: String) = viewModelScope.launch { + downloaderRepository.trustPackage(packageName) } - fun revokePluginTrust(packageName: String) = viewModelScope.launch { - downloaderPluginRepository.revokeTrustForPackage(packageName) + fun revokeDownloaderTrust(packageName: String) = viewModelScope.launch { + downloaderRepository.revokeTrustForPackage(packageName) } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt index 194f4214..ce053ee6 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt @@ -34,8 +34,8 @@ import app.revanced.manager.patcher.StepId import app.revanced.manager.patcher.logger.LogLevel import app.revanced.manager.patcher.logger.Logger import app.revanced.manager.patcher.worker.PatcherWorker -import app.revanced.manager.plugin.downloader.PluginHostApi -import app.revanced.manager.plugin.downloader.UserInteractionException +import app.revanced.manager.downloader.DownloaderHostApi +import app.revanced.manager.downloader.UserInteractionException import app.revanced.manager.ui.model.InstallerModel import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.ui.model.State @@ -79,7 +79,7 @@ import java.io.File import java.nio.file.Files import java.time.Duration -@OptIn(SavedStateHandleSaveableApi::class, PluginHostApi::class) +@OptIn(SavedStateHandleSaveableApi::class, DownloaderHostApi::class) class PatcherViewModel( private val input: Patcher.ViewModelParams ) : ViewModel(), KoinComponent, InstallerModel { @@ -184,13 +184,13 @@ class PatcherViewModel( input.options, logger, setInputFile = { withContext(Dispatchers.Main) { inputFile = it } }, - handleStartActivityRequest = { plugin, intent -> + handleStartActivityRequest = { downloader, intent -> withContext(Dispatchers.Main) { if (currentActivityRequest != null) throw Exception("Another request is already pending.") try { // Wait for the dialog interaction. val accepted = with(CompletableDeferred()) { - currentActivityRequest = this to plugin.name + currentActivityRequest = this to downloader.name await() } diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/SelectedAppInfoViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/SelectedAppInfoViewModel.kt index 665b353b..4869909e 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/SelectedAppInfoViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/SelectedAppInfoViewModel.kt @@ -22,19 +22,19 @@ import app.revanced.manager.R import app.revanced.manager.data.room.apps.installed.InstalledApp import app.revanced.manager.domain.installer.RootInstaller import app.revanced.manager.domain.manager.PreferencesManager -import app.revanced.manager.domain.repository.DownloaderPluginRepository +import app.revanced.manager.domain.repository.DownloaderRepository import app.revanced.manager.domain.repository.InstalledAppRepository import app.revanced.manager.domain.repository.PatchBundleRepository import app.revanced.manager.domain.repository.PatchOptionsRepository import app.revanced.manager.domain.repository.PatchSelectionRepository import app.revanced.manager.patcher.patch.PatchBundleInfo import app.revanced.manager.patcher.patch.PatchBundleInfo.Extensions.toPatchSelection -import app.revanced.manager.network.downloader.LoadedDownloaderPlugin +import app.revanced.manager.network.downloader.LoadedDownloader import app.revanced.manager.network.downloader.ParceledDownloaderData import app.revanced.manager.patcher.patch.PatchBundleInfo.Extensions.requiredOptionsSet -import app.revanced.manager.plugin.downloader.GetScope -import app.revanced.manager.plugin.downloader.PluginHostApi -import app.revanced.manager.plugin.downloader.UserInteractionException +import app.revanced.manager.downloader.GetScope +import app.revanced.manager.downloader.DownloaderHostApi +import app.revanced.manager.downloader.UserInteractionException import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.ui.model.navigation.Patcher import app.revanced.manager.ui.model.navigation.SelectedApplicationInfo @@ -59,7 +59,7 @@ import kotlinx.parcelize.Parcelize import org.koin.core.component.KoinComponent import org.koin.core.component.get -@OptIn(SavedStateHandleSaveableApi::class, PluginHostApi::class) +@OptIn(SavedStateHandleSaveableApi::class, DownloaderHostApi::class) class SelectedAppInfoViewModel( input: SelectedApplicationInfo.ViewModelParams ) : ViewModel(), KoinComponent { @@ -67,13 +67,13 @@ class SelectedAppInfoViewModel( private val bundleRepository: PatchBundleRepository = get() private val selectionRepository: PatchSelectionRepository = get() private val optionsRepository: PatchOptionsRepository = get() - private val pluginsRepository: DownloaderPluginRepository = get() + private val downloaderRepository: DownloaderRepository = get() private val installedAppRepository: InstalledAppRepository = get() private val rootInstaller: RootInstaller = get() private val pm: PM = get() private val savedStateHandle: SavedStateHandle = get() val prefs: PreferencesManager = get() - val plugins = pluginsRepository.loadedPluginsFlow + val downloader = downloaderRepository.loadedDownloaderFlow val desiredVersion = input.app.version val packageName = input.app.packageName @@ -160,15 +160,15 @@ class SelectedAppInfoViewModel( var showSourceSelector by mutableStateOf(false) private set - private var pluginAction: Pair? by mutableStateOf(null) - val activePluginAction get() = pluginAction?.first?.packageName + private var downloaderAction: Pair? by mutableStateOf(null) + val activeDownloaderAction get() = downloaderAction?.first?.packageName private var launchedActivity by mutableStateOf?>(null) private val launchActivityChannel = Channel() val launchActivityFlow = launchActivityChannel.receiveAsFlow() - val errorFlow = combine(plugins, snapshotFlow { selectedApp }) { pluginsList, app -> + val errorFlow = combine(downloader, snapshotFlow { selectedApp }) { downloaderList, app -> when { - app is SelectedApp.Search && pluginsList.isEmpty() -> Error.NoPlugins + app is SelectedApp.Search && downloaderList.isEmpty() -> Error.NoDownloader else -> null } } @@ -178,23 +178,23 @@ class SelectedAppInfoViewModel( showSourceSelector = true } - private fun cancelPluginAction() { - pluginAction?.second?.cancel() - pluginAction = null + private fun cancelDownloaderAction() { + downloaderAction?.second?.cancel() + downloaderAction = null } fun dismissSourceSelector() { - cancelPluginAction() + cancelDownloaderAction() showSourceSelector = false } - fun searchUsingPlugin(plugin: LoadedDownloaderPlugin) { - cancelPluginAction() - pluginAction = plugin to viewModelScope.launch { + fun searchUsingDownloader(downloader: LoadedDownloader) { + cancelDownloaderAction() + downloaderAction = downloader to viewModelScope.launch { try { val scope = object : GetScope { override val hostPackageName = app.packageName - override val pluginPackageName = plugin.packageName + override val downloaderPackageName = downloader.packageName override suspend fun requestStartActivity(intent: Intent) = withContext(Dispatchers.Main) { if (launchedActivity != null) error("Previous activity has not finished") @@ -219,7 +219,7 @@ class SelectedAppInfoViewModel( } withContext(Dispatchers.IO) { - plugin.get(scope, packageName, desiredVersion) + downloader.get(scope, packageName, desiredVersion) }?.let { (data, version) -> if (desiredVersion != null && version != desiredVersion) { app.toast(app.getString(R.string.downloader_invalid_version)) @@ -228,7 +228,7 @@ class SelectedAppInfoViewModel( selectedApp = SelectedApp.Download( packageName, version, - ParceledDownloaderData(plugin, data) + ParceledDownloaderData(downloader, data) ) } ?: app.toast(app.getString(R.string.downloader_app_not_found)) } catch (e: UserInteractionException.Activity) { @@ -239,13 +239,13 @@ class SelectedAppInfoViewModel( app.toast(app.getString(R.string.downloader_error, e.simpleMessage())) Log.e(tag, "Downloader.get threw an exception", e) } finally { - pluginAction = null + downloaderAction = null dismissSourceSelector() } } } - fun handlePluginActivityResult(result: ActivityResult) { + fun handleDownloaderActivityResult(result: ActivityResult) { launchedActivity?.complete(result) } @@ -307,7 +307,7 @@ class SelectedAppInfoViewModel( } enum class Error(@param:StringRes val resourceId: Int) { - NoPlugins(R.string.downloader_no_plugins_available) + NoDownloader(R.string.no_downloader_available) } private companion object { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eeb52799..8cd18037 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -19,8 +19,8 @@ Second \"item\" text" CLI Manager - ReVanced Manager plugin host - Used to control access to ReVanced Manager plugins. Only ReVanced Manager has this. + ReVanced Manager downloader host + Used to control access to ReVanced Manager downloader. Only ReVanced Manager has this. Copied! Copy to clipboard @@ -30,7 +30,7 @@ Second \"item\" text" Select an app %1$d/%2$d selected - New downloader plugins available. Click here to configure them. + New downloader available. Click here to configure them. Patching on this device architecture is unsupported and will most likely fail. Import @@ -56,7 +56,7 @@ Second \"item\" text" Select source Auto Use all available downloader to download the app - No plugins available + No downloader available Mounted apps cannot be patched again without root access Version %s does not match the suggested version @@ -87,7 +87,7 @@ Second \"item\" text" Updates Check for updates and view changelogs Downloads - Downloader plugins and downloaded apps + Downloader and downloaded apps Import & export Keystore, patch options and selection Advanced @@ -175,17 +175,17 @@ You will not be able to update the previously installed apps from this source."< Reset patch options globally You are about to reset all patch options. You will have to reapply each option again. Resets all patch options - Plugins - Trusted - Failed to load. Click for more details - Untrusted - Trust plugin? - Revoke trust? - Continuing will allow this plugin to run on your system.\n\nOnly enable this plugin if you trust it. Plugins can execute arbitrary code and may compromise your device. - Signature:\n\n%s - Plugin:\n%s - Delete selected apps - Are you sure you want to delete the selected apps? + Downloader + Trusted + Failed to load. Click for more details + Untrusted + Trust downloader? + Revoke trust? + Continuing will allow this downloader to run on your system.\n\nOnly enable this downloader if you trust it. Downloader can execute arbitrary code and may compromise your device. + Signature:\n\n%s + Downloader:\n%s + Delete selected apps + Are you sure you want to delete the selected apps? No downloaded apps found. Search apps… @@ -316,8 +316,8 @@ It is only compatible with the following version(s): %2$s" Downloader did not fetch the correct version Downloader did not find the app Downloader error: %s - No downloader installed. - There are downloaders installed but none are trusted. Check your settings. + No downloader installed. + There are downloader installed but none are trusted. Check your settings. Already patched Filter @@ -345,7 +345,7 @@ It is only compatible with the following version(s): %2$s" APK Saved Failed to sign APK: %s Save logs - User interaction is required in order to proceed with this plugin. + User interaction is required in order to proceed with this downloader. Select installation type Preparing