feat: Add confirmation dialog to "Reset" options (#2576)

This commit is contained in:
brosssh
2025-06-10 16:38:05 +02:00
committed by GitHub
parent aebad0b0e2
commit 0992e63c28
10 changed files with 314 additions and 58 deletions

View File

@ -27,10 +27,10 @@ abstract class OptionDao {
abstract suspend fun createOptionGroup(group: OptionGroup) abstract suspend fun createOptionGroup(group: OptionGroup)
@Query("DELETE FROM option_groups WHERE patch_bundle = :uid") @Query("DELETE FROM option_groups WHERE patch_bundle = :uid")
abstract suspend fun clearForPatchBundle(uid: Int) abstract suspend fun resetOptionsForPatchBundle(uid: Int)
@Query("DELETE FROM option_groups WHERE package_name = :packageName") @Query("DELETE FROM option_groups WHERE package_name = :packageName")
abstract suspend fun clearForPackage(packageName: String) abstract suspend fun resetOptionsForPackage(packageName: String)
@Query("DELETE FROM option_groups") @Query("DELETE FROM option_groups")
abstract suspend fun reset() abstract suspend fun reset()

View File

@ -5,6 +5,7 @@ import androidx.room.Insert
import androidx.room.MapColumn import androidx.room.MapColumn
import androidx.room.Query import androidx.room.Query
import androidx.room.Transaction import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow
@Dao @Dao
abstract class SelectionDao { abstract class SelectionDao {
@ -34,11 +35,14 @@ abstract class SelectionDao {
@Insert @Insert
abstract suspend fun createSelection(selection: PatchSelection) abstract suspend fun createSelection(selection: PatchSelection)
@Query("SELECT package_name FROM patch_selections")
abstract fun getPackagesWithSelection(): Flow<List<String>>
@Query("DELETE FROM patch_selections WHERE patch_bundle = :uid") @Query("DELETE FROM patch_selections WHERE patch_bundle = :uid")
abstract suspend fun clearForPatchBundle(uid: Int) abstract suspend fun resetForPatchBundle(uid: Int)
@Query("DELETE FROM patch_selections WHERE package_name = :packageName") @Query("DELETE FROM patch_selections WHERE package_name = :packageName")
abstract suspend fun clearForPackage(packageName: String) abstract suspend fun resetForPackage(packageName: String)
@Query("DELETE FROM patch_selections") @Query("DELETE FROM patch_selections")
abstract suspend fun reset() abstract suspend fun reset()

View File

@ -76,7 +76,7 @@ class PatchOptionsRepository(db: AppDatabase) {
fun getPackagesWithSavedOptions() = fun getPackagesWithSavedOptions() =
dao.getPackagesWithOptions().map(Iterable<String>::toSet).distinctUntilChanged() dao.getPackagesWithOptions().map(Iterable<String>::toSet).distinctUntilChanged()
suspend fun clearOptionsForPackage(packageName: String) = dao.clearForPackage(packageName) suspend fun resetOptionsForPackage(packageName: String) = dao.resetOptionsForPackage(packageName)
suspend fun clearOptionsForPatchBundle(uid: Int) = dao.clearForPatchBundle(uid) suspend fun resetOptionsForPatchBundle(uid: Int) = dao.resetOptionsForPatchBundle(uid)
suspend fun reset() = dao.reset() suspend fun reset() = dao.reset()
} }

View File

@ -3,6 +3,8 @@ package app.revanced.manager.domain.repository
import app.revanced.manager.data.room.AppDatabase import app.revanced.manager.data.room.AppDatabase
import app.revanced.manager.data.room.AppDatabase.Companion.generateUid import app.revanced.manager.data.room.AppDatabase.Companion.generateUid
import app.revanced.manager.data.room.selection.PatchSelection import app.revanced.manager.data.room.selection.PatchSelection
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
class PatchSelectionRepository(db: AppDatabase) { class PatchSelectionRepository(db: AppDatabase) {
private val dao = db.selectionDao() private val dao = db.selectionDao()
@ -25,8 +27,15 @@ class PatchSelectionRepository(db: AppDatabase) {
) )
}) })
suspend fun clearSelection(packageName: String) { fun getPackagesWithSavedSelection() =
dao.clearForPackage(packageName) dao.getPackagesWithSelection().map(Iterable<String>::toSet).distinctUntilChanged()
suspend fun resetSelectionForPackage(packageName: String) {
dao.resetForPackage(packageName)
}
suspend fun resetSelectionForPatchBundle(uid: Int) {
dao.resetForPatchBundle(uid)
} }
suspend fun reset() = dao.reset() suspend fun reset() = dao.reset()
@ -34,7 +43,7 @@ class PatchSelectionRepository(db: AppDatabase) {
suspend fun export(bundleUid: Int): SerializedSelection = dao.exportSelection(bundleUid) suspend fun export(bundleUid: Int): SerializedSelection = dao.exportSelection(bundleUid)
suspend fun import(bundleUid: Int, selection: SerializedSelection) { suspend fun import(bundleUid: Int, selection: SerializedSelection) {
dao.clearForPatchBundle(bundleUid) dao.resetForPatchBundle(bundleUid)
dao.updateSelections(selection.entries.associate { (packageName, patches) -> dao.updateSelections(selection.entries.associate { (packageName, patches) ->
getOrCreateSelection(bundleUid, packageName) to patches.toSet() getOrCreateSelection(bundleUid, packageName) to patches.toSet()
}) })

View File

@ -13,11 +13,14 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import app.revanced.manager.domain.bundles.PatchBundleSource import app.revanced.manager.domain.bundles.PatchBundleSource
import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState
import kotlinx.coroutines.flow.map
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -54,6 +57,10 @@ fun BundleSelector(bundles: List<PatchBundleSource>, onFinish: (PatchBundleSourc
} }
bundles.forEach { bundles.forEach {
val name by it.nameState val name by it.nameState
val version by remember(it) {
it.propsFlow().map { props -> props?.version }
}.collectAsStateWithLifecycle(null)
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
@ -65,7 +72,7 @@ fun BundleSelector(bundles: List<PatchBundleSource>, onFinish: (PatchBundleSourc
} }
) { ) {
Text( Text(
name, "$name $version",
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface color = MaterialTheme.colorScheme.onSurface
) )

View File

@ -1,6 +1,17 @@
package app.revanced.manager.ui.component.settings package app.revanced.manager.ui.component.settings
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItemColors import androidx.compose.material3.ListItemColors
import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -10,6 +21,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@Composable @Composable
fun SettingsListItem( fun SettingsListItem(
@ -67,4 +82,48 @@ fun SettingsListItem(
colors = colors, colors = colors,
tonalElevation = tonalElevation, tonalElevation = tonalElevation,
shadowElevation = shadowElevation shadowElevation = shadowElevation
) )
@Composable
fun ExpandableSettingListItem(
headlineContent: String,
supportingContent: String,
expandableContent: @Composable () -> Unit
) {
var expanded by remember { mutableStateOf(false) }
Column(
modifier = Modifier
.fillMaxWidth()
.animateContentSize()
) {
SettingsListItem(
modifier = Modifier
.clickable{ expanded = !expanded },
headlineContent = headlineContent,
supportingContent = supportingContent,
trailingContent = {
Icon(
imageVector = if (expanded) Icons.Default.ExpandLess else Icons.Default.ExpandMore,
contentDescription = null
)
}
)
AnimatedVisibility(visible = expanded) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp, start = 16.dp, end = 16.dp)
.animateContentSize(
animationSpec = tween(
durationMillis = 500,
easing = FastOutSlowInEasing
)
)
) {
expandableContent()
}
}
}
}

View File

@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Key import androidx.compose.material.icons.outlined.Key
import androidx.compose.material.icons.outlined.WarningAmber
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -28,6 +29,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -42,11 +44,14 @@ import androidx.lifecycle.viewModelScope
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ColumnWithScrollbar import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.ConfirmDialog
import app.revanced.manager.ui.component.GroupHeader import app.revanced.manager.ui.component.GroupHeader
import app.revanced.manager.ui.component.PasswordField import app.revanced.manager.ui.component.PasswordField
import app.revanced.manager.ui.component.bundle.BundleSelector import app.revanced.manager.ui.component.bundle.BundleSelector
import app.revanced.manager.ui.component.settings.ExpandableSettingListItem
import app.revanced.manager.ui.component.settings.SettingsListItem import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.ImportExportViewModel import app.revanced.manager.ui.viewmodel.ImportExportViewModel
import app.revanced.manager.ui.viewmodel.ResetDialogState
import app.revanced.manager.util.toast import app.revanced.manager.util.toast
import app.revanced.manager.util.uiSafe import app.revanced.manager.util.uiSafe
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -59,6 +64,8 @@ fun ImportExportSettingsScreen(
vm: ImportExportViewModel = koinViewModel() vm: ImportExportViewModel = koinViewModel()
) { ) {
val context = LocalContext.current val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
var selectorDialog by rememberSaveable { mutableStateOf<(@Composable () -> Unit)?>(null) }
val importKeystoreLauncher = val importKeystoreLauncher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) { rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) {
@ -70,6 +77,7 @@ fun ImportExportSettingsScreen(
} }
val patchBundles by vm.patchBundles.collectAsStateWithLifecycle(initialValue = emptyList()) val patchBundles by vm.patchBundles.collectAsStateWithLifecycle(initialValue = emptyList())
val packagesWithSelections by vm.packagesWithSelection.collectAsStateWithLifecycle(initialValue = emptySet())
val packagesWithOptions by vm.packagesWithOptions.collectAsStateWithLifecycle(initialValue = emptySet()) val packagesWithOptions by vm.packagesWithOptions.collectAsStateWithLifecycle(initialValue = emptySet())
vm.selectionAction?.let { action -> vm.selectionAction?.let { action ->
@ -107,6 +115,20 @@ fun ImportExportSettingsScreen(
) )
} }
vm.resetDialogState?.let {
with(vm.resetDialogState!!) {
ConfirmDialog(
onDismiss = { vm.resetDialogState = null },
onConfirm = onConfirm,
title = stringResource(titleResId),
description = dialogOptionName?.let {
stringResource(descriptionResId, it)
} ?: stringResource(descriptionResId),
icon = Icons.Outlined.WarningAmber
)
}
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold( Scaffold(
@ -124,28 +146,7 @@ fun ImportExportSettingsScreen(
.fillMaxSize() .fillMaxSize()
.padding(paddingValues) .padding(paddingValues)
) { ) {
var showPackageSelector by rememberSaveable { selectorDialog?.invoke()
mutableStateOf(false)
}
var showBundleSelector by rememberSaveable {
mutableStateOf(false)
}
if (showPackageSelector) {
PackageSelector(packages = packagesWithOptions) { selected ->
selected?.let(vm::resetOptionsForPackage)
showPackageSelector = false
}
}
if (showBundleSelector) {
BundleSelector(bundles = patchBundles) { bundle ->
bundle?.let(vm::clearOptionsForBundle)
showBundleSelector = false
}
}
GroupHeader(stringResource(R.string.import_)) GroupHeader(stringResource(R.string.import_))
GroupItem( GroupItem(
@ -181,32 +182,126 @@ fun ImportExportSettingsScreen(
GroupHeader(stringResource(R.string.reset)) GroupHeader(stringResource(R.string.reset))
GroupItem( GroupItem(
onClick = vm::regenerateKeystore, onClick = {
vm.resetDialogState = ResetDialogState.Keystore {
vm.regenerateKeystore()
}
},
headline = R.string.regenerate_keystore, headline = R.string.regenerate_keystore,
description = R.string.regenerate_keystore_description description = R.string.regenerate_keystore_description
) )
GroupItem(
onClick = vm::resetSelection, // TODO: allow resetting selection for specific bundle or package name. ExpandableSettingListItem(
headline = R.string.reset_patch_selection, headlineContent = stringResource(R.string.reset_patch_selection),
description = R.string.reset_patch_selection_description supportingContent = stringResource(R.string.reset_patch_selection_description),
expandableContent = {
GroupItem(
onClick = {
vm.resetDialogState = ResetDialogState.PatchSelectionAll {
vm.resetSelection()
}
},
headline = R.string.patch_selection_reset_all,
description = R.string.patch_selection_reset_all_description
)
GroupItem(
onClick = {
selectorDialog = {
PackageSelector(packages = packagesWithSelections) { packageName ->
packageName?.also {
vm.resetDialogState =
ResetDialogState.PatchSelectionPackage(packageName) {
vm.resetSelectionForPackage(packageName)
}
}
selectorDialog = null
}
}
},
headline = R.string.patch_selection_reset_package,
description = R.string.patch_selection_reset_package_description
)
if (patchBundles.isNotEmpty()) {
GroupItem(
onClick = {
selectorDialog = {
BundleSelector(bundles = patchBundles) { bundle ->
bundle?.also {
coroutineScope.launch {
vm.resetDialogState =
ResetDialogState.PatchSelectionBundle(bundle.getName()) {
vm.resetSelectionForPatchBundle(bundle)
}
}
}
selectorDialog = null
}
}
},
headline = R.string.patch_selection_reset_bundle,
description = R.string.patch_selection_reset_bundle_description
)
}
}
) )
GroupItem(
onClick = vm::resetOptions, // TODO: patch options import/export. ExpandableSettingListItem(
headline = R.string.patch_options_reset_all, headlineContent = stringResource(R.string.reset_patch_options),
description = R.string.patch_options_reset_all_description, supportingContent = stringResource(R.string.reset_patch_options_description),
expandableContent = {
GroupItem(
onClick = {
vm.resetDialogState = ResetDialogState.PatchOptionsAll {
vm.resetOptions()
}
}, // TODO: patch options import/export.
headline = R.string.patch_options_reset_all,
description = R.string.patch_options_reset_all_description,
)
GroupItem(
onClick = {
selectorDialog = {
PackageSelector(packages = packagesWithOptions) { packageName ->
packageName?.also {
vm.resetDialogState =
ResetDialogState.PatchOptionPackage(packageName) {
vm.resetOptionsForPackage(packageName)
}
}
selectorDialog = null
}
}
},
headline = R.string.patch_options_reset_package,
description = R.string.patch_options_reset_package_description
)
if (patchBundles.isNotEmpty()) {
GroupItem(
onClick = {
selectorDialog = {
BundleSelector(bundles = patchBundles) { bundle ->
bundle?.also {
coroutineScope.launch {
vm.resetDialogState =
ResetDialogState.PatchOptionBundle(bundle.getName()) {
vm.resetOptionsForBundle(bundle)
}
}
}
selectorDialog = null
}
}
},
headline = R.string.patch_options_reset_bundle,
description = R.string.patch_options_reset_bundle_description,
)
}
}
) )
GroupItem(
onClick = { showPackageSelector = true },
headline = R.string.patch_options_reset_package,
description = R.string.patch_options_reset_package_description
)
if (patchBundles.size > 1) {
GroupItem(
onClick = { showBundleSelector = true },
headline = R.string.patch_options_reset_bundle,
description = R.string.patch_options_reset_bundle_description,
)
}
} }
} }
} }

View File

@ -4,6 +4,7 @@ import android.app.Application
import android.net.Uri import android.net.Uri
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -34,6 +35,59 @@ import java.nio.file.StandardCopyOption
import kotlin.io.path.deleteExisting import kotlin.io.path.deleteExisting
import kotlin.io.path.inputStream import kotlin.io.path.inputStream
sealed class ResetDialogState(
@StringRes val titleResId: Int,
@StringRes val descriptionResId: Int,
val onConfirm: () -> Unit,
val dialogOptionName: String? = null
) {
class Keystore(onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.regenerate_keystore,
descriptionResId = R.string.regenerate_keystore_dialog_description,
onConfirm = onConfirm
)
class PatchSelectionAll(onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_selection_reset_all,
descriptionResId = R.string.patch_selection_reset_all_dialog_description,
onConfirm = onConfirm
)
class PatchSelectionPackage(dialogOptionName:String, onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_selection_reset_package,
descriptionResId = R.string.patch_selection_reset_package_dialog_description,
onConfirm = onConfirm,
dialogOptionName = dialogOptionName
)
class PatchSelectionBundle(dialogOptionName: String, onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_selection_reset_bundle,
descriptionResId = R.string.patch_selection_reset_bundle_dialog_description,
onConfirm = onConfirm,
dialogOptionName = dialogOptionName
)
class PatchOptionsAll(onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_options_reset_all,
descriptionResId = R.string.patch_options_reset_all_dialog_description,
onConfirm = onConfirm
)
class PatchOptionPackage(dialogOptionName:String, onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_options_reset_package,
descriptionResId = R.string.patch_options_reset_package_dialog_description,
onConfirm = onConfirm,
dialogOptionName = dialogOptionName
)
class PatchOptionBundle(dialogOptionName: String, onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_options_reset_bundle,
descriptionResId = R.string.patch_options_reset_bundle_dialog_description,
onConfirm = onConfirm,
dialogOptionName = dialogOptionName
)
}
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
class ImportExportViewModel( class ImportExportViewModel(
private val app: Application, private val app: Application,
@ -51,15 +105,18 @@ class ImportExportViewModel(
private var keystoreImportPath by mutableStateOf<Path?>(null) private var keystoreImportPath by mutableStateOf<Path?>(null)
val showCredentialsDialog by derivedStateOf { keystoreImportPath != null } val showCredentialsDialog by derivedStateOf { keystoreImportPath != null }
var resetDialogState by mutableStateOf<ResetDialogState?>(null)
val packagesWithOptions = optionsRepository.getPackagesWithSavedOptions() val packagesWithOptions = optionsRepository.getPackagesWithSavedOptions()
val packagesWithSelection = selectionRepository.getPackagesWithSavedSelection()
fun resetOptionsForPackage(packageName: String) = viewModelScope.launch { fun resetOptionsForPackage(packageName: String) = viewModelScope.launch {
optionsRepository.clearOptionsForPackage(packageName) optionsRepository.resetOptionsForPackage(packageName)
app.toast(app.getString(R.string.patch_options_reset_toast)) app.toast(app.getString(R.string.patch_options_reset_toast))
} }
fun clearOptionsForBundle(patchBundle: PatchBundleSource) = viewModelScope.launch { fun resetOptionsForBundle(patchBundle: PatchBundleSource) = viewModelScope.launch {
optionsRepository.clearOptionsForPatchBundle(patchBundle.uid) optionsRepository.resetOptionsForPatchBundle(patchBundle.uid)
app.toast(app.getString(R.string.patch_options_reset_toast)) app.toast(app.getString(R.string.patch_options_reset_toast))
} }
@ -135,6 +192,16 @@ class ImportExportViewModel(
app.toast(app.getString(R.string.reset_patch_selection_success)) app.toast(app.getString(R.string.reset_patch_selection_success))
} }
fun resetSelectionForPackage(packageName: String) = viewModelScope.launch {
selectionRepository.resetSelectionForPackage(packageName)
app.toast(app.getString(R.string.reset_patch_selection_success))
}
fun resetSelectionForPatchBundle(patchBundle: PatchBundleSource) = viewModelScope.launch {
selectionRepository.resetSelectionForPatchBundle(patchBundle.uid)
app.toast(app.getString(R.string.reset_patch_selection_success))
}
fun executeSelectionAction(target: Uri) = viewModelScope.launch { fun executeSelectionAction(target: Uri) = viewModelScope.launch {
val source = selectedBundle!! val source = selectedBundle!!
val action = selectionAction!! val action = selectionAction!!

View File

@ -305,7 +305,7 @@ class SelectedAppInfoViewModel(
if (!persistConfiguration) return@launch if (!persistConfiguration) return@launch
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
selection?.let { selectionRepository.updateSelection(packageName, it) } selection?.let { selectionRepository.updateSelection(packageName, it) }
?: selectionRepository.clearSelection(packageName) ?: selectionRepository.resetSelectionForPackage(packageName)
optionsRepository.saveOptions(packageName, filteredOptions) optionsRepository.saveOptions(packageName, filteredOptions)
} }

View File

@ -118,6 +118,7 @@
<string name="export_keystore_success">Exported keystore</string> <string name="export_keystore_success">Exported keystore</string>
<string name="regenerate_keystore">Regenerate keystore</string> <string name="regenerate_keystore">Regenerate keystore</string>
<string name="regenerate_keystore_description">Generate a new keystore</string> <string name="regenerate_keystore_description">Generate a new keystore</string>
<string name="regenerate_keystore_dialog_description">You are about to regenerate your keystore the manager will use during the patching process.\n\nYou will not be able to update the previously installed apps from this source.</string>
<string name="regenerate_keystore_success">The keystore has been successfully replaced</string> <string name="regenerate_keystore_success">The keystore has been successfully replaced</string>
<string name="import_patch_selection">Import patch selection</string> <string name="import_patch_selection">Import patch selection</string>
<string name="import_patch_selection_description">Import patch selection from a JSON file</string> <string name="import_patch_selection_description">Import patch selection from a JSON file</string>
@ -129,12 +130,26 @@
<string name="export_patch_selection_success">Exported patch selection</string> <string name="export_patch_selection_success">Exported patch selection</string>
<string name="reset_patch_selection">Reset patch selection</string> <string name="reset_patch_selection">Reset patch selection</string>
<string name="reset_patch_selection_description">Reset the stored patch selection</string> <string name="reset_patch_selection_description">Reset the stored patch selection</string>
<string name="reset_patch_options">Reset patch options</string>
<string name="reset_patch_options_description">Reset the stored patch options</string>
<string name="reset_patch_selection_success">Patch selection has been reset</string> <string name="reset_patch_selection_success">Patch selection has been reset</string>
<string name="patch_selection_reset_all">Reset all patch selection</string>
<string name="patch_selection_reset_all_dialog_description">You are about to reset all the patch selections. You will need to manually select each patch again.</string>
<string name="patch_selection_reset_all_description">Reset all the patch selections</string>
<string name="patch_selection_reset_package">Reset patch selection for app</string>
<string name="patch_selection_reset_package_dialog_description">You are about to reset the patch selection for the app \"%s\". You will have to manually select each patch again.</string>
<string name="patch_selection_reset_package_description">Resets patch selection for a single app</string>
<string name="patch_selection_reset_bundle">Resets patch selection for bundle</string>
<string name="patch_selection_reset_bundle_dialog_description">You are about to reset the patch selection for the bundle \"%s\". You will have to manually select each patch again.</string>
<string name="patch_selection_reset_bundle_description">Resets the patch selection for all patches in a bundle</string>
<string name="patch_options_reset_package">Reset patch options for app</string> <string name="patch_options_reset_package">Reset patch options for app</string>
<string name="patch_options_reset_package_dialog_description">You are about to reset the patch options for the app \"%s\". You will have to reapply each option again.</string>
<string name="patch_options_reset_package_description">Resets patch options for a single app</string> <string name="patch_options_reset_package_description">Resets patch options for a single app</string>
<string name="patch_options_reset_bundle">Resets patch options for bundle</string> <string name="patch_options_reset_bundle">Resets patch options for bundle</string>
<string name="patch_options_reset_bundle_dialog_description">You are about to reset the patch options for the bundle \"%s\". You will have to reapply each option again.</string>
<string name="patch_options_reset_bundle_description">Resets patch options for all patches in a bundle</string> <string name="patch_options_reset_bundle_description">Resets patch options for all patches in a bundle</string>
<string name="patch_options_reset_all">Reset patch options</string> <string name="patch_options_reset_all">Reset patch options</string>
<string name="patch_options_reset_all_dialog_description">You are about to reset patch options. You will have to reapply each option again.</string>
<string name="patch_options_reset_all_description">Resets all patch options</string> <string name="patch_options_reset_all_description">Resets all patch options</string>
<string name="downloader_plugins">Plugins</string> <string name="downloader_plugins">Plugins</string>
<string name="downloader_plugin_state_trusted">Trusted</string> <string name="downloader_plugin_state_trusted">Trusted</string>