manager: Refactor card elevation handling and improve theme support

This commit is contained in:
ShirkNeko
2025-06-01 20:17:22 +08:00
parent ee4c3bb03b
commit 5457a4772b
16 changed files with 1005 additions and 908 deletions

View File

@@ -63,7 +63,12 @@ fun SearchAppBar(
var onSearch by remember { mutableStateOf(false) } var onSearch by remember { mutableStateOf(false) }
// 获取卡片颜色和透明度 // 获取卡片颜色和透明度
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha val cardAlpha = CardConfig.cardAlpha
if (onSearch) { if (onSearch) {

View File

@@ -1,87 +0,0 @@
package com.sukisu.ultra.ui.component
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.Role
import com.dergoogler.mmrl.ui.component.LabelItem
import com.dergoogler.mmrl.ui.component.text.TextRow
@Composable
fun SwitchItem(
icon: ImageVector? = null,
title: String,
summary: String? = null,
checked: Boolean,
enabled: Boolean = true,
beta: Boolean = false,
onCheckedChange: (Boolean) -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
val stateAlpha = remember(checked, enabled) { Modifier.alpha(if (enabled) 1f else 0.5f) }
ListItem(
modifier = Modifier
.toggleable(
value = checked,
interactionSource = interactionSource,
role = Role.Switch,
enabled = enabled,
indication = LocalIndication.current,
onValueChange = onCheckedChange
),
headlineContent = {
TextRow(
leadingContent = if (beta) {
{
LabelItem(
modifier = Modifier.then(stateAlpha),
text = "Beta"
)
}
} else null
) {
Text(
modifier = Modifier.then(stateAlpha),
text = title,
)
}
},
leadingContent = icon?.let {
{
Icon(
modifier = Modifier.then(stateAlpha),
imageVector = icon,
contentDescription = title,
tint = MaterialTheme.colorScheme.primary
)
}
},
trailingContent = {
Switch(
checked = checked,
enabled = enabled,
onCheckedChange = onCheckedChange,
interactionSource = interactionSource
)
},
supportingContent = {
if (summary != null) {
Text(
modifier = Modifier.then(stateAlpha),
text = summary
)
}
}
)
}

View File

@@ -21,7 +21,7 @@ import androidx.compose.ui.unit.dp
@Composable @Composable
fun SwitchItem( fun SwitchItem(
icon: ImageVector, icon: ImageVector? = null,
title: String, title: String,
summary: String? = null, summary: String? = null,
checked: Boolean, checked: Boolean,
@@ -55,6 +55,11 @@ fun SwitchItem(
disabledUncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant disabledUncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant
) )
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
ListItem( ListItem(
headlineContent = { headlineContent = {
Text( Text(
@@ -75,13 +80,15 @@ fun SwitchItem(
) )
} }
}, },
leadingContent = { leadingContent = icon?.let {
{
Icon( Icon(
imageVector = icon, imageVector = it,
contentDescription = null, contentDescription = null,
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
tint = iconTint tint = iconTint
) )
}
}, },
trailingContent = { trailingContent = {
Switch( Switch(
@@ -99,3 +106,4 @@ fun SwitchItem(
.padding(vertical = 4.dp) .padding(vertical = 4.dp)
) )
} }
}

View File

@@ -31,7 +31,6 @@ fun AppProfileConfig(
onValueChange = { onProfileChange(profile.copy(name = it)) } onValueChange = { onProfileChange(profile.copy(name = it)) }
) )
} }
SwitchItem( SwitchItem(
title = stringResource(R.string.profile_umount_modules), title = stringResource(R.string.profile_umount_modules),
summary = stringResource(R.string.profile_umount_modules_summary), summary = stringResource(R.string.profile_umount_modules_summary),

View File

@@ -37,7 +37,6 @@ import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@@ -84,6 +83,8 @@ import com.sukisu.ultra.ui.component.profile.AppProfileConfig
import com.sukisu.ultra.ui.component.profile.RootProfileConfig import com.sukisu.ultra.ui.component.profile.RootProfileConfig
import com.sukisu.ultra.ui.component.profile.TemplateConfig import com.sukisu.ultra.ui.component.profile.TemplateConfig
import com.sukisu.ultra.ui.theme.CardConfig import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.getCardColors
import com.sukisu.ultra.ui.theme.getCardElevation
import com.sukisu.ultra.ui.util.LocalSnackbarHost import com.sukisu.ultra.ui.util.LocalSnackbarHost
import com.sukisu.ultra.ui.util.forceStopApp import com.sukisu.ultra.ui.util.forceStopApp
import com.sukisu.ultra.ui.util.getSepolicy import com.sukisu.ultra.ui.util.getSepolicy
@@ -122,7 +123,12 @@ fun AppProfileScreen(
mutableStateOf(initialProfile) mutableStateOf(initialProfile)
} }
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha val cardAlpha = CardConfig.cardAlpha
Scaffold( Scaffold(
@@ -203,13 +209,21 @@ private fun AppProfileInner(
onProfileChange: (Natives.Profile) -> Unit, onProfileChange: (Natives.Profile) -> Unit,
) { ) {
val isRootGranted = profile.allowSu val isRootGranted = profile.allowSu
val cardColors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh)
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
Column(modifier = modifier) { Column(modifier = modifier) {
ElevatedCard( ElevatedCard(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) { ) {
AppMenuBox(packageName) { AppMenuBox(packageName) {
ListItem( ListItem(
@@ -235,7 +249,9 @@ private fun AppProfileInner(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) { ) {
SwitchItem( SwitchItem(
icon = Icons.Filled.Security, icon = Icons.Filled.Security,
@@ -268,7 +284,8 @@ private fun AppProfileInner(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium shape = MaterialTheme.shapes.medium,
colors = cardColors,
) { ) {
ProfileBox(mode, true) { ProfileBox(mode, true) {
// template mode shouldn't change profile here! // template mode shouldn't change profile here!
@@ -288,10 +305,15 @@ private fun AppProfileInner(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(vertical = 8.dp)) {
Crossfade(targetState = mode, label = "ProfileMode") { currentMode -> Crossfade(
targetState = mode,
label = "ProfileMode"
) { currentMode ->
when (currentMode) { when (currentMode) {
Mode.Template -> { Mode.Template -> {
TemplateConfig( TemplateConfig(
@@ -301,6 +323,7 @@ private fun AppProfileInner(
onProfileChange = onProfileChange onProfileChange = onProfileChange
) )
} }
Mode.Custom -> { Mode.Custom -> {
RootProfileConfig( RootProfileConfig(
fixedName = true, fixedName = true,
@@ -308,6 +331,7 @@ private fun AppProfileInner(
onProfileChange = onProfileChange onProfileChange = onProfileChange
) )
} }
else -> {} else -> {}
} }
} }
@@ -321,7 +345,9 @@ private fun AppProfileInner(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) { ) {
ProfileBox(mode, false) { ProfileBox(mode, false) {
onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default))) onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default)))
@@ -337,7 +363,9 @@ private fun AppProfileInner(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(vertical = 8.dp)) {
AppProfileConfig( AppProfileConfig(
@@ -354,6 +382,7 @@ private fun AppProfileInner(
} }
} }
} }
}
private enum class Mode(@StringRes private val res: Int) { private enum class Mode(@StringRes private val res: Int) {
Default(R.string.profile_default), Template(R.string.profile_template), Custom(R.string.profile_custom); Default(R.string.profile_default), Template(R.string.profile_template), Custom(R.string.profile_custom);
@@ -377,12 +406,10 @@ private fun TopBar(
Text( Text(
text = title, text = title,
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface
) )
Text( Text(
text = packageName, text = packageName,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.alpha(0.8f) modifier = Modifier.alpha(0.8f)
) )
} }
@@ -391,9 +418,6 @@ private fun TopBar(
navigationIcon = { navigationIcon = {
IconButton( IconButton(
onClick = onBack, onClick = onBack,
colors = IconButtonDefaults.iconButtonColors(
contentColor = MaterialTheme.colorScheme.onSurface
)
) { ) {
Icon( Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
@@ -408,7 +432,6 @@ private fun TopBar(
modifier = Modifier.shadow( modifier = Modifier.shadow(
elevation = if ((scrollBehavior?.state?.overlappedFraction ?: 0f) > 0.01f) elevation = if ((scrollBehavior?.state?.overlappedFraction ?: 0f) > 0.01f)
4.dp else 0.dp, 4.dp else 0.dp,
spotColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f)
) )
) )
} }
@@ -431,7 +454,6 @@ private fun ProfileBox(
Text( Text(
text = mode.text, text = mode.text,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
) )
}, },
leadingContent = { leadingContent = {
@@ -444,7 +466,6 @@ private fun ProfileBox(
HorizontalDivider( HorizontalDivider(
thickness = Dp.Hairline, thickness = Dp.Hairline,
color = MaterialTheme.colorScheme.outlineVariant
) )
ListItem( ListItem(
@@ -574,6 +595,11 @@ private fun AppMenuOption(text: String, onClick: () -> Unit) {
@Composable @Composable
private fun AppProfilePreview() { private fun AppProfilePreview() {
var profile by remember { mutableStateOf(Natives.Profile("")) } var profile by remember { mutableStateOf(Natives.Profile("")) }
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
Surface { Surface {
AppProfileInner( AppProfileInner(
packageName = "icu.nullptr.test", packageName = "icu.nullptr.test",
@@ -591,3 +617,4 @@ private fun AppProfilePreview() {
) )
} }
} }
}

View File

@@ -439,7 +439,12 @@ private fun TopBar(
onSave: () -> Unit = {}, onSave: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null
) { ) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha val cardAlpha = CardConfig.cardAlpha
val statusColor = when(status) { val statusColor = when(status) {

View File

@@ -90,9 +90,11 @@ import com.sukisu.ultra.Natives
import com.sukisu.ultra.R import com.sukisu.ultra.R
import com.sukisu.ultra.ui.component.KsuIsValid import com.sukisu.ultra.ui.component.KsuIsValid
import com.sukisu.ultra.ui.component.rememberConfirmDialog import com.sukisu.ultra.ui.component.rememberConfirmDialog
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import com.sukisu.ultra.ui.theme.getCardColors import com.sukisu.ultra.ui.theme.getCardColors
import com.sukisu.ultra.ui.theme.getCardElevation
import com.sukisu.ultra.ui.util.checkNewVersion import com.sukisu.ultra.ui.util.checkNewVersion
import com.sukisu.ultra.ui.util.getKpmModuleCount import com.sukisu.ultra.ui.util.getKpmModuleCount
import com.sukisu.ultra.ui.util.getKpmVersion import com.sukisu.ultra.ui.util.getKpmVersion
@@ -281,7 +283,12 @@ private fun TopBar(
onInstallClick: () -> Unit, onInstallClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null
) { ) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
TopAppBar( TopAppBar(
title = { title = {
@@ -336,7 +343,7 @@ private fun StatusCard(
ElevatedCard( ElevatedCard(
colors = getCardColors( if (systemStatus.ksuVersion != null)MaterialTheme.colorScheme.secondaryContainer colors = getCardColors( if (systemStatus.ksuVersion != null)MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.errorContainer), else MaterialTheme.colorScheme.errorContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -510,7 +517,7 @@ fun WarningCard(
) { ) {
ElevatedCard( ElevatedCard(
colors = getCardColors(color), colors = getCardColors(color),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -534,7 +541,7 @@ fun ContributionCard() {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -602,7 +609,7 @@ fun DonateCard() {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -641,7 +648,7 @@ private fun InfoCard(
) { ) {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier

View File

@@ -33,7 +33,6 @@ import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -92,6 +91,8 @@ import com.sukisu.ultra.ui.util.isAbDevice
import com.sukisu.ultra.ui.util.isInitBoot import com.sukisu.ultra.ui.util.isInitBoot
import com.sukisu.ultra.ui.util.rootAvailable import com.sukisu.ultra.ui.util.rootAvailable
import com.sukisu.ultra.getKernelVersion import com.sukisu.ultra.getKernelVersion
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.getCardElevation
/** /**
* @author ShirkNeko * @author ShirkNeko
@@ -253,7 +254,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
(lkmSelection as? LkmSelection.LkmUri)?.let { (lkmSelection as? LkmSelection.LkmUri)?.let {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant), colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 12.dp) .padding(bottom = 12.dp)
@@ -279,7 +280,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
if (method.slot != null) { if (method.slot != null) {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant), colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 12.dp) .padding(bottom = 12.dp)
@@ -478,7 +479,7 @@ private fun SelectInstallMethod(
if (isGKI) { if (isGKI) {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant), colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 12.dp) .padding(bottom = 12.dp)
@@ -488,6 +489,11 @@ private fun SelectInstallMethod(
shape = MaterialTheme.shapes.large, shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f) spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
) )
) {
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = MaterialTheme.colorScheme.surfaceVariant
)
) { ) {
ListItem( ListItem(
leadingContent = { leadingContent = {
@@ -507,6 +513,7 @@ private fun SelectInstallMethod(
LKMExpanded = !LKMExpanded LKMExpanded = !LKMExpanded
} }
) )
}
AnimatedVisibility( AnimatedVisibility(
visible = LKMExpanded, visible = LKMExpanded,
@@ -584,7 +591,7 @@ private fun SelectInstallMethod(
if (rootAvailable) { if (rootAvailable) {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant), colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 12.dp) .padding(bottom = 12.dp)
@@ -594,6 +601,11 @@ private fun SelectInstallMethod(
shape = MaterialTheme.shapes.large, shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f) spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
) )
) {
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = MaterialTheme.colorScheme.surfaceVariant
)
) { ) {
ListItem( ListItem(
leadingContent = { leadingContent = {
@@ -613,6 +625,7 @@ private fun SelectInstallMethod(
GKIExpanded = !GKIExpanded GKIExpanded = !GKIExpanded
} }
) )
}
AnimatedVisibility( AnimatedVisibility(
visible = GKIExpanded, visible = GKIExpanded,
@@ -732,7 +745,12 @@ private fun TopBar(
onLkmUpload: () -> Unit = {}, onLkmUpload: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null
) { ) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = cardAlpha val cardAlpha = cardAlpha
TopAppBar( TopAppBar(

View File

@@ -366,7 +366,12 @@ private fun TopBar(
else -> MaterialTheme.colorScheme.primary else -> MaterialTheme.colorScheme.primary
} }
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha val cardAlpha = CardConfig.cardAlpha
TopAppBar( TopAppBar(

View File

@@ -617,7 +617,7 @@ private fun KpmModuleItem(
Card( Card(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation) elevation = getCardElevation()
) { ) {
Column( Column(
modifier = Modifier.padding(20.dp) modifier = Modifier.padding(20.dp)

View File

@@ -72,6 +72,7 @@ import com.dergoogler.mmrl.platform.Platform
import androidx.core.net.toUri import androidx.core.net.toUri
import com.dergoogler.mmrl.platform.model.ModuleConfig import com.dergoogler.mmrl.platform.model.ModuleConfig
import com.dergoogler.mmrl.platform.model.ModuleConfig.Companion.asModuleConfig import com.dergoogler.mmrl.platform.model.ModuleConfig.Companion.asModuleConfig
import com.sukisu.ultra.ui.theme.getCardElevation
/** /**
* @author ShirkNeko * @author ShirkNeko
@@ -711,7 +712,7 @@ fun ModuleItem(
) { ) {
ElevatedCard( ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), elevation = getCardElevation(),
) { ) {
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }

View File

@@ -11,31 +11,42 @@ import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.expandVertically import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.NavigateNext import androidx.compose.material.icons.automirrored.filled.NavigateNext
import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.filled.*
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.material3.HorizontalDivider
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
@@ -49,14 +60,16 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.edit import androidx.core.content.edit
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.sukisu.ultra.Natives import com.sukisu.ultra.Natives
import com.sukisu.ultra.R import com.sukisu.ultra.R
import com.sukisu.ultra.ui.MainActivity import com.sukisu.ultra.ui.MainActivity
@@ -68,6 +81,7 @@ import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import com.sukisu.ultra.ui.theme.ThemeColors import com.sukisu.ultra.ui.theme.ThemeColors
import com.sukisu.ultra.ui.theme.ThemeConfig import com.sukisu.ultra.ui.theme.ThemeConfig
import com.sukisu.ultra.ui.theme.getCardColors import com.sukisu.ultra.ui.theme.getCardColors
import com.sukisu.ultra.ui.theme.getCardElevation
import com.sukisu.ultra.ui.theme.saveAndApplyCustomBackground import com.sukisu.ultra.ui.theme.saveAndApplyCustomBackground
import com.sukisu.ultra.ui.theme.saveCustomBackground import com.sukisu.ultra.ui.theme.saveCustomBackground
import com.sukisu.ultra.ui.theme.saveDynamicColorState import com.sukisu.ultra.ui.theme.saveDynamicColorState
@@ -96,7 +110,7 @@ fun saveCardConfig(context: Context) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph> @Destination<RootGraph>
@Composable @Composable
fun MoreSettingsScreen(navigator: DestinationsNavigator) { fun MoreSettingsScreen() {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val context = LocalContext.current val context = LocalContext.current
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
@@ -393,7 +407,7 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
// 如果启用了系统跟随且系统是深色模式,应用深色模式默认值 // 如果启用了系统跟随且系统是深色模式,应用深色模式默认值
if (themeMode == 0 && systemIsDark) { if (themeMode == 0 && systemIsDark) {
CardConfig.setDarkModeDefaults() CardConfig.setThemeDefaults(true)
} }
currentDpi = prefs.getInt("app_dpi", systemDpi) currentDpi = prefs.getInt("app_dpi", systemDpi)
@@ -476,91 +490,43 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
} }
) )
} }
val cardColor = MaterialTheme.colorScheme.surfaceContainerHigh
val isDarkTheme = isSystemInDarkTheme() val isDarkTheme = isSystemInDarkTheme()
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
TopAppBar( TopBar(scrollBehavior = scrollBehavior)
title = { Text(stringResource(R.string.more_settings)) },
colors = TopAppBarDefaults.topAppBarColors(
containerColor = cardColor.copy(alpha = cardAlpha),
scrolledContainerColor = cardColor.copy(alpha = cardAlpha)),
navigationIcon = {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back))
}
}, },
scrollBehavior = scrollBehavior, contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
)
}
) { paddingValues -> ) { paddingValues ->
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize()
.padding(paddingValues) .padding(paddingValues)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.padding(horizontal = 16.dp, vertical = 8.dp) .padding(horizontal = 16.dp)
.padding(top = 8.dp)
) { ) {
// 外观设置部分 // 外观设置部分
Card( SettingsCard(
modifier = Modifier title = stringResource(R.string.appearance_settings),
.fillMaxWidth() icon = Icons.Default.Palette
.padding(bottom = 16.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation)
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.appearance_settings),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
// 语言设置 // 语言设置
ListItem( SettingItem(
headlineContent = { Text(stringResource(R.string.language_setting)) }, icon = Icons.Default.Language,
supportingContent = { title = stringResource(R.string.language_setting),
Text(supportedLanguages.find { it.first == currentLanguage }?.second subtitle = supportedLanguages.find { it.first == currentLanguage }?.second
?: stringResource(R.string.language_follow_system)) ?: stringResource(R.string.language_follow_system),
}, onClick = { showLanguageDialog = true }
leadingContent = {
Icon(
Icons.Default.Language,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
trailingContent = {
Icon(
Icons.AutoMirrored.Filled.NavigateNext,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
},
modifier = Modifier.clickable { showLanguageDialog = true }
) )
// 主题模式 // 主题模式
ListItem( SettingItem(
headlineContent = { Text(stringResource(R.string.theme_mode)) }, icon = Icons.Default.DarkMode,
supportingContent = { Text(themeOptions[themeMode]) }, title = stringResource(R.string.theme_mode),
leadingContent = { subtitle = themeOptions[themeMode],
Icon( onClick = { showThemeModeDialog = true }
Icons.Default.DarkMode,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
trailingContent = {
Icon(
Icons.AutoMirrored.Filled.NavigateNext,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
},
modifier = Modifier.clickable { showThemeModeDialog = true }
) )
// 动态颜色开关 // 动态颜色开关
@@ -582,11 +548,10 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
enter = fadeIn() + expandVertically(), enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically() exit = fadeOut() + shrinkVertically()
) { ) {
Column { SettingItem(
ListItem( icon = Icons.Default.Palette,
headlineContent = { Text(stringResource(R.string.theme_color)) }, title = stringResource(R.string.theme_color),
supportingContent = { subtitle = when (ThemeConfig.currentTheme) {
val currentThemeName = when (ThemeConfig.currentTheme) {
is ThemeColors.Green -> stringResource(R.string.color_green) is ThemeColors.Green -> stringResource(R.string.color_green)
is ThemeColors.Purple -> stringResource(R.string.color_purple) is ThemeColors.Purple -> stringResource(R.string.color_purple)
is ThemeColors.Orange -> stringResource(R.string.color_orange) is ThemeColors.Orange -> stringResource(R.string.color_orange)
@@ -594,51 +559,50 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
is ThemeColors.Gray -> stringResource(R.string.color_gray) is ThemeColors.Gray -> stringResource(R.string.color_gray)
is ThemeColors.Yellow -> stringResource(R.string.color_yellow) is ThemeColors.Yellow -> stringResource(R.string.color_yellow)
else -> stringResource(R.string.color_default) else -> stringResource(R.string.color_default)
}
Text(currentThemeName)
},
leadingContent = {
Icon(
Icons.Default.Palette,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
}, },
onClick = { showThemeColorDialog = true },
trailingContent = { trailingContent = {
Icon( Row {
Icons.AutoMirrored.Filled.NavigateNext, themeColorOptions.take(4).forEach { (_, theme) ->
contentDescription = null, ColorCircle(
tint = MaterialTheme.colorScheme.onSurfaceVariant color = if (isDarkTheme) theme.primaryDark else theme.primaryLight,
) isSelected = ThemeConfig.currentTheme::class == theme::class,
}, modifier = Modifier.padding(horizontal = 2.dp)
modifier = Modifier.clickable { showThemeColorDialog = true }
) )
} }
} }
}
)
}
// DPI 设置 HorizontalDivider(
ListItem( modifier = Modifier.padding(vertical = 8.dp)
headlineContent = { Text(stringResource(R.string.app_dpi_title)) },
supportingContent = { Text(stringResource(R.string.app_dpi_summary)) },
leadingContent = {
Icon(
Icons.Default.AcUnit,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
) )
},
// DPI 设置
SettingItem(
icon = Icons.Default.FormatSize,
title = stringResource(R.string.app_dpi_title),
subtitle = stringResource(R.string.app_dpi_summary),
onClick = {},
trailingContent = { trailingContent = {
Text( Text(
text = getDpiFriendlyName(tempDpi), text = getDpiFriendlyName(tempDpi),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.primary
) )
} }
) )
// DPI 滑动条 // DPI 滑动条
Column(modifier = Modifier.padding(horizontal = 32.dp, vertical = 8.dp)) { Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
val sliderValue by animateFloatAsState(
targetValue = tempDpi.toFloat(),
label = "DPI Slider Animation"
)
Slider( Slider(
value = tempDpi.toFloat(), value = sliderValue,
onValueChange = { onValueChange = {
tempDpi = it.toInt() tempDpi = it.toInt()
isDpiCustom = !dpiPresets.containsValue(tempDpi) isDpiCustom = !dpiPresets.containsValue(tempDpi)
@@ -658,46 +622,72 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
.padding(top = 8.dp), .padding(top = 8.dp),
) { ) {
dpiPresets.forEach { (name, dpi) -> dpiPresets.forEach { (name, dpi) ->
TextButton( val isSelected = tempDpi == dpi
onClick = { val buttonColor = if (isSelected)
MaterialTheme.colorScheme.primaryContainer
else
MaterialTheme.colorScheme.surfaceVariant
Box(
modifier = Modifier
.weight(1f)
.padding(horizontal = 2.dp)
.clip(RoundedCornerShape(8.dp))
.background(buttonColor)
.clickable {
tempDpi = dpi tempDpi = dpi
isDpiCustom = false isDpiCustom = false
}, }
modifier = Modifier.weight(1f) .padding(vertical = 8.dp, horizontal = 4.dp),
contentAlignment = Alignment.Center
) { ) {
Text( Text(
text = name, text = name,
color = if (tempDpi == dpi) style = MaterialTheme.typography.labelMedium,
MaterialTheme.colorScheme.primary color = if (isSelected)
MaterialTheme.colorScheme.onPrimaryContainer
else else
MaterialTheme.colorScheme.onSurfaceVariant MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis
) )
} }
} }
} }
TextButton(
onClick = {
if (tempDpi != currentDpi) {
showDpiConfirmDialog = true
}
},
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
) {
Text(stringResource(R.string.dpi_apply_settings))
}
Text( Text(
text = if (isDpiCustom) text = if (isDpiCustom)
"${stringResource(R.string.dpi_size_custom)}: $tempDpi" "${stringResource(R.string.dpi_size_custom)}: $tempDpi"
else else
"${getDpiFriendlyName(tempDpi)}: $tempDpi", "${getDpiFriendlyName(tempDpi)}: $tempDpi",
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(top = 4.dp) modifier = Modifier.padding(top = 8.dp)
) )
Button(
onClick = {
if (tempDpi != currentDpi) {
showDpiConfirmDialog = true
} }
},
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
enabled = tempDpi != currentDpi
) {
Icon(
Icons.Default.Check,
contentDescription = null,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(stringResource(R.string.dpi_apply_settings))
}
}
HorizontalDivider(
modifier = Modifier.padding(vertical = 8.dp),
)
// 自定义背景开关 // 自定义背景开关
SwitchItem( SwitchItem(
@@ -711,15 +701,12 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
} else { } else {
context.saveCustomBackground(null) context.saveCustomBackground(null)
isCustomBackgroundEnabled = false isCustomBackgroundEnabled = false
cardElevation
CardConfig.cardAlpha = 1f CardConfig.cardAlpha = 1f
CardConfig.cardDim = 0f CardConfig.cardDim = 0f
CardConfig.isCustomAlphaSet = false CardConfig.isCustomAlphaSet = false
CardConfig.isCustomDimSet = false CardConfig.isCustomDimSet = false
CardConfig.isCustomBackgroundEnabled = false CardConfig.isCustomBackgroundEnabled = false
saveCardConfig(context) saveCardConfig(context)
cardAlpha = 1f
cardDim = 0f
// 重置其他相关设置 // 重置其他相关设置
ThemeConfig.needsResetOnThemeChange = true ThemeConfig.needsResetOnThemeChange = true
@@ -744,11 +731,10 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
// 透明度和亮度调节滑动条 // 透明度和亮度调节滑动条
AnimatedVisibility( AnimatedVisibility(
visible = ThemeConfig.customBackgroundUri != null, visible = ThemeConfig.customBackgroundUri != null,
enter = fadeIn() + expandVertically(), enter = fadeIn() + slideInVertically(),
exit = fadeOut() + shrinkVertically(), exit = fadeOut() + slideOutVertically()
modifier = Modifier.padding(horizontal = 32.dp)
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
// 透明度滑动条 // 透明度滑动条
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -772,8 +758,13 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
) )
} }
val alphaSliderValue by animateFloatAsState(
targetValue = cardAlpha,
label = "Alpha Slider Animation"
)
Slider( Slider(
value = cardAlpha, value = alphaSliderValue,
onValueChange = { newValue -> onValueChange = { newValue ->
cardAlpha = newValue cardAlpha = newValue
CardConfig.cardAlpha = newValue CardConfig.cardAlpha = newValue
@@ -820,8 +811,13 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
) )
} }
val dimSliderValue by animateFloatAsState(
targetValue = cardDim,
label = "Dim Slider Animation"
)
Slider( Slider(
value = cardDim, value = dimSliderValue,
onValueChange = { newValue -> onValueChange = { newValue ->
cardDim = newValue cardDim = newValue
CardConfig.cardDim = newValue CardConfig.cardDim = newValue
@@ -847,22 +843,12 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
} }
} }
} }
}
// 自定义设置部分 // 自定义设置部分
Card( SettingsCard(
modifier = Modifier title = stringResource(R.string.custom_settings),
.fillMaxWidth() icon = Icons.Default.Settings
.padding(bottom = 16.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation)
) { ) {
Column(Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.custom_settings),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
// 添加简洁模式开关 // 添加简洁模式开关
SwitchItem( SwitchItem(
icon = Icons.Filled.Brush, icon = Icons.Filled.Brush,
@@ -925,22 +911,12 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
onHideLinkCardChange(it) onHideLinkCardChange(it)
} }
} }
}
// 高级设置部分 // 高级设置部分
Card( SettingsCard(
modifier = Modifier title = stringResource(R.string.advanced_settings),
.fillMaxWidth() icon = Icons.Default.AdminPanelSettings
.padding(bottom = 16.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation)
) { ) {
Column( Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.advanced_settings),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
// SELinux 开关 // SELinux 开关
KsuIsValid { KsuIsValid {
SwitchItem( SwitchItem(
@@ -1026,7 +1002,6 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
} }
} }
} }
}
// 主题模式选择对话框 // 主题模式选择对话框
if (showThemeModeDialog) { if (showThemeModeDialog) {
@@ -1053,36 +1028,21 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
ThemeConfig.forceDarkMode = true ThemeConfig.forceDarkMode = true
CardConfig.isUserDarkModeEnabled = true CardConfig.isUserDarkModeEnabled = true
CardConfig.isUserLightModeEnabled = false CardConfig.isUserLightModeEnabled = false
if (!CardConfig.isCustomAlphaSet) { CardConfig.setThemeDefaults(true)
CardConfig.cardAlpha = 1f
}
if (!CardConfig.isCustomDimSet) {
CardConfig.cardDim = 0.5f
}
CardConfig.save(context) CardConfig.save(context)
} }
1 -> { // 浅色 1 -> { // 浅色
ThemeConfig.forceDarkMode = false ThemeConfig.forceDarkMode = false
CardConfig.isUserLightModeEnabled = true CardConfig.isUserLightModeEnabled = true
CardConfig.isUserDarkModeEnabled = false CardConfig.isUserDarkModeEnabled = false
if (!CardConfig.isCustomAlphaSet) { CardConfig.setThemeDefaults(false)
CardConfig.cardAlpha = 1f
}
if (!CardConfig.isCustomDimSet) {
CardConfig.cardDim = 0f
}
CardConfig.save(context) CardConfig.save(context)
} }
0 -> { // 跟随系统 0 -> { // 跟随系统
ThemeConfig.forceDarkMode = null ThemeConfig.forceDarkMode = null
CardConfig.isUserLightModeEnabled = false CardConfig.isUserLightModeEnabled = false
CardConfig.isUserDarkModeEnabled = false CardConfig.isUserDarkModeEnabled = false
if (!CardConfig.isCustomAlphaSet) { CardConfig.setThemeDefaults(isDarkTheme)
CardConfig.cardAlpha = 1f
}
if (!CardConfig.isCustomDimSet) {
CardConfig.cardDim = if (isDarkTheme) 0.5f else 0f
}
CardConfig.save(context) CardConfig.save(context)
} }
} }
@@ -1200,3 +1160,143 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
) )
} }
} }
@Composable
fun SettingsCard(
title: String,
icon: ImageVector,
content: @Composable () -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = getCardElevation(),
shape = MaterialTheme.shapes.medium
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
)
}
content()
}
}
}
@Composable
fun SettingItem(
icon: ImageVector,
title: String,
subtitle: String? = null,
onClick: () -> Unit,
iconTint: Color = MaterialTheme.colorScheme.primary,
trailingContent: @Composable (() -> Unit)? = {
Icon(
Icons.AutoMirrored.Filled.NavigateNext,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onClick)
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = iconTint,
modifier = Modifier
.padding(end = 16.dp)
.size(24.dp)
)
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
)
if (subtitle != null) {
Text(
text = subtitle,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
trailingContent?.invoke()
}
}
@Composable
fun ColorCircle(
color: Color,
isSelected: Boolean,
modifier: Modifier = Modifier
) {
Box(
modifier = modifier
.size(20.dp)
.clip(CircleShape)
.background(color)
.then(
if (isSelected) {
Modifier.border(
width = 2.dp,
color = MaterialTheme.colorScheme.primary,
shape = CircleShape
)
} else {
Modifier
}
)
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
TopAppBar(
title = {
Text(
text = stringResource(R.string.more_settings),
style = MaterialTheme.typography.titleLarge
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = cardColor.copy(alpha = CardConfig.cardAlpha),
scrolledContainerColor = cardColor.copy(alpha = CardConfig.cardAlpha)
),
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}

View File

@@ -63,7 +63,6 @@ import com.sukisu.ultra.ui.util.getBugreportFile
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import com.sukisu.ultra.ui.component.KsuIsValid import com.sukisu.ultra.ui.component.KsuIsValid
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
/** /**
* @author ShirkNeko * @author ShirkNeko
@@ -127,7 +126,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation) elevation = getCardElevation()
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text( Text(
@@ -195,7 +194,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation) elevation = getCardElevation()
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text( Text(
@@ -340,7 +339,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation) elevation = getCardElevation()
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text( Text(
@@ -436,7 +435,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp), .padding(horizontal = 16.dp, vertical = 8.dp),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh), colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation) elevation = getCardElevation()
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text( Text(
@@ -740,14 +739,12 @@ fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
private fun TopBar( private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null
) { ) {
val systemIsDark = isSystemInDarkTheme() val colorScheme = MaterialTheme.colorScheme
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
val cardAlpha = if (ThemeConfig.customBackgroundUri != null) { colorScheme.surfaceContainerLow
cardAlpha
} else { } else {
if (systemIsDark) 0.8f else 1f colorScheme.background
} }
TopAppBar( TopAppBar(
title = { title = {
Text( Text(

View File

@@ -231,7 +231,12 @@ private fun TopBar(
colors: TopAppBarColors, colors: TopAppBarColors,
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null
) { ) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha val cardAlpha = CardConfig.cardAlpha
TopAppBar( TopAppBar(

View File

@@ -10,19 +10,15 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
object CardConfig { object CardConfig {
val settingElevation: Dp = 4.dp
val customBackgroundElevation: Dp = 0.dp
// 卡片透明度 // 卡片透明度
var cardAlpha by mutableFloatStateOf(1f) var cardAlpha by mutableFloatStateOf(1f)
// 卡片亮度 // 卡片亮度
var cardDim by mutableFloatStateOf(0f) var cardDim by mutableFloatStateOf(0f)
// 卡片阴影 // 卡片阴影
var cardElevation by mutableStateOf(settingElevation) var cardElevation by mutableStateOf(4.dp)
var isShadowEnabled by mutableStateOf(true) var isShadowEnabled by mutableStateOf(true)
var isCustomAlphaSet by mutableStateOf(false) var isCustomAlphaSet by mutableStateOf(false)
var isCustomDimSet by mutableStateOf(false) var isCustomDimSet by mutableStateOf(false)
@@ -69,37 +65,24 @@ object CardConfig {
*/ */
fun updateShadowEnabled(enabled: Boolean) { fun updateShadowEnabled(enabled: Boolean) {
isShadowEnabled = enabled isShadowEnabled = enabled
cardElevation = if (isCustomBackgroundEnabled && cardAlpha != 1f) { cardElevation = if (isCustomBackgroundEnabled) {
customBackgroundElevation 0.dp
} else if (enabled) { } else if (enabled) {
settingElevation 4.dp
} else { } else {
customBackgroundElevation 0.dp
} }
} }
/** /**
* 设置深色模式默认值 * 设置主题模式默认值
*/ */
fun setDarkModeDefaults() { fun setThemeDefaults(isDarkMode: Boolean) {
if (!isCustomAlphaSet) { if (!isCustomAlphaSet) {
cardAlpha = 1f cardAlpha = 1f
} }
if (!isCustomDimSet) { if (!isCustomDimSet) {
cardDim = 0.5f cardDim = if (isDarkMode) 0.5f else 0f
}
updateShadowEnabled(isShadowEnabled)
}
/**
* 设置浅色模式默认值
*/
fun setLightModeDefaults() {
if (!isCustomAlphaSet) {
cardAlpha = 1f
}
if (!isCustomDimSet) {
cardDim = 0f
} }
updateShadowEnabled(isShadowEnabled) updateShadowEnabled(isShadowEnabled)
} }
@@ -114,6 +97,19 @@ fun getCardColors(originalColor: Color) = CardDefaults.cardColors(
contentColor = determineContentColor(originalColor) contentColor = determineContentColor(originalColor)
) )
/**
* 获取卡片阴影配置
*/
@Composable
fun getCardElevation() = CardDefaults.cardElevation(
defaultElevation = CardConfig.cardElevation,
pressedElevation = if (CardConfig.isCustomBackgroundEnabled) 0.dp else 8.dp,
focusedElevation = if (CardConfig.isCustomBackgroundEnabled) 0.dp else 6.dp,
hoveredElevation = if (CardConfig.isCustomBackgroundEnabled) 0.dp else 4.dp,
draggedElevation = if (CardConfig.isCustomBackgroundEnabled) 0.dp else 8.dp,
disabledElevation = 0.dp
)
/** /**
* 根据背景颜色、主题模式和用户设置确定内容颜色 * 根据背景颜色、主题模式和用户设置确定内容颜色
*/ */

View File

@@ -47,6 +47,7 @@ import com.sukisu.ultra.ui.util.saveTransformedBackground
import androidx.activity.SystemBarStyle import androidx.activity.SystemBarStyle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.SideEffect import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
@@ -150,9 +151,9 @@ fun KernelSUTheme(
// 根据暗色模式和自定义背景调整卡片配置 // 根据暗色模式和自定义背景调整卡片配置
val isDarkModeWithCustomBackground = darkTheme && ThemeConfig.customBackgroundUri != null val isDarkModeWithCustomBackground = darkTheme && ThemeConfig.customBackgroundUri != null
if (darkTheme && !dynamicColor) { if (darkTheme && !dynamicColor) {
CardConfig.setDarkModeDefaults() CardConfig.setThemeDefaults(true)
} else if (!darkTheme && !dynamicColor) { } else if (!darkTheme && !dynamicColor) {
CardConfig.setLightModeDefaults() CardConfig.setThemeDefaults(false)
} }
CardConfig.updateShadowEnabled(!isDarkModeWithCustomBackground) CardConfig.updateShadowEnabled(!isDarkModeWithCustomBackground)
@@ -216,7 +217,8 @@ fun KernelSUTheme(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.zIndex(-2f) .zIndex(-2f)
.background(if (darkTheme) MaterialTheme.colorScheme.surfaceContainerLow else MaterialTheme.colorScheme.surfaceContainerLow) .background(if (darkTheme) if (CardConfig.isCustomBackgroundEnabled) { colorScheme.surfaceContainerLow } else { colorScheme.background }
else if (CardConfig.isCustomBackgroundEnabled) { colorScheme.surfaceContainerLow } else { colorScheme.background })
) )
// 自定义背景层 // 自定义背景层
@@ -287,22 +289,30 @@ fun KernelSUTheme(
*/ */
@RequiresApi(Build.VERSION_CODES.S) @RequiresApi(Build.VERSION_CODES.S)
@Composable @Composable
private fun createDynamicDarkColorScheme(context: Context) = private fun createDynamicDarkColorScheme(context: Context): ColorScheme {
dynamicDarkColorScheme(context).copy( val scheme = dynamicDarkColorScheme(context)
background = Color.Transparent, return scheme.copy(
surface = Color.Transparent background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.background,
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.surface,
onBackground = Color.White,
onSurface = Color.White
) )
}
/** /**
* 创建动态浅色颜色方案 * 创建动态浅色颜色方案
*/ */
@RequiresApi(Build.VERSION_CODES.S) @RequiresApi(Build.VERSION_CODES.S)
@Composable @Composable
private fun createDynamicLightColorScheme(context: Context) = private fun createDynamicLightColorScheme(context: Context): ColorScheme {
dynamicLightColorScheme(context).copy( val scheme = dynamicLightColorScheme(context)
background = Color.Transparent, return scheme.copy(
surface = Color.Transparent background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.background,
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.surface
) )
}
/** /**
* 创建深色颜色方案 * 创建深色颜色方案
@@ -325,9 +335,9 @@ private fun createDarkColorScheme() = darkColorScheme(
onError = ThemeConfig.currentTheme.onErrorDark, onError = ThemeConfig.currentTheme.onErrorDark,
errorContainer = ThemeConfig.currentTheme.errorContainerDark, errorContainer = ThemeConfig.currentTheme.errorContainerDark,
onErrorContainer = ThemeConfig.currentTheme.onErrorContainerDark, onErrorContainer = ThemeConfig.currentTheme.onErrorContainerDark,
background = Color.Transparent, background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.backgroundDark,
onBackground = ThemeConfig.currentTheme.onBackgroundDark, onBackground = ThemeConfig.currentTheme.onBackgroundDark,
surface = Color.Transparent, surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.surfaceDark,
onSurface = ThemeConfig.currentTheme.onSurfaceDark, onSurface = ThemeConfig.currentTheme.onSurfaceDark,
surfaceVariant = ThemeConfig.currentTheme.surfaceVariantDark, surfaceVariant = ThemeConfig.currentTheme.surfaceVariantDark,
onSurfaceVariant = ThemeConfig.currentTheme.onSurfaceVariantDark, onSurfaceVariant = ThemeConfig.currentTheme.onSurfaceVariantDark,
@@ -367,9 +377,9 @@ private fun createLightColorScheme() = lightColorScheme(
onError = ThemeConfig.currentTheme.onErrorLight, onError = ThemeConfig.currentTheme.onErrorLight,
errorContainer = ThemeConfig.currentTheme.errorContainerLight, errorContainer = ThemeConfig.currentTheme.errorContainerLight,
onErrorContainer = ThemeConfig.currentTheme.onErrorContainerLight, onErrorContainer = ThemeConfig.currentTheme.onErrorContainerLight,
background = Color.Transparent, background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.backgroundLight,
onBackground = ThemeConfig.currentTheme.onBackgroundLight, onBackground = ThemeConfig.currentTheme.onBackgroundLight,
surface = Color.Transparent, surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.surfaceLight,
onSurface = ThemeConfig.currentTheme.onSurfaceLight, onSurface = ThemeConfig.currentTheme.onSurfaceLight,
surfaceVariant = ThemeConfig.currentTheme.surfaceVariantLight, surfaceVariant = ThemeConfig.currentTheme.surfaceVariantLight,
onSurfaceVariant = ThemeConfig.currentTheme.onSurfaceVariantLight, onSurfaceVariant = ThemeConfig.currentTheme.onSurfaceVariantLight,
@@ -388,6 +398,7 @@ private fun createLightColorScheme() = lightColorScheme(
surfaceContainerHighest = ThemeConfig.currentTheme.surfaceContainerHighestLight, surfaceContainerHighest = ThemeConfig.currentTheme.surfaceContainerHighestLight,
) )
/** /**
* 复制图片到应用内部存储并提升持久性 * 复制图片到应用内部存储并提升持久性
*/ */