mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-04-29 21:44:26 +02:00
add string resources and fix webview bugs
This commit is contained in:
parent
d0cd29d625
commit
829f093afe
@ -76,7 +76,7 @@ class PatcherWorker(
|
||||
val logger: Logger,
|
||||
val downloadProgress: MutableStateFlow<Pair<Double, Double?>?>,
|
||||
val patchesProgress: MutableStateFlow<Pair<Int, Int>>,
|
||||
val handleStartActivityRequest: suspend (Intent) -> ActivityResult,
|
||||
val handleStartActivityRequest: suspend (LoadedDownloaderPlugin, Intent) -> ActivityResult,
|
||||
val setInputFile: (File) -> Unit,
|
||||
val onProgress: ProgressEventHandler
|
||||
) {
|
||||
@ -182,7 +182,7 @@ class PatcherWorker(
|
||||
override val pluginPackageName = plugin.packageName
|
||||
override val hostPackageName = applicationContext.packageName
|
||||
override suspend fun requestStartActivity(intent: Intent): Intent? {
|
||||
val result = args.handleStartActivityRequest(intent)
|
||||
val result = args.handleStartActivityRequest(plugin, intent)
|
||||
return when (result.resultCode) {
|
||||
Activity.RESULT_OK -> result.data
|
||||
Activity.RESULT_CANCELED -> throw UserInteractionException.Activity.Cancelled()
|
||||
|
@ -96,7 +96,7 @@ fun PatcherScreen(
|
||||
activityLauncher.launch(intent)
|
||||
}
|
||||
|
||||
if (vm.showActivityPromptDialog)
|
||||
vm.activityPromptDialog?.let { title ->
|
||||
AlertDialog(
|
||||
onDismissRequest = vm::rejectInteraction,
|
||||
confirmButton = {
|
||||
@ -113,11 +113,12 @@ fun PatcherScreen(
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
title = { Text("User interaction required.") },
|
||||
title = { Text(title) },
|
||||
text = {
|
||||
Text("User interaction is required to proceed.")
|
||||
Text(stringResource(R.string.plugin_activity_dialog_body))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
AppScaffold(
|
||||
topBar = {
|
||||
|
@ -273,7 +273,7 @@ private fun AppSourceSelectorDialog(
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
title = { Text("Select source") },
|
||||
title = { Text(stringResource(R.string.app_source_dialog_title)) },
|
||||
textHorizontalPadding = PaddingValues(horizontal = 0.dp),
|
||||
text = {
|
||||
LazyColumn {
|
||||
@ -283,8 +283,15 @@ private fun AppSourceSelectorDialog(
|
||||
modifier = Modifier
|
||||
.clickable(enabled = canSelect && hasPlugins) { onSelect(searchApp) }
|
||||
.enabled(hasPlugins),
|
||||
headlineContent = { Text("Auto") },
|
||||
supportingContent = { Text(if (hasPlugins) "Use all installed downloaders to find a suitable app." else "No plugins available") },
|
||||
headlineContent = { Text(stringResource(R.string.app_source_dialog_option_auto)) },
|
||||
supportingContent = {
|
||||
Text(
|
||||
if (hasPlugins)
|
||||
stringResource(R.string.app_source_dialog_option_auto_description)
|
||||
else
|
||||
stringResource(R.string.app_source_dialog_option_auto_unavailable)
|
||||
)
|
||||
},
|
||||
colors = transparentListItemColors
|
||||
)
|
||||
}
|
||||
@ -293,11 +300,17 @@ private fun AppSourceSelectorDialog(
|
||||
item(key = "installed") {
|
||||
val (usable, text) = when {
|
||||
// Mounted apps must be unpatched before patching, which cannot be done without root access.
|
||||
meta?.installType == InstallType.MOUNT && !hasRoot -> false to "Mounted apps cannot be patched again without root access"
|
||||
meta?.installType == InstallType.MOUNT && !hasRoot -> false to stringResource(
|
||||
R.string.app_source_dialog_option_installed_no_root
|
||||
)
|
||||
// Patching already patched apps is not allowed because patches expect unpatched apps.
|
||||
meta?.installType == InstallType.DEFAULT -> false to stringResource(R.string.already_patched)
|
||||
// Version does not match suggested version.
|
||||
requiredVersion != null && app.version != requiredVersion -> false to "Version ${app.version} does not match the suggested version"
|
||||
requiredVersion != null && app.version != requiredVersion -> false to stringResource(
|
||||
R.string.app_source_dialog_option_installed_version_not_suggested,
|
||||
app.version
|
||||
)
|
||||
|
||||
else -> true to app.version
|
||||
}
|
||||
ListItem(
|
||||
@ -315,7 +328,6 @@ private fun AppSourceSelectorDialog(
|
||||
ListItem(
|
||||
modifier = Modifier.clickable(enabled = canSelect) { onSelectPlugin(plugin) },
|
||||
headlineContent = { Text(plugin.name) },
|
||||
supportingContent = { Text("Try to find the app using ${plugin.name}") },
|
||||
trailingContent = (@Composable { LoadingIndicator() }).takeIf { activeSearchJob == plugin.packageName },
|
||||
colors = transparentListItemColors
|
||||
)
|
||||
|
@ -98,8 +98,8 @@ class PatcherViewModel(
|
||||
var isInstalling by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
private var currentActivityRequest: CompletableDeferred<Boolean>? by mutableStateOf(null)
|
||||
val showActivityPromptDialog by derivedStateOf { currentActivityRequest != null }
|
||||
private var currentActivityRequest: Pair<CompletableDeferred<Boolean>, String>? by mutableStateOf(null)
|
||||
val activityPromptDialog by derivedStateOf { currentActivityRequest?.second }
|
||||
|
||||
private var launchedActivity: CompletableDeferred<ActivityResult>? = null
|
||||
private val launchActivityChannel = Channel<Intent>()
|
||||
@ -146,13 +146,13 @@ class PatcherViewModel(
|
||||
downloadProgress,
|
||||
patchesProgress,
|
||||
setInputFile = { inputFile = it },
|
||||
handleStartActivityRequest = { intent ->
|
||||
handleStartActivityRequest = { plugin, intent ->
|
||||
withContext(Dispatchers.Main) {
|
||||
if (currentActivityRequest != null) throw Exception("Another request is already pending.")
|
||||
try {
|
||||
// Wait for the dialog interaction.
|
||||
val accepted = with(CompletableDeferred<Boolean>()) {
|
||||
currentActivityRequest = this
|
||||
currentActivityRequest = this to plugin.name
|
||||
|
||||
await()
|
||||
}
|
||||
@ -291,11 +291,11 @@ class PatcherViewModel(
|
||||
fun isDeviceRooted() = rootInstaller.isDeviceRooted()
|
||||
|
||||
fun rejectInteraction() {
|
||||
currentActivityRequest?.complete(false)
|
||||
currentActivityRequest?.first?.complete(false)
|
||||
}
|
||||
|
||||
fun allowInteraction() {
|
||||
currentActivityRequest?.complete(true)
|
||||
currentActivityRequest?.first?.complete(true)
|
||||
}
|
||||
|
||||
fun handleActivityResult(result: ActivityResult) {
|
||||
|
@ -36,6 +36,12 @@
|
||||
<string name="bundle_name_fallback">Unnamed</string>
|
||||
|
||||
<string name="selected_app_meta_any_version">Any available version</string>
|
||||
<string name="app_source_dialog_title">Select source</string>
|
||||
<string name="app_source_dialog_option_auto">Auto</string>
|
||||
<string name="app_source_dialog_option_auto_description">Use all installed downloaders to find a suitable APK file</string>
|
||||
<string name="app_source_dialog_option_auto_unavailable">No plugins available</string>
|
||||
<string name="app_source_dialog_option_installed_no_root">Mounted apps cannot be patched again without root access</string>
|
||||
<string name="app_source_dialog_option_installed_version_not_suggested">Version %s does not match the suggested version</string>
|
||||
|
||||
<string name="patch_item_description">Start patching the application</string>
|
||||
<string name="patch_selector_item">Patch selection and options</string>
|
||||
@ -275,6 +281,7 @@
|
||||
<string name="save_apk_success">APK Saved</string>
|
||||
<string name="sign_fail">Failed to sign APK: %s</string>
|
||||
<string name="save_logs">Save logs</string>
|
||||
<string name="plugin_activity_dialog_body">User interaction is required in order to proceed with this plugin.</string>
|
||||
<string name="select_install_type">Select installation type</string>
|
||||
|
||||
<string name="patcher_step_group_preparing">Preparing</string>
|
||||
|
@ -5,11 +5,13 @@ import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.os.Parcelable
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.view.ViewCompat
|
||||
@ -31,14 +33,20 @@ class WebViewActivity : ComponentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val vm by viewModels<WebViewModel>()
|
||||
|
||||
enableEdgeToEdge()
|
||||
setContentView(R.layout.activity_webview)
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
val webView = findViewById<WebView>(R.id.webview)
|
||||
onBackPressedDispatcher.addCallback {
|
||||
if (webView.canGoBack()) webView.goBack()
|
||||
else cancelActivity()
|
||||
}
|
||||
|
||||
val params = intent.getParcelableExtra<Parameters>(KEY)!!
|
||||
actionBar?.apply {
|
||||
title = params.title
|
||||
@ -49,12 +57,11 @@ class WebViewActivity : ComponentActivity() {
|
||||
val events = IWebViewEvents.Stub.asInterface(params.events)!!
|
||||
vm.setup(events)
|
||||
|
||||
val webView = findViewById<WebView>(R.id.content).apply {
|
||||
webView.apply {
|
||||
settings.apply {
|
||||
cacheMode = WebSettings.LOAD_NO_CACHE
|
||||
databaseEnabled = false
|
||||
allowContentAccess = false
|
||||
domStorageEnabled = false
|
||||
domStorageEnabled = true
|
||||
javaScriptEnabled = true
|
||||
}
|
||||
|
||||
@ -80,9 +87,14 @@ class WebViewActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = if (item.itemId == android.R.id.home) {
|
||||
private fun cancelActivity() {
|
||||
setResult(RESULT_CANCELED)
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = if (item.itemId == android.R.id.home) {
|
||||
cancelActivity()
|
||||
|
||||
true
|
||||
} else super.onOptionsItemSelected(item)
|
||||
|
||||
|
@ -1,16 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".webview.WebViewActivity">
|
||||
android:id="@+id/main">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/content"
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:layout_editor_absoluteX="1dp"
|
||||
tools:layout_editor_absoluteY="1dp" />
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
@ -12,18 +12,6 @@ import app.revanced.manager.plugin.downloader.webview.WebViewDownloader
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlin.io.path.*
|
||||
|
||||
// TODO: update UI error presentation and strings
|
||||
|
||||
@Parcelize
|
||||
class InstalledApp(val path: String) : Parcelable
|
||||
|
||||
private val application by lazy {
|
||||
// Don't do this in a real plugin.
|
||||
val clazz = Class.forName("android.app.ActivityThread")
|
||||
val activityThread = clazz.getMethod("currentActivityThread")(null)
|
||||
clazz.getMethod("getApplication")(activityThread) as Application
|
||||
}
|
||||
|
||||
val apkMirrorDownloader = WebViewDownloader { packageName, version ->
|
||||
with(Uri.Builder()) {
|
||||
scheme("https")
|
||||
@ -41,6 +29,16 @@ val apkMirrorDownloader = WebViewDownloader { packageName, version ->
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class InstalledApp(val path: String) : Parcelable
|
||||
|
||||
private val application by lazy {
|
||||
// Don't do this in a real plugin.
|
||||
val clazz = Class.forName("android.app.ActivityThread")
|
||||
val activityThread = clazz.getMethod("currentActivityThread")(null)
|
||||
clazz.getMethod("getApplication")(activityThread) as Application
|
||||
}
|
||||
|
||||
val installedAppDownloader = Downloader<InstalledApp> {
|
||||
val pm = application.packageManager
|
||||
|
||||
@ -68,4 +66,4 @@ val installedAppDownloader = Downloader<InstalledApp> {
|
||||
reportSize(path.fileSize())
|
||||
Files.copy(path, outputStream)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
[versions]
|
||||
ktx = "1.15.0"
|
||||
material3 = "1.3.1"
|
||||
ui-tooling = "1.7.5"
|
||||
ui-tooling = "1.7.6"
|
||||
viewmodel-lifecycle = "2.8.7"
|
||||
splash-screen = "1.0.1"
|
||||
activity = "1.9.3"
|
||||
appcompat = "1.7.0"
|
||||
preferences-datastore = "1.1.1"
|
||||
work-runtime = "2.10.0"
|
||||
compose-bom = "2024.11.00"
|
||||
compose-bom = "2024.12.01"
|
||||
accompanist = "0.34.0"
|
||||
placeholder = "1.1.2"
|
||||
reorderable = "1.5.2"
|
||||
@ -24,9 +24,9 @@ reimagined-navigation = "1.5.0"
|
||||
ktor = "2.3.9"
|
||||
markdown-renderer = "0.22.0"
|
||||
fading-edges = "1.0.4"
|
||||
kotlin = "2.0.21"
|
||||
android-gradle-plugin = "8.7.2"
|
||||
dev-tools-gradle-plugin = "2.0.21-1.0.27"
|
||||
kotlin = "2.1.0"
|
||||
android-gradle-plugin = "8.7.3"
|
||||
dev-tools-gradle-plugin = "2.1.0-1.0.29"
|
||||
about-libraries-gradle-plugin = "11.1.1"
|
||||
binary-compatibility-validator = "0.15.1"
|
||||
coil = "2.6.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user