feat(Settings): use SettingsListItem consistently and overall improvements (#1427)

This commit is contained in:
Ushie 2023-11-01 20:11:43 +03:00 committed by GitHub
parent 7fe4724e10
commit 25bd91debc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 201 additions and 186 deletions

View file

@ -18,6 +18,6 @@ fun GroupHeader(
text = title,
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.labelLarge,
modifier = Modifier.padding(16.dp).semantics { heading() }.then(modifier)
modifier = Modifier.padding(24.dp).semantics { heading() }.then(modifier)
)
}

View file

@ -0,0 +1,47 @@
package app.revanced.manager.ui.component
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ListItemColors
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.material3.ListItem
@Composable
fun SettingsListItem(
headlineContent: String,
modifier: Modifier = Modifier,
overlineContent: @Composable (() -> Unit)? = null,
supportingContent: String? = null,
leadingContent: @Composable (() -> Unit)? = null,
trailingContent: @Composable (() -> Unit)? = null,
colors: ListItemColors = ListItemDefaults.colors(),
tonalElevation: Dp = ListItemDefaults.Elevation,
shadowElevation: Dp = ListItemDefaults.Elevation,
) = ListItem(
headlineContent = {
Text(
text = headlineContent,
style = MaterialTheme.typography.titleLarge
)
},
modifier = modifier.then(Modifier.padding(horizontal = 8.dp)),
overlineContent = overlineContent,
supportingContent = {
if (supportingContent != null)
Text(
text = supportingContent,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.outline
) else null
},
leadingContent = leadingContent,
trailingContent = trailingContent,
colors = colors,
tonalElevation = tonalElevation,
shadowElevation = shadowElevation
)

View file

@ -2,15 +2,14 @@ package app.revanced.manager.ui.component.settings
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.material3.ListItem
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.revanced.manager.domain.manager.base.Preference
import app.revanced.manager.ui.component.SettingsListItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -37,10 +36,10 @@ fun BooleanItem(
onValueChange: (Boolean) -> Unit,
@StringRes headline: Int,
@StringRes description: Int
) = ListItem(
) = SettingsListItem(
modifier = Modifier.clickable { onValueChange(!value) },
headlineContent = { Text(stringResource(headline)) },
supportingContent = { Text(stringResource(description)) },
headlineContent = stringResource(headline),
supportingContent = stringResource(description),
trailingContent = {
Switch(
checked = value,

View file

@ -5,9 +5,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
@ -21,7 +19,6 @@ import androidx.compose.material.icons.outlined.Update
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
@ -32,7 +29,6 @@ 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.draw.clip
import androidx.compose.ui.res.pluralStringResource
@ -40,10 +36,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.ui.component.AppIcon
import app.revanced.manager.ui.component.AppInfo
import app.revanced.manager.ui.component.AppLabel
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.SettingsListItem
import app.revanced.manager.ui.component.SegmentedButton
import app.revanced.manager.ui.viewmodel.InstalledAppInfoViewModel
import app.revanced.manager.util.PatchesSelection
@ -148,38 +143,35 @@ fun InstalledAppInfoScreen(
Column(
modifier = Modifier.padding(vertical = 16.dp)
) {
ListItem(
SettingsListItem(
modifier = Modifier.clickable { },
headlineContent = { Text(stringResource(R.string.applied_patches)) },
supportingContent = {
Text(
headlineContent = stringResource(R.string.applied_patches),
supportingContent =
(viewModel.appliedPatches?.values?.sumOf { it.size } ?: 0).let {
pluralStringResource(
id = R.plurals.applied_patches,
it,
it
)
}
)
},
},
trailingContent = { Icon(Icons.Filled.ArrowRight, contentDescription = stringResource(R.string.view_applied_patches)) }
)
ListItem(
headlineContent = { Text(stringResource(R.string.package_name)) },
supportingContent = { Text(viewModel.installedApp.currentPackageName) }
SettingsListItem(
headlineContent = stringResource(R.string.package_name),
supportingContent = viewModel.installedApp.currentPackageName
)
if (viewModel.installedApp.originalPackageName != viewModel.installedApp.currentPackageName) {
ListItem(
headlineContent = { Text(stringResource(R.string.original_package_name)) },
supportingContent = { Text(viewModel.installedApp.originalPackageName) }
SettingsListItem(
headlineContent = stringResource(R.string.original_package_name),
supportingContent = viewModel.installedApp.originalPackageName
)
}
ListItem(
headlineContent = { Text(stringResource(R.string.install_type)) },
supportingContent = { Text(stringResource(viewModel.installedApp.installType.stringResource)) }
SettingsListItem(
headlineContent = stringResource(R.string.install_type),
supportingContent = stringResource(viewModel.installedApp.installType.stringResource)
)
}

View file

@ -45,9 +45,10 @@ import app.revanced.manager.ui.screen.settings.update.UpdatesSettingsScreen
import app.revanced.manager.ui.viewmodel.SettingsViewModel
import dev.olshevski.navigation.reimagined.*
import org.koin.androidx.compose.getViewModel
import app.revanced.manager.ui.component.SettingsListItem
@SuppressLint("BatteryLife")
@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(
onBackClick: () -> Unit,
@ -157,8 +158,7 @@ fun SettingsScreen(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(12.dp)
.verticalScroll(rememberScrollState())
) {
AnimatedVisibility(visible = showBatteryButton) {
Card(
@ -197,21 +197,10 @@ fun SettingsScreen(
}
}
settingsSections.forEach { (titleDescIcon, destination) ->
ListItem(
SettingsListItem(
modifier = Modifier.clickable { navController.navigate(destination) },
headlineContent = {
Text(
stringResource(titleDescIcon.first),
style = MaterialTheme.typography.titleLarge
)
},
supportingContent = {
Text(
stringResource(titleDescIcon.second),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.outline
)
},
headlineContent = stringResource(titleDescIcon.first),
supportingContent = stringResource(titleDescIcon.second),
leadingContent = { Icon(titleDescIcon.third, null) }
)
}

View file

@ -1,10 +1,19 @@
package app.revanced.manager.ui.screen.settings
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
@ -12,23 +21,30 @@ import androidx.compose.material.icons.outlined.Code
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.Language
import androidx.compose.material.icons.outlined.MailOutline
import androidx.compose.material3.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.BuildConfig
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.SettingsListItem
import app.revanced.manager.util.isDebuggable
import app.revanced.manager.util.openUrl
import com.google.accompanist.drawablepainter.rememberDrawablePainter
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@Composable
fun AboutSettingsScreen(
onBackClick: () -> Unit,
@ -92,99 +108,87 @@ fun AboutSettingsScreen(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Image(
modifier = Modifier.padding(top = 16.dp),
painter = icon,
contentDescription = null
)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Image(painter = icon, contentDescription = null)
Text(stringResource(R.string.app_name), style = MaterialTheme.typography.titleLarge)
Text(
stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineSmall
)
Text(
text = stringResource(R.string.version) + " " + BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")",
style = MaterialTheme.typography.bodyMedium
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.outline
)
Row(
modifier = Modifier.padding(top = 12.dp)
) {
filledButton.forEach { (icon, text, onClick) ->
FilledTonalButton(
onClick = onClick,
modifier = Modifier.padding(end = 8.dp)
}
FlowRow(
maxItemsInEachRow = 2,
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)
) {
filledButton.forEach { (icon, text, onClick) ->
FilledTonalButton(
onClick = onClick
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
icon,
contentDescription = null,
modifier = Modifier
.size(28.dp)
.padding(end = 8.dp),
tint = MaterialTheme.colorScheme.primary
)
Text(
text,
style = MaterialTheme.typography.labelLarge,
)
}
Icon(
icon,
contentDescription = null,
modifier = Modifier.size(18.dp)
)
Text(
text,
style = MaterialTheme.typography.labelLarge
)
}
}
}
Row(
modifier = Modifier.padding(top = 12.dp)
) {
outlinedButton.forEach { (icon, text, onClick) ->
Button(
onClick = onClick,
modifier = Modifier.padding(end = 8.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
),
border = ButtonDefaults.outlinedButtonBorder
outlinedButton.forEach { (icon, text, onClick) ->
OutlinedButton(
onClick = onClick
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
icon,
contentDescription = null,
modifier = Modifier
.size(28.dp)
.padding(end = 8.dp),
tint = MaterialTheme.colorScheme.primary
)
Text(
text,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary
)
}
Icon(
icon,
contentDescription = null,
modifier = Modifier.size(18.dp)
)
Text(
text,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary
)
}
}
}
}
Box(
modifier = Modifier
.padding(vertical = 8.dp, horizontal = 16.dp)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.outlineVariant,
shape = MaterialTheme.shapes.medium
)
.padding(16.dp)
OutlinedCard(
modifier = Modifier.padding(horizontal = 16.dp),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)
) {
Column {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = stringResource(R.string.about_revanced_manager),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.titleMedium
)
Text(
text = stringResource(R.string.revanced_manager_description),
@ -192,24 +196,17 @@ fun AboutSettingsScreen(
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
listItems.forEach { (title, description, onClick) ->
ListItem(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clickable { onClick() },
headlineContent = { Text(title, style = MaterialTheme.typography.titleLarge) },
supportingContent = {
Text(
description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.outline
)
}
)
Column {
listItems.forEach { (title, description, onClick) ->
SettingsListItem(
modifier = Modifier
.fillMaxWidth()
.clickable { onClick() },
headlineContent = title,
supportingContent = description
)
}
}
}
}

View file

@ -14,7 +14,6 @@ import androidx.compose.material.icons.outlined.Http
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
@ -36,6 +35,7 @@ import androidx.lifecycle.viewModelScope
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.GroupHeader
import app.revanced.manager.ui.component.SettingsListItem
import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel
import org.koin.androidx.compose.getViewModel
@ -79,9 +79,9 @@ fun AdvancedSettingsScreen(
it?.let(vm::setApiUrl)
}
}
ListItem(
headlineContent = { Text(stringResource(R.string.api_url)) },
supportingContent = { Text(apiUrl) },
SettingsListItem(
headlineContent = stringResource(R.string.api_url),
supportingContent = apiUrl,
modifier = Modifier.clickable {
showApiUrlDialog = true
}
@ -96,35 +96,35 @@ fun AdvancedSettingsScreen(
)
GroupHeader(stringResource(R.string.patch_bundles_section))
ListItem(
headlineContent = { Text(stringResource(R.string.patch_bundles_redownload)) },
SettingsListItem(
headlineContent = stringResource(R.string.patch_bundles_redownload),
modifier = Modifier.clickable {
vm.redownloadBundles()
}
)
ListItem(
headlineContent = { Text(stringResource(R.string.patch_bundles_reset)) },
SettingsListItem(
headlineContent = stringResource(R.string.patch_bundles_reset),
modifier = Modifier.clickable {
vm.resetBundles()
}
)
GroupHeader(stringResource(R.string.device))
ListItem(
headlineContent = { Text(stringResource(R.string.device_model)) },
supportingContent = { Text(Build.MODEL) }
SettingsListItem(
headlineContent = stringResource(R.string.device_model),
supportingContent = Build.MODEL
)
ListItem(
headlineContent = { Text(stringResource(R.string.device_android_version)) },
supportingContent = { Text(Build.VERSION.RELEASE) }
SettingsListItem(
headlineContent = stringResource(R.string.device_android_version),
supportingContent = Build.VERSION.RELEASE
)
ListItem(
headlineContent = { Text(stringResource(R.string.device_architectures)) },
supportingContent = { Text(Build.SUPPORTED_ABIS.joinToString(", ")) }
SettingsListItem(
headlineContent = stringResource(R.string.device_architectures),
supportingContent = Build.SUPPORTED_ABIS.joinToString(", ")
)
ListItem(
headlineContent = { Text(stringResource(R.string.device_memory_limit)) },
supportingContent = { Text(memoryLimit) }
SettingsListItem(
headlineContent = stringResource(R.string.device_memory_limit),
supportingContent = memoryLimit
)
}
}

View file

@ -12,9 +12,7 @@ import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
@ -24,6 +22,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.GroupHeader
import app.revanced.manager.ui.component.SettingsListItem
import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.viewmodel.DownloadsViewModel
import org.koin.androidx.compose.getViewModel
@ -70,16 +69,16 @@ fun DownloadsSettingsScreen(
downloadedApps.forEach { app ->
val selected = app in viewModel.selection
ListItem(
SettingsListItem(
modifier = Modifier.clickable { viewModel.toggleItem(app) },
headlineContent = { Text(app.packageName) },
headlineContent = app.packageName,
leadingContent = (@Composable {
Checkbox(
checked = selected,
onCheckedChange = { viewModel.toggleItem(app) }
)
}).takeIf { viewModel.selection.isNotEmpty() },
supportingContent = { Text(app.version) },
supportingContent = app.version,
tonalElevation = if (selected) 8.dp else 0.dp
)
}

View file

@ -23,6 +23,7 @@ import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.theme.Theme
import app.revanced.manager.ui.viewmodel.SettingsViewModel
import org.koin.compose.koinInject
import app.revanced.manager.ui.component.SettingsListItem
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -58,12 +59,12 @@ fun GeneralSettingsScreen(
GroupHeader(stringResource(R.string.appearance))
val theme by prefs.theme.getAsState()
ListItem(
SettingsListItem(
modifier = Modifier.clickable { showThemePicker = true },
headlineContent = { Text(stringResource(R.string.theme)) },
supportingContent = { Text(stringResource(R.string.theme_description)) },
headlineContent = stringResource(R.string.theme),
supportingContent = stringResource(R.string.theme_description),
trailingContent = {
Button(
FilledTonalButton(
onClick = {
showThemePicker = true
}

View file

@ -39,6 +39,7 @@ import app.revanced.manager.ui.component.bundle.BundleSelector
import app.revanced.manager.util.toast
import kotlinx.coroutines.launch
import org.koin.androidx.compose.getViewModel
import app.revanced.manager.ui.component.SettingsListItem
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -253,10 +254,10 @@ private fun PackageSelector(packages: Set<String>, onFinish: (String?) -> Unit)
@Composable
private fun GroupItem(onClick: () -> Unit, @StringRes headline: Int, @StringRes description: Int) =
ListItem(
SettingsListItem(
modifier = Modifier.clickable { onClick() },
headlineContent = { Text(stringResource(headline)) },
supportingContent = { Text(stringResource(description)) }
headlineContent = stringResource(headline),
supportingContent = stringResource(description)
)
@Composable

View file

@ -28,6 +28,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.SettingsListItem
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -74,24 +75,13 @@ fun UpdatesSettingsScreen(
)
listItems.forEach { (title, description, onClick) ->
ListItem(
SettingsListItem(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.padding(horizontal = 8.dp)
.clickable { onClick() },
headlineContent = {
Text(
title,
style = MaterialTheme.typography.titleLarge
)
},
supportingContent = {
Text(
description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.outline
)
}
headlineContent = title,
supportingContent = description
)
}
}
@ -124,4 +114,4 @@ fun UpdateNotification(
)
}
}
}
}