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