mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-04-29 21:44:26 +02:00
feat: improve the safeguards (#2038)
This commit is contained in:
parent
3f4a234915
commit
1ee1330e47
@ -15,7 +15,6 @@ class PreferencesManager(
|
||||
val multithreadingDexFileWriter = booleanPreference("multithreading_dex_file_writer", true)
|
||||
val useProcessRuntime = booleanPreference("use_process_runtime", false)
|
||||
val patcherProcessMemoryLimit = intPreference("process_runtime_memory_limit", 700)
|
||||
val disablePatchVersionCompatCheck = booleanPreference("disable_patch_version_compatibility_check", false)
|
||||
|
||||
val keystoreCommonName = stringPreference("keystore_cn", KeystoreManager.DEFAULT)
|
||||
val keystorePass = stringPreference("keystore_pass", KeystoreManager.DEFAULT)
|
||||
@ -25,8 +24,8 @@ class PreferencesManager(
|
||||
val firstLaunch = booleanPreference("first_launch", true)
|
||||
val managerAutoUpdates = booleanPreference("manager_auto_updates", false)
|
||||
|
||||
val disablePatchVersionCompatCheck = booleanPreference("disable_patch_version_compatibility_check", false)
|
||||
val disableSelectionWarning = booleanPreference("disable_selection_warning", false)
|
||||
val enableSelectionWarningCountdown = booleanPreference("enable_selection_warning_countdown", true)
|
||||
|
||||
val disableUniversalPatchWarning = booleanPreference("disable_universal_patch_warning", false)
|
||||
val suggestedVersionSafeguard = booleanPreference("suggested_version_safeguard", true)
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
package app.revanced.manager.ui.component
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
fun Countdown(start: Int, content: @Composable (Int) -> Unit) {
|
||||
var timer by rememberSaveable(start) {
|
||||
mutableStateOf(start)
|
||||
}
|
||||
LaunchedEffect(timer) {
|
||||
if (timer == 0) {
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
delay(1000L)
|
||||
timer -= 1
|
||||
}
|
||||
|
||||
content(timer)
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package app.revanced.manager.ui.component
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.WarningAmber
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.revanced.manager.R
|
||||
|
||||
@Composable
|
||||
fun DangerousActionDialogBase(
|
||||
onCancel: () -> Unit,
|
||||
confirmButton: @Composable (Boolean) -> Unit,
|
||||
@StringRes title: Int,
|
||||
body: String,
|
||||
) {
|
||||
var dismissPermanently by rememberSaveable {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onCancel,
|
||||
confirmButton = {
|
||||
confirmButton(dismissPermanently)
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onCancel) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
Icon(Icons.Outlined.WarningAmber, null)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(title),
|
||||
style = MaterialTheme.typography.headlineSmall.copy(textAlign = TextAlign.Center),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
horizontalAlignment = Alignment.Start
|
||||
) {
|
||||
Text(
|
||||
text = body,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(0.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
dismissPermanently = !dismissPermanently
|
||||
}
|
||||
) {
|
||||
Checkbox(
|
||||
checked = dismissPermanently,
|
||||
onCheckedChange = {
|
||||
dismissPermanently = it
|
||||
}
|
||||
)
|
||||
Text(stringResource(R.string.permanent_dismiss))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package app.revanced.manager.ui.component
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.revanced.manager.R
|
||||
|
||||
@Composable
|
||||
fun NonSuggestedVersionDialog(suggestedVersion: String, onCancel: () -> Unit, onContinue: (Boolean) -> Unit) {
|
||||
DangerousActionDialogBase(
|
||||
onCancel = onCancel,
|
||||
confirmButton = { dismissPermanently ->
|
||||
TextButton(
|
||||
onClick = { onContinue(dismissPermanently) }
|
||||
) {
|
||||
Text(stringResource(R.string.continue_))
|
||||
}
|
||||
},
|
||||
title = R.string.non_suggested_version_warning_title,
|
||||
body = stringResource(R.string.non_suggested_version_warning_description, suggestedVersion),
|
||||
)
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package app.revanced.manager.ui.component
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.WarningAmber
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import app.revanced.manager.R
|
||||
|
||||
@Composable
|
||||
fun SafeguardDialog(
|
||||
onDismiss: () -> Unit,
|
||||
@StringRes title: Int,
|
||||
body: String,
|
||||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
confirmButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text(stringResource(R.string.ok))
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
Icon(Icons.Outlined.WarningAmber, null)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(title),
|
||||
style = MaterialTheme.typography.headlineSmall.copy(textAlign = TextAlign.Center)
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(body)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NonSuggestedVersionDialog(suggestedVersion: String, onDismiss: () -> Unit) {
|
||||
SafeguardDialog(
|
||||
onDismiss = onDismiss,
|
||||
title = R.string.non_suggested_version_warning_title,
|
||||
body = stringResource(R.string.non_suggested_version_warning_description, suggestedVersion),
|
||||
)
|
||||
}
|
@ -70,8 +70,7 @@ fun AppSelectorScreen(
|
||||
vm.nonSuggestedVersionDialogSubject?.let {
|
||||
NonSuggestedVersionDialog(
|
||||
suggestedVersion = suggestedVersions[it.packageName].orEmpty(),
|
||||
onCancel = vm::dismissNonSuggestedVersionDialog,
|
||||
onContinue = vm::continueWithNonSuggestedVersion,
|
||||
onDismiss = vm::dismissNonSuggestedVersionDialog
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import androidx.compose.material.icons.outlined.Restore
|
||||
import androidx.compose.material.icons.outlined.Save
|
||||
import androidx.compose.material.icons.outlined.Search
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.WarningAmber
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@ -37,7 +38,6 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@ -48,17 +48,16 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.domain.manager.PreferencesManager
|
||||
import app.revanced.manager.patcher.patch.Option
|
||||
import app.revanced.manager.patcher.patch.PatchInfo
|
||||
import app.revanced.manager.ui.component.AppTopBar
|
||||
import app.revanced.manager.ui.component.Countdown
|
||||
import app.revanced.manager.ui.component.DangerousActionDialogBase
|
||||
import app.revanced.manager.ui.component.SafeguardDialog
|
||||
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.SearchView
|
||||
import app.revanced.manager.ui.component.patches.OptionItem
|
||||
@ -70,7 +69,6 @@ import app.revanced.manager.util.Options
|
||||
import app.revanced.manager.util.PatchSelection
|
||||
import app.revanced.manager.util.isScrollingUp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@ -160,10 +158,16 @@ fun PatchesSelectorScreen(
|
||||
)
|
||||
}
|
||||
|
||||
vm.pendingSelectionAction?.let {
|
||||
SelectionWarningDialog(
|
||||
onCancel = vm::dismissSelectionWarning,
|
||||
onConfirm = vm::confirmSelectionWarning
|
||||
var showSelectionWarning by rememberSaveable {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
if (showSelectionWarning) {
|
||||
SelectionWarningDialog(onDismiss = { showSelectionWarning = false })
|
||||
}
|
||||
vm.pendingUniversalPatchAction?.let {
|
||||
UniversalPatchWarningDialog(
|
||||
onCancel = vm::dismissUniversalPatchWarning,
|
||||
onConfirm = vm::confirmUniversalPatchWarning
|
||||
)
|
||||
}
|
||||
|
||||
@ -196,9 +200,9 @@ fun PatchesSelectorScreen(
|
||||
),
|
||||
onToggle = {
|
||||
if (vm.selectionWarningEnabled) {
|
||||
vm.pendingSelectionAction = {
|
||||
vm.togglePatch(uid, patch)
|
||||
}
|
||||
showSelectionWarning = true
|
||||
} else if (vm.universalPatchWarningEnabled && patch.compatiblePackages == null) {
|
||||
vm.pendingUniversalPatchAction = { vm.togglePatch(uid, patch) }
|
||||
} else {
|
||||
vm.togglePatch(uid, patch)
|
||||
}
|
||||
@ -369,36 +373,43 @@ fun PatchesSelectorScreen(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SelectionWarningDialog(
|
||||
fun SelectionWarningDialog(onDismiss: () -> Unit) {
|
||||
SafeguardDialog(
|
||||
onDismiss = onDismiss,
|
||||
title = R.string.warning,
|
||||
body = stringResource(R.string.selection_warning_description),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UniversalPatchWarningDialog(
|
||||
onCancel: () -> Unit,
|
||||
onConfirm: (Boolean) -> Unit
|
||||
onConfirm: () -> Unit
|
||||
) {
|
||||
val prefs: PreferencesManager = koinInject()
|
||||
|
||||
DangerousActionDialogBase(
|
||||
onCancel = onCancel,
|
||||
confirmButton = { dismissPermanently ->
|
||||
val enableCountdown by prefs.enableSelectionWarningCountdown.getAsState()
|
||||
|
||||
Countdown(start = if (enableCountdown) 3 else 0) { timer ->
|
||||
LaunchedEffect(timer) {
|
||||
if (timer == 0) prefs.enableSelectionWarningCountdown.update(false)
|
||||
}
|
||||
|
||||
TextButton(
|
||||
onClick = { onConfirm(dismissPermanently) },
|
||||
enabled = timer == 0
|
||||
) {
|
||||
val text =
|
||||
if (timer == 0) stringResource(R.string.continue_) else stringResource(
|
||||
R.string.selection_warning_continue_countdown, timer
|
||||
)
|
||||
Text(text, color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
AlertDialog(
|
||||
onDismissRequest = onCancel,
|
||||
confirmButton = {
|
||||
TextButton(onClick = onConfirm) {
|
||||
Text(stringResource(R.string.continue_))
|
||||
}
|
||||
},
|
||||
title = R.string.selection_warning_title,
|
||||
body = stringResource(R.string.selection_warning_description),
|
||||
dismissButton = {
|
||||
TextButton(onClick = onCancel) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
Icon(Icons.Outlined.WarningAmber, null)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.warning),
|
||||
style = MaterialTheme.typography.headlineSmall.copy(textAlign = TextAlign.Center)
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.universal_patch_warning_description))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,7 @@ fun VersionSelectorScreen(
|
||||
if (viewModel.showNonSuggestedVersionDialog)
|
||||
NonSuggestedVersionDialog(
|
||||
suggestedVersion = viewModel.requiredVersion.orEmpty(),
|
||||
onCancel = viewModel::dismissNonSuggestedVersionDialog,
|
||||
onContinue = viewModel::continueWithNonSuggestedVersion,
|
||||
onDismiss = viewModel::dismissNonSuggestedVersionDialog
|
||||
)
|
||||
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
@ -126,12 +126,24 @@ fun AdvancedSettingsScreen(
|
||||
headline = R.string.patch_compat_check,
|
||||
description = R.string.patch_compat_check_description
|
||||
)
|
||||
BooleanItem(
|
||||
preference = vm.prefs.disableUniversalPatchWarning,
|
||||
coroutineScope = vm.viewModelScope,
|
||||
headline = R.string.universal_patches_safeguard,
|
||||
description = R.string.universal_patches_safeguard_description
|
||||
)
|
||||
BooleanItem(
|
||||
preference = vm.prefs.suggestedVersionSafeguard,
|
||||
coroutineScope = vm.viewModelScope,
|
||||
headline = R.string.suggested_version_safeguard,
|
||||
description = R.string.suggested_version_safeguard_description
|
||||
)
|
||||
BooleanItem(
|
||||
preference = vm.prefs.disableSelectionWarning,
|
||||
coroutineScope = vm.viewModelScope,
|
||||
headline = R.string.patch_selection_safeguard,
|
||||
description = R.string.patch_selection_safeguard_description
|
||||
)
|
||||
|
||||
GroupHeader(stringResource(R.string.device))
|
||||
SettingsListItem(
|
||||
|
@ -3,14 +3,12 @@ package app.revanced.manager.ui.viewmodel
|
||||
import android.app.Application
|
||||
import android.content.pm.PackageInfo
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.domain.manager.PreferencesManager
|
||||
import app.revanced.manager.domain.repository.PatchBundleRepository
|
||||
import app.revanced.manager.ui.model.SelectedApp
|
||||
import app.revanced.manager.util.PM
|
||||
@ -25,8 +23,7 @@ import java.nio.file.Files
|
||||
class AppSelectorViewModel(
|
||||
private val app: Application,
|
||||
private val pm: PM,
|
||||
private val patchBundleRepository: PatchBundleRepository,
|
||||
private val prefs: PreferencesManager,
|
||||
private val patchBundleRepository: PatchBundleRepository
|
||||
) : ViewModel() {
|
||||
private val inputFile = File(app.cacheDir, "input.apk").also {
|
||||
it.delete()
|
||||
@ -46,13 +43,6 @@ class AppSelectorViewModel(
|
||||
nonSuggestedVersionDialogSubject = null
|
||||
}
|
||||
|
||||
fun continueWithNonSuggestedVersion(dismissPermanently: Boolean) = viewModelScope.launch {
|
||||
if (dismissPermanently) prefs.suggestedVersionSafeguard.update(false)
|
||||
|
||||
nonSuggestedVersionDialogSubject?.let(onStorageClick)
|
||||
dismissNonSuggestedVersionDialog()
|
||||
}
|
||||
|
||||
fun handleStorageResult(uri: Uri) = viewModelScope.launch {
|
||||
val selectedApp = withContext(Dispatchers.IO) {
|
||||
loadSelectedFile(uri)
|
||||
|
@ -47,10 +47,12 @@ class PatchesSelectorViewModel(input: Params) : ViewModel(), KoinComponent {
|
||||
private val packageName = input.app.packageName
|
||||
val appVersion = input.app.version
|
||||
|
||||
var pendingSelectionAction by mutableStateOf<(() -> Unit)?>(null)
|
||||
var pendingUniversalPatchAction by mutableStateOf<(() -> Unit)?>(null)
|
||||
|
||||
var selectionWarningEnabled by mutableStateOf(true)
|
||||
private set
|
||||
var universalPatchWarningEnabled by mutableStateOf(true)
|
||||
private set
|
||||
|
||||
val allowIncompatiblePatches =
|
||||
get<PreferencesManager>().disablePatchVersionCompatCheck.getBlocking()
|
||||
@ -59,6 +61,8 @@ class PatchesSelectorViewModel(input: Params) : ViewModel(), KoinComponent {
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
universalPatchWarningEnabled = !prefs.disableUniversalPatchWarning.get()
|
||||
|
||||
if (prefs.disableSelectionWarning.get()) {
|
||||
selectionWarningEnabled = false
|
||||
return@launch
|
||||
@ -131,21 +135,15 @@ class PatchesSelectorViewModel(input: Params) : ViewModel(), KoinComponent {
|
||||
customPatchSelection = selection.put(bundle, newPatches)
|
||||
}
|
||||
|
||||
fun confirmSelectionWarning(dismissPermanently: Boolean) {
|
||||
selectionWarningEnabled = false
|
||||
fun confirmUniversalPatchWarning() {
|
||||
universalPatchWarningEnabled = false
|
||||
|
||||
pendingSelectionAction?.invoke()
|
||||
pendingSelectionAction = null
|
||||
|
||||
if (!dismissPermanently) return
|
||||
|
||||
viewModelScope.launch {
|
||||
prefs.disableSelectionWarning.update(true)
|
||||
}
|
||||
pendingUniversalPatchAction?.invoke()
|
||||
pendingUniversalPatchAction = null
|
||||
}
|
||||
|
||||
fun dismissSelectionWarning() {
|
||||
pendingSelectionAction = null
|
||||
fun dismissUniversalPatchWarning() {
|
||||
pendingUniversalPatchAction = null
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
|
@ -162,12 +162,6 @@ class VersionSelectorViewModel(
|
||||
nonSuggestedVersionDialogSubject = null
|
||||
}
|
||||
|
||||
fun continueWithNonSuggestedVersion(dismissPermanently: Boolean) = viewModelScope.launch {
|
||||
if (dismissPermanently) prefs.suggestedVersionSafeguard.update(false)
|
||||
selectedVersion = nonSuggestedVersionDialogSubject
|
||||
dismissNonSuggestedVersionDialog()
|
||||
}
|
||||
|
||||
fun select(app: SelectedApp) {
|
||||
if (requiredVersion != null && app.version != requiredVersion) {
|
||||
nonSuggestedVersionDialogSubject = app
|
||||
|
@ -76,6 +76,10 @@
|
||||
<string name="patch_compat_check_description">The check restricts patches to supported app versions</string>
|
||||
<string name="suggested_version_safeguard">Require suggested app version</string>
|
||||
<string name="suggested_version_safeguard_description">Enforce selection of the suggested app version</string>
|
||||
<string name="patch_selection_safeguard">Allow changing patch selection</string>
|
||||
<string name="patch_selection_safeguard_description">Do not prevent selecting or deselecting patches</string>
|
||||
<string name="universal_patches_safeguard">Disable universal patch warning</string>
|
||||
<string name="universal_patches_safeguard_description">Disables the warning that appears when you try to select universal patches</string>
|
||||
<string name="import_keystore">Import keystore</string>
|
||||
<string name="import_keystore_description">Import a custom keystore</string>
|
||||
<string name="import_keystore_dialog_title">Enter keystore credentials</string>
|
||||
@ -134,6 +138,7 @@
|
||||
<string name="apply">Apply</string>
|
||||
<string name="help">Help</string>
|
||||
<string name="back">Back</string>
|
||||
<string name="warning">Warning</string>
|
||||
<string name="add">Add</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="system">System</string>
|
||||
@ -190,10 +195,10 @@
|
||||
<string name="patch_selection_reset_toast">Patch selection and options has been reset to recommended defaults</string>
|
||||
<string name="patch_options_reset_toast">Patch options have been reset</string>
|
||||
<string name="non_suggested_version_warning_title">Non suggested version</string>
|
||||
<string name="non_suggested_version_warning_description">The version of the app you have selected does not match the suggested version.\nPlease use the suggested version: %s</string>
|
||||
<string name="non_suggested_version_warning_description">The version of the app you have selected does not match the suggested version.\nPlease use the suggested version: %s\n\nTo continue anyway, disable \"Require suggested app version\" in the advanced settings.</string>
|
||||
<string name="selection_warning_title">Stop using defaults?</string>
|
||||
<string name="selection_warning_description">You may encounter issues when not using the default patch selection and options.</string>
|
||||
<string name="selection_warning_continue_countdown">Continue (%ds)</string>
|
||||
<string name="selection_warning_description">It is recommended to use the default patch selection and options. Changing them may result in unexpected issues.\n\nYou need to turn on \"Allow changing patch selection\" in the advanced settings before toggling patches.</string>
|
||||
<string name="universal_patch_warning_description">Universal patches have a more generalized use and do not work as reliably as patches that target specific apps. You may encounter issues while using them.\n\nThis warning can be disabled in the advanced settings.</string>
|
||||
<string name="supported">Supported</string>
|
||||
<string name="universal">Universal</string>
|
||||
<string name="unsupported">Unsupported</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user