mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2024-11-10 01:01:56 +01:00
feat: Migrate more buttons
This commit is contained in:
parent
bfbf27024d
commit
968c665791
7 changed files with 306 additions and 272 deletions
|
@ -10,26 +10,9 @@ import androidx.compose.foundation.layout.PaddingValues
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Topic
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
|
@ -37,6 +20,8 @@ import androidx.compose.ui.unit.dp
|
|||
import app.revanced.manager.R
|
||||
import app.revanced.manager.ui.component.AlertDialogExtended
|
||||
import app.revanced.manager.ui.component.TextHorizontalPadding
|
||||
import app.revanced.manager.ui.component.haptics.HapticCheckbox
|
||||
import app.revanced.manager.ui.component.haptics.HapticRadioButton
|
||||
import app.revanced.manager.ui.model.BundleType
|
||||
import app.revanced.manager.util.APK_MIMETYPE
|
||||
import app.revanced.manager.util.JAR_MIMETYPE
|
||||
|
@ -45,7 +30,7 @@ import app.revanced.manager.util.JAR_MIMETYPE
|
|||
fun ImportPatchBundleDialog(
|
||||
onDismiss: () -> Unit,
|
||||
onRemoteSubmit: (String, Boolean) -> Unit,
|
||||
onLocalSubmit: (Uri, Uri?) -> Unit
|
||||
onLocalSubmit: (Uri, Uri?) -> Unit,
|
||||
) {
|
||||
var currentStep by rememberSaveable { mutableIntStateOf(0) }
|
||||
var bundleType by rememberSaveable { mutableStateOf(BundleType.Remote) }
|
||||
|
@ -72,7 +57,8 @@ fun ImportPatchBundleDialog(
|
|||
integrationsActivityLauncher.launch(APK_MIMETYPE)
|
||||
}
|
||||
|
||||
val steps = listOf<@Composable () -> Unit>(
|
||||
val steps =
|
||||
listOf<@Composable () -> Unit>(
|
||||
{
|
||||
SelectBundleTypeStep(bundleType) { selectedType ->
|
||||
bundleType = selectedType
|
||||
|
@ -88,9 +74,9 @@ fun ImportPatchBundleDialog(
|
|||
{ launchPatchActivity() },
|
||||
{ launchIntegrationsActivity() },
|
||||
{ remoteUrl = it },
|
||||
{ autoUpdate = it }
|
||||
{ autoUpdate = it },
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
val inputsAreValid by remember {
|
||||
|
@ -114,16 +100,17 @@ fun ImportPatchBundleDialog(
|
|||
enabled = inputsAreValid,
|
||||
onClick = {
|
||||
when (bundleType) {
|
||||
BundleType.Local -> patchBundle?.let {
|
||||
BundleType.Local ->
|
||||
patchBundle?.let {
|
||||
onLocalSubmit(
|
||||
it,
|
||||
integrations
|
||||
integrations,
|
||||
)
|
||||
}
|
||||
|
||||
BundleType.Remote -> onRemoteSubmit(remoteUrl, autoUpdate)
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.add))
|
||||
}
|
||||
|
@ -144,53 +131,55 @@ fun ImportPatchBundleDialog(
|
|||
}
|
||||
}
|
||||
},
|
||||
textHorizontalPadding = PaddingValues(0.dp)
|
||||
textHorizontalPadding = PaddingValues(0.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SelectBundleTypeStep(
|
||||
bundleType: BundleType,
|
||||
onBundleTypeSelected: (BundleType) -> Unit
|
||||
onBundleTypeSelected: (BundleType) -> Unit,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 24.dp),
|
||||
text = stringResource(R.string.select_bundle_type_dialog_description)
|
||||
text = stringResource(R.string.select_bundle_type_dialog_description),
|
||||
)
|
||||
Column {
|
||||
ListItem(
|
||||
modifier = Modifier.clickable(
|
||||
modifier =
|
||||
Modifier.clickable(
|
||||
role = Role.RadioButton,
|
||||
onClick = { onBundleTypeSelected(BundleType.Remote) }
|
||||
onClick = { onBundleTypeSelected(BundleType.Remote) },
|
||||
),
|
||||
headlineContent = { Text(stringResource(R.string.enter_url)) },
|
||||
overlineContent = { Text(stringResource(R.string.recommended)) },
|
||||
supportingContent = { Text(stringResource(R.string.remote_bundle_description)) },
|
||||
leadingContent = {
|
||||
RadioButton(
|
||||
HapticRadioButton(
|
||||
selected = bundleType == BundleType.Remote,
|
||||
onClick = null
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp))
|
||||
ListItem(
|
||||
modifier = Modifier.clickable(
|
||||
modifier =
|
||||
Modifier.clickable(
|
||||
role = Role.RadioButton,
|
||||
onClick = { onBundleTypeSelected(BundleType.Local) }
|
||||
onClick = { onBundleTypeSelected(BundleType.Local) },
|
||||
),
|
||||
headlineContent = { Text(stringResource(R.string.select_from_storage)) },
|
||||
supportingContent = { Text(stringResource(R.string.local_bundle_description)) },
|
||||
overlineContent = { },
|
||||
leadingContent = {
|
||||
RadioButton(
|
||||
HapticRadioButton(
|
||||
selected = bundleType == BundleType.Local,
|
||||
onClick = null
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -207,67 +196,92 @@ fun ImportBundleStep(
|
|||
launchPatchActivity: () -> Unit,
|
||||
launchIntegrationsActivity: () -> Unit,
|
||||
onRemoteUrlChange: (String) -> Unit,
|
||||
onAutoUpdateChange: (Boolean) -> Unit
|
||||
onAutoUpdateChange: (Boolean) -> Unit,
|
||||
) {
|
||||
Column {
|
||||
when (bundleType) {
|
||||
BundleType.Local -> {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 8.dp)
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
) {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(stringResource(R.string.patch_bundle_field))
|
||||
},
|
||||
supportingContent = { Text(stringResource(if (patchBundle != null) R.string.file_field_set else R.string.file_field_not_set)) },
|
||||
supportingContent = {
|
||||
Text(
|
||||
stringResource(
|
||||
if (patchBundle !=
|
||||
null
|
||||
) {
|
||||
R.string.file_field_set
|
||||
} else {
|
||||
R.string.file_field_not_set
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
trailingContent = {
|
||||
IconButton(onClick = launchPatchActivity) {
|
||||
Icon(imageVector = Icons.Default.Topic, contentDescription = null)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.clickable { launchPatchActivity() }
|
||||
modifier = Modifier.clickable { launchPatchActivity() },
|
||||
)
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(stringResource(R.string.integrations_field))
|
||||
},
|
||||
supportingContent = { Text(stringResource(if (integrations != null) R.string.file_field_set else R.string.file_field_not_set)) },
|
||||
supportingContent = {
|
||||
Text(
|
||||
stringResource(
|
||||
if (integrations !=
|
||||
null
|
||||
) {
|
||||
R.string.file_field_set
|
||||
} else {
|
||||
R.string.file_field_not_set
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
trailingContent = {
|
||||
IconButton(onClick = launchIntegrationsActivity) {
|
||||
Icon(imageVector = Icons.Default.Topic, contentDescription = null)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.clickable { launchIntegrationsActivity() }
|
||||
modifier = Modifier.clickable { launchIntegrationsActivity() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BundleType.Remote -> {
|
||||
Column(
|
||||
modifier = Modifier.padding(TextHorizontalPadding)
|
||||
modifier = Modifier.padding(TextHorizontalPadding),
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = remoteUrl,
|
||||
onValueChange = onRemoteUrlChange,
|
||||
label = { Text(stringResource(R.string.bundle_url)) }
|
||||
label = { Text(stringResource(R.string.bundle_url)) },
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 8.dp)
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
) {
|
||||
ListItem(
|
||||
modifier = Modifier.clickable(
|
||||
modifier =
|
||||
Modifier.clickable(
|
||||
role = Role.Checkbox,
|
||||
onClick = { onAutoUpdateChange(!autoUpdate) }
|
||||
onClick = { onAutoUpdateChange(!autoUpdate) },
|
||||
),
|
||||
headlineContent = { Text(stringResource(R.string.auto_update)) },
|
||||
leadingContent = {
|
||||
CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) {
|
||||
Checkbox(
|
||||
HapticCheckbox(
|
||||
checked = autoUpdate,
|
||||
onCheckedChange = {
|
||||
onAutoUpdateChange(!autoUpdate)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
package app.revanced.manager.ui.component.haptics
|
||||
|
||||
import android.view.HapticFeedbackConstants
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.RadioButtonColors
|
||||
import androidx.compose.material3.RadioButtonDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
|
||||
@Composable
|
||||
fun HapticRadioButton (
|
||||
fun HapticRadioButton(
|
||||
selected: Boolean,
|
||||
onClick: (() -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
colors: RadioButtonColors = RadioButtonDefaults.colors(),
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
) {
|
||||
val selectedState = remember { mutableStateOf(selected) }
|
||||
|
||||
|
@ -42,6 +37,6 @@ fun HapticRadioButton (
|
|||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
colors = colors,
|
||||
interactionSource = interactionSource
|
||||
interactionSource = interactionSource,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
|
@ -16,11 +15,12 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.data.room.apps.installed.InstallType
|
||||
import app.revanced.manager.ui.component.haptics.HapticRadioButton
|
||||
|
||||
@Composable
|
||||
fun InstallPickerDialog(
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (InstallType) -> Unit
|
||||
onConfirm: (InstallType) -> Unit,
|
||||
) {
|
||||
var selectedInstallType by rememberSaveable { mutableStateOf(InstallType.DEFAULT) }
|
||||
|
||||
|
@ -36,7 +36,7 @@ fun InstallPickerDialog(
|
|||
onClick = {
|
||||
onConfirm(selectedInstallType)
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.install_app))
|
||||
}
|
||||
|
@ -44,19 +44,19 @@ fun InstallPickerDialog(
|
|||
title = { Text(stringResource(R.string.select_install_type)) },
|
||||
text = {
|
||||
Column {
|
||||
InstallType.values().forEach {
|
||||
InstallType.entries.forEach {
|
||||
ListItem(
|
||||
modifier = Modifier.clickable { selectedInstallType = it },
|
||||
leadingContent = {
|
||||
RadioButton(
|
||||
HapticRadioButton(
|
||||
selected = selectedInstallType == it,
|
||||
onClick = null
|
||||
onClick = null,
|
||||
)
|
||||
},
|
||||
headlineContent = { Text(stringResource(it.stringResource)) }
|
||||
headlineContent = { Text(stringResource(it.stringResource)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
|
@ -31,13 +31,11 @@ import androidx.compose.material3.AlertDialog
|
|||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
|
@ -65,6 +63,8 @@ import app.revanced.manager.ui.component.AppTopBar
|
|||
import app.revanced.manager.ui.component.FloatInputDialog
|
||||
import app.revanced.manager.ui.component.IntInputDialog
|
||||
import app.revanced.manager.ui.component.LongInputDialog
|
||||
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
||||
import app.revanced.manager.ui.component.haptics.HapticRadioButton
|
||||
import app.revanced.manager.ui.component.haptics.HapticSwitch
|
||||
import app.revanced.manager.util.isScrollingUp
|
||||
import app.revanced.manager.util.mutableStateSetOf
|
||||
|
@ -443,7 +443,7 @@ private class PresetOptionEditor<T : Any>(
|
|||
headlineContent = { Text(title) },
|
||||
supportingContent = value?.toString()?.let { { Text(it) } },
|
||||
leadingContent = {
|
||||
RadioButton(
|
||||
HapticRadioButton(
|
||||
selected = selectedPreset == presetKey,
|
||||
onClick = { selectedPreset = presetKey },
|
||||
)
|
||||
|
@ -601,7 +601,7 @@ private class ListOptionEditor<T : Serializable>(
|
|||
floatingActionButton = {
|
||||
if (deleteMode) return@Scaffold
|
||||
|
||||
ExtendedFloatingActionButton(
|
||||
HapticExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.add)) },
|
||||
icon = { Icon(Icons.Outlined.Add, null) },
|
||||
expanded = lazyListState.isScrollingUp,
|
||||
|
|
|
@ -35,6 +35,7 @@ import app.revanced.manager.ui.component.AppTopBar
|
|||
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.SafeguardDialog
|
||||
import app.revanced.manager.ui.component.SearchView
|
||||
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
||||
import app.revanced.manager.ui.component.patches.OptionItem
|
||||
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel
|
||||
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_SUPPORTED
|
||||
|
@ -50,12 +51,13 @@ import kotlinx.coroutines.launch
|
|||
fun PatchesSelectorScreen(
|
||||
onSave: (PatchSelection?, Options) -> Unit,
|
||||
onBackClick: () -> Unit,
|
||||
vm: PatchesSelectorViewModel
|
||||
vm: PatchesSelectorViewModel,
|
||||
) {
|
||||
val bundles by vm.bundlesFlow.collectAsStateWithLifecycle(initialValue = emptyList())
|
||||
val pagerState = rememberPagerState(
|
||||
val pagerState =
|
||||
rememberPagerState(
|
||||
initialPage = 0,
|
||||
initialPageOffsetFraction = 0f
|
||||
initialPageOffsetFraction = 0f,
|
||||
) {
|
||||
bundles.size
|
||||
}
|
||||
|
@ -74,30 +76,30 @@ fun PatchesSelectorScreen(
|
|||
ModalBottomSheet(
|
||||
onDismissRequest = {
|
||||
showBottomSheet = false
|
||||
}
|
||||
},
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 24.dp)
|
||||
modifier = Modifier.padding(horizontal = 24.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.patch_selector_sheet_filter_title),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
modifier = Modifier.padding(bottom = 16.dp),
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.patch_selector_sheet_filter_compat_title),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(5.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
||||
) {
|
||||
FilterChip(
|
||||
selected = vm.filter and SHOW_SUPPORTED != 0,
|
||||
onClick = { vm.toggleFlag(SHOW_SUPPORTED) },
|
||||
label = { Text(stringResource(R.string.supported)) }
|
||||
label = { Text(stringResource(R.string.supported)) },
|
||||
)
|
||||
|
||||
FilterChip(
|
||||
|
@ -116,12 +118,13 @@ fun PatchesSelectorScreen(
|
|||
}
|
||||
}
|
||||
|
||||
if (vm.compatibleVersions.isNotEmpty())
|
||||
if (vm.compatibleVersions.isNotEmpty()) {
|
||||
UnsupportedDialog(
|
||||
appVersion = vm.appVersion,
|
||||
supportedVersions = vm.compatibleVersions,
|
||||
onDismissRequest = vm::dismissDialogs
|
||||
onDismissRequest = vm::dismissDialogs,
|
||||
)
|
||||
}
|
||||
|
||||
vm.optionsDialog?.let { (bundle, patch) ->
|
||||
OptionsDialog(
|
||||
|
@ -129,7 +132,7 @@ fun PatchesSelectorScreen(
|
|||
patch = patch,
|
||||
values = vm.getOptions(bundle, patch),
|
||||
reset = { vm.resetOptions(bundle, patch) },
|
||||
set = { key, value -> vm.setOption(bundle, patch, key, value) }
|
||||
set = { key, value -> vm.setOption(bundle, patch, key, value) },
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -142,7 +145,7 @@ fun PatchesSelectorScreen(
|
|||
vm.pendingUniversalPatchAction?.let {
|
||||
UniversalPatchWarningDialog(
|
||||
onCancel = vm::dismissUniversalPatchWarning,
|
||||
onConfirm = vm::confirmUniversalPatchWarning
|
||||
onConfirm = vm::confirmUniversalPatchWarning,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -151,7 +154,7 @@ fun PatchesSelectorScreen(
|
|||
patches: List<PatchInfo>,
|
||||
filterFlag: Int,
|
||||
supported: Boolean,
|
||||
header: (@Composable () -> Unit)? = null
|
||||
header: (@Composable () -> Unit)? = null,
|
||||
) {
|
||||
if (patches.isNotEmpty() && (vm.filter and filterFlag) != 0 || vm.filter == 0) {
|
||||
header?.let {
|
||||
|
@ -162,16 +165,18 @@ fun PatchesSelectorScreen(
|
|||
|
||||
items(
|
||||
items = patches,
|
||||
key = { it.name }
|
||||
key = { it.name },
|
||||
) { patch ->
|
||||
PatchItem(
|
||||
patch = patch,
|
||||
onOptionsDialog = {
|
||||
vm.optionsDialog = uid to patch
|
||||
},
|
||||
selected = supported && vm.isSelected(
|
||||
selected =
|
||||
supported &&
|
||||
vm.isSelected(
|
||||
uid,
|
||||
patch
|
||||
patch,
|
||||
),
|
||||
onToggle = {
|
||||
if (vm.selectionWarningEnabled) {
|
||||
|
@ -182,7 +187,7 @@ fun PatchesSelectorScreen(
|
|||
vm.togglePatch(uid, patch)
|
||||
}
|
||||
},
|
||||
supported = supported
|
||||
supported = supported,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -193,14 +198,15 @@ fun PatchesSelectorScreen(
|
|||
query = query,
|
||||
onQueryChange = { search = it },
|
||||
onActiveChange = { if (!it) search = null },
|
||||
placeholder = { Text(stringResource(R.string.search_patches)) }
|
||||
placeholder = { Text(stringResource(R.string.search_patches)) },
|
||||
) {
|
||||
val bundle = bundles[pagerState.currentPage]
|
||||
|
||||
LazyColumnWithScrollbar(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
fun List<PatchInfo>.searched() = filter {
|
||||
fun List<PatchInfo>.searched() =
|
||||
filter {
|
||||
it.name.contains(query, true)
|
||||
}
|
||||
|
||||
|
@ -208,13 +214,13 @@ fun PatchesSelectorScreen(
|
|||
uid = bundle.uid,
|
||||
patches = bundle.supported.searched(),
|
||||
filterFlag = SHOW_SUPPORTED,
|
||||
supported = true
|
||||
supported = true,
|
||||
)
|
||||
patchList(
|
||||
uid = bundle.uid,
|
||||
patches = bundle.universal.searched(),
|
||||
filterFlag = SHOW_UNIVERSAL,
|
||||
supported = true
|
||||
supported = true,
|
||||
) {
|
||||
ListHeader(
|
||||
title = stringResource(R.string.universal_patches),
|
||||
|
@ -226,11 +232,11 @@ fun PatchesSelectorScreen(
|
|||
uid = bundle.uid,
|
||||
patches = bundle.unsupported.searched(),
|
||||
filterFlag = SHOW_UNSUPPORTED,
|
||||
supported = true
|
||||
supported = true,
|
||||
) {
|
||||
ListHeader(
|
||||
title = stringResource(R.string.unsupported_patches),
|
||||
onHelpClick = { vm.openUnsupportedDialog(bundle.unsupported) }
|
||||
onHelpClick = { vm.openUnsupportedDialog(bundle.unsupported) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -252,11 +258,11 @@ fun PatchesSelectorScreen(
|
|||
IconButton(
|
||||
onClick = {
|
||||
search = ""
|
||||
}
|
||||
},
|
||||
) {
|
||||
Icon(Icons.Outlined.Search, stringResource(R.string.search))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
|
@ -269,19 +275,19 @@ fun PatchesSelectorScreen(
|
|||
onClick = {
|
||||
// TODO: only allow this if all required options have been set.
|
||||
onSave(vm.getCustomSelection(), vm.getOptions())
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(paddingValues),
|
||||
) {
|
||||
if (bundles.size > 1) {
|
||||
ScrollableTabRow(
|
||||
selectedTabIndex = pagerState.currentPage,
|
||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp),
|
||||
) {
|
||||
bundles.forEachIndexed { index, bundle ->
|
||||
HapticTab(
|
||||
|
@ -289,13 +295,13 @@ fun PatchesSelectorScreen(
|
|||
onClick = {
|
||||
composableScope.launch {
|
||||
pagerState.animateScrollToPage(
|
||||
index
|
||||
index,
|
||||
)
|
||||
}
|
||||
},
|
||||
text = { Text(bundle.name) },
|
||||
selectedContentColor = MaterialTheme.colorScheme.primary,
|
||||
unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
unselectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -311,19 +317,19 @@ fun PatchesSelectorScreen(
|
|||
|
||||
LazyColumnWithScrollbar(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = patchLazyListStates[index]
|
||||
state = patchLazyListStates[index],
|
||||
) {
|
||||
patchList(
|
||||
uid = bundle.uid,
|
||||
patches = bundle.supported,
|
||||
filterFlag = SHOW_SUPPORTED,
|
||||
supported = true
|
||||
supported = true,
|
||||
)
|
||||
patchList(
|
||||
uid = bundle.uid,
|
||||
patches = bundle.universal,
|
||||
filterFlag = SHOW_UNIVERSAL,
|
||||
supported = true
|
||||
supported = true,
|
||||
) {
|
||||
ListHeader(
|
||||
title = stringResource(R.string.universal_patches),
|
||||
|
@ -333,15 +339,15 @@ fun PatchesSelectorScreen(
|
|||
uid = bundle.uid,
|
||||
patches = bundle.unsupported,
|
||||
filterFlag = SHOW_UNSUPPORTED,
|
||||
supported = vm.allowIncompatiblePatches
|
||||
supported = vm.allowIncompatiblePatches,
|
||||
) {
|
||||
ListHeader(
|
||||
title = stringResource(R.string.unsupported_patches),
|
||||
onHelpClick = { vm.openUnsupportedDialog(bundle.unsupported) }
|
||||
onHelpClick = { vm.openUnsupportedDialog(bundle.unsupported) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -359,7 +365,7 @@ fun SelectionWarningDialog(onDismiss: () -> Unit) {
|
|||
@Composable
|
||||
fun UniversalPatchWarningDialog(
|
||||
onCancel: () -> Unit,
|
||||
onConfirm: () -> Unit
|
||||
onConfirm: () -> Unit,
|
||||
) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onCancel,
|
||||
|
@ -379,12 +385,12 @@ fun UniversalPatchWarningDialog(
|
|||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.warning),
|
||||
style = MaterialTheme.typography.headlineSmall.copy(textAlign = TextAlign.Center)
|
||||
style = MaterialTheme.typography.headlineSmall.copy(textAlign = TextAlign.Center),
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.universal_patch_warning_description))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -394,9 +400,10 @@ fun PatchItem(
|
|||
onOptionsDialog: () -> Unit,
|
||||
selected: Boolean,
|
||||
onToggle: () -> Unit,
|
||||
supported: Boolean = true
|
||||
) = ListItem (
|
||||
modifier = Modifier
|
||||
supported: Boolean = true,
|
||||
) = ListItem(
|
||||
modifier =
|
||||
Modifier
|
||||
.let { if (!supported) it.alpha(0.5f) else it }
|
||||
.clickable(enabled = supported, onClick = onToggle)
|
||||
.fillMaxSize(),
|
||||
|
@ -404,7 +411,7 @@ fun PatchItem(
|
|||
HapticCheckbox(
|
||||
checked = selected,
|
||||
onCheckedChange = { onToggle() },
|
||||
enabled = supported
|
||||
enabled = supported,
|
||||
)
|
||||
},
|
||||
headlineContent = { Text(patch.name) },
|
||||
|
@ -421,26 +428,27 @@ fun PatchItem(
|
|||
@Composable
|
||||
fun ListHeader(
|
||||
title: String,
|
||||
onHelpClick: (() -> Unit)? = null
|
||||
onHelpClick: (() -> Unit)? = null,
|
||||
) {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = title,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = MaterialTheme.typography.labelLarge
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
)
|
||||
},
|
||||
trailingContent = onHelpClick?.let {
|
||||
trailingContent =
|
||||
onHelpClick?.let {
|
||||
{
|
||||
IconButton(onClick = it) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
stringResource(R.string.help)
|
||||
stringResource(R.string.help),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -448,7 +456,7 @@ fun ListHeader(
|
|||
fun UnsupportedDialog(
|
||||
appVersion: String,
|
||||
supportedVersions: List<String>,
|
||||
onDismissRequest: () -> Unit
|
||||
onDismissRequest: () -> Unit,
|
||||
) = AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
confirmButton = {
|
||||
|
@ -462,10 +470,10 @@ fun UnsupportedDialog(
|
|||
stringResource(
|
||||
R.string.app_not_supported,
|
||||
appVersion,
|
||||
supportedVersions.joinToString(", ")
|
||||
supportedVersions.joinToString(", "),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
|
@ -478,10 +486,11 @@ fun OptionsDialog(
|
|||
onDismissRequest: () -> Unit,
|
||||
) = Dialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
properties = DialogProperties(
|
||||
properties =
|
||||
DialogProperties(
|
||||
usePlatformDefaultWidth = false,
|
||||
dismissOnBackPress = true
|
||||
)
|
||||
dismissOnBackPress = true,
|
||||
),
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
|
@ -492,12 +501,12 @@ fun OptionsDialog(
|
|||
IconButton(onClick = reset) {
|
||||
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
LazyColumnWithScrollbar(
|
||||
modifier = Modifier.padding(paddingValues)
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
) {
|
||||
if (patch.options == null) return@LazyColumnWithScrollbar
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.automirrored.outlined.ArrowRight
|
||||
import androidx.compose.material.icons.filled.AutoFixHigh
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
@ -28,6 +27,7 @@ import app.revanced.manager.R
|
|||
import app.revanced.manager.ui.component.AppInfo
|
||||
import app.revanced.manager.ui.component.AppTopBar
|
||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
||||
import app.revanced.manager.ui.destination.SelectedAppInfoDestination
|
||||
import app.revanced.manager.ui.model.BundleInfo.Extensions.bundleInfoFlow
|
||||
import app.revanced.manager.ui.model.SelectedApp
|
||||
|
@ -48,7 +48,7 @@ import org.koin.core.parameter.parametersOf
|
|||
fun SelectedAppInfoScreen(
|
||||
onPatchClick: (SelectedApp, PatchSelection, Options) -> Unit,
|
||||
onBackClick: () -> Unit,
|
||||
vm: SelectedAppInfoViewModel
|
||||
vm: SelectedAppInfoViewModel,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
|
@ -82,7 +82,8 @@ fun SelectedAppInfoScreen(
|
|||
|
||||
AnimatedNavHost(controller = navController) { destination ->
|
||||
when (destination) {
|
||||
is SelectedAppInfoDestination.Main -> SelectedAppInfoScreen(
|
||||
is SelectedAppInfoDestination.Main ->
|
||||
SelectedAppInfoScreen(
|
||||
onPatchClick = patchClick@{
|
||||
if (selectedPatchCount == 0) {
|
||||
context.toast(context.getString(R.string.no_patches_selected))
|
||||
|
@ -92,7 +93,7 @@ fun SelectedAppInfoScreen(
|
|||
onPatchClick(
|
||||
vm.selectedApp,
|
||||
patches,
|
||||
vm.getOptionsFiltered(bundles)
|
||||
vm.getOptionsFiltered(bundles),
|
||||
)
|
||||
},
|
||||
onPatchSelectorClick = {
|
||||
|
@ -101,10 +102,10 @@ fun SelectedAppInfoScreen(
|
|||
vm.selectedApp,
|
||||
vm.getCustomPatches(
|
||||
bundles,
|
||||
allowIncompatiblePatches
|
||||
allowIncompatiblePatches,
|
||||
),
|
||||
vm.options,
|
||||
),
|
||||
vm.options
|
||||
)
|
||||
)
|
||||
},
|
||||
onVersionSelectorClick = {
|
||||
|
@ -118,30 +119,33 @@ fun SelectedAppInfoScreen(
|
|||
packageInfo = vm.selectedAppInfo,
|
||||
)
|
||||
|
||||
is SelectedAppInfoDestination.VersionSelector -> VersionSelectorScreen(
|
||||
is SelectedAppInfoDestination.VersionSelector ->
|
||||
VersionSelectorScreen(
|
||||
onBackClick = navController::pop,
|
||||
onAppClick = {
|
||||
vm.selectedApp = it
|
||||
navController.pop()
|
||||
},
|
||||
viewModel = koinViewModel { parametersOf(packageName) }
|
||||
viewModel = koinViewModel { parametersOf(packageName) },
|
||||
)
|
||||
|
||||
is SelectedAppInfoDestination.PatchesSelector -> PatchesSelectorScreen(
|
||||
is SelectedAppInfoDestination.PatchesSelector ->
|
||||
PatchesSelectorScreen(
|
||||
onSave = { patches, options ->
|
||||
vm.updateConfiguration(patches, options, bundles)
|
||||
navController.pop()
|
||||
},
|
||||
onBackClick = navController::pop,
|
||||
vm = koinViewModel {
|
||||
vm =
|
||||
koinViewModel {
|
||||
parametersOf(
|
||||
PatchesSelectorViewModel.Params(
|
||||
destination.app,
|
||||
destination.currentSelection,
|
||||
destination.options,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -164,21 +168,22 @@ private fun SelectedAppInfoScreen(
|
|||
topBar = {
|
||||
AppTopBar(
|
||||
title = stringResource(R.string.app_info),
|
||||
onBackClick = onBackClick
|
||||
onBackClick = onBackClick,
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
ExtendedFloatingActionButton(
|
||||
HapticExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.patch)) },
|
||||
icon = { Icon(Icons.Default.AutoFixHigh, null) },
|
||||
onClick = onPatchClick
|
||||
onClick = onPatchClick,
|
||||
)
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
ColumnWithScrollbar(
|
||||
modifier = Modifier
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(paddingValues),
|
||||
) {
|
||||
AppInfo(packageInfo, placeholderLabel = packageName) {
|
||||
Text(
|
||||
|
@ -191,39 +196,44 @@ private fun SelectedAppInfoScreen(
|
|||
PageItem(
|
||||
R.string.patch_selector_item,
|
||||
stringResource(R.string.patch_selector_item_description, selectedPatchCount),
|
||||
onPatchSelectorClick
|
||||
onPatchSelectorClick,
|
||||
)
|
||||
PageItem(
|
||||
R.string.version_selector_item,
|
||||
stringResource(R.string.version_selector_item_description, version),
|
||||
onVersionSelectorClick
|
||||
onVersionSelectorClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PageItem(@StringRes title: Int, description: String, onClick: () -> Unit) {
|
||||
private fun PageItem(
|
||||
@StringRes title: Int,
|
||||
description: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
ListItem(
|
||||
modifier = Modifier
|
||||
modifier =
|
||||
Modifier
|
||||
.clickable(onClick = onClick)
|
||||
.padding(start = 8.dp),
|
||||
headlineContent = {
|
||||
Text(
|
||||
stringResource(title),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
},
|
||||
supportingContent = {
|
||||
Text(
|
||||
description,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
},
|
||||
trailingContent = {
|
||||
Icon(Icons.AutoMirrored.Outlined.ArrowRight, null)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
|
@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
|
@ -20,6 +19,7 @@ import app.revanced.manager.R
|
|||
import app.revanced.manager.ui.component.AppTopBar
|
||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.GroupHeader
|
||||
import app.revanced.manager.ui.component.haptics.HapticCheckbox
|
||||
import app.revanced.manager.ui.component.settings.BooleanItem
|
||||
import app.revanced.manager.ui.component.settings.SettingsListItem
|
||||
import app.revanced.manager.ui.viewmodel.DownloadsViewModel
|
||||
|
@ -29,7 +29,7 @@ import org.koin.androidx.compose.koinViewModel
|
|||
@Composable
|
||||
fun DownloadsSettingsScreen(
|
||||
onBackClick: () -> Unit,
|
||||
viewModel: DownloadsViewModel = koinViewModel()
|
||||
viewModel: DownloadsViewModel = koinViewModel(),
|
||||
) {
|
||||
val prefs = viewModel.prefs
|
||||
|
||||
|
@ -46,14 +46,15 @@ fun DownloadsSettingsScreen(
|
|||
Icon(Icons.Default.Delete, stringResource(R.string.delete))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
ColumnWithScrollbar(
|
||||
modifier = Modifier
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(paddingValues),
|
||||
) {
|
||||
BooleanItem(
|
||||
preference = prefs.preferSplits,
|
||||
|
@ -69,14 +70,19 @@ fun DownloadsSettingsScreen(
|
|||
SettingsListItem(
|
||||
modifier = Modifier.clickable { viewModel.toggleItem(app) },
|
||||
headlineContent = app.packageName,
|
||||
leadingContent = (@Composable {
|
||||
Checkbox(
|
||||
leadingContent =
|
||||
{
|
||||
(
|
||||
@Composable {
|
||||
HapticCheckbox(
|
||||
checked = selected,
|
||||
onCheckedChange = { viewModel.toggleItem(app) }
|
||||
onCheckedChange = { viewModel.toggleItem(app) },
|
||||
)
|
||||
}).takeIf { viewModel.selection.isNotEmpty() },
|
||||
}
|
||||
).takeIf { viewModel.selection.isNotEmpty() }
|
||||
},
|
||||
supportingContent = app.version,
|
||||
tonalElevation = if (selected) 8.dp else 0.dp
|
||||
tonalElevation = if (selected) 8.dp else 0.dp,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue