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,47 +55,55 @@ fun SwitchItem(
disabledUncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant disabledUncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant
) )
ListItem( MaterialTheme(
headlineContent = { colorScheme = MaterialTheme.colorScheme.copy(
Text( surface = MaterialTheme.colorScheme.surfaceContainerHigh
text = title, )
style = MaterialTheme.typography.titleMedium, ) {
maxLines = Int.MAX_VALUE, ListItem(
overflow = TextOverflow.Ellipsis headlineContent = {
)
},
supportingContent = summary?.let {
{
Text( Text(
text = it, text = title,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = Int.MAX_VALUE, maxLines = Int.MAX_VALUE,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
} },
}, supportingContent = summary?.let {
leadingContent = { {
Icon( Text(
imageVector = icon, text = it,
contentDescription = null, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.size(24.dp), color = MaterialTheme.colorScheme.onSurfaceVariant,
tint = iconTint maxLines = Int.MAX_VALUE,
) overflow = TextOverflow.Ellipsis
}, )
trailingContent = { }
Switch( },
checked = checked, leadingContent = icon?.let {
onCheckedChange = null, {
enabled = enabled, Icon(
colors = switchColors imageVector = it,
) contentDescription = null,
}, modifier = Modifier.size(24.dp),
modifier = Modifier tint = iconTint
.fillMaxWidth() )
.clickable(enabled = enabled) { }
onCheckedChange(!checked) },
} trailingContent = {
.padding(vertical = 4.dp) Switch(
) checked = checked,
onCheckedChange = null,
enabled = enabled,
colors = switchColors
)
},
modifier = Modifier
.fillMaxWidth()
.clickable(enabled = enabled) {
onCheckedChange(!checked)
}
.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,149 +209,172 @@ 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)
Column(modifier = modifier) { MaterialTheme(
ElevatedCard( colorScheme = MaterialTheme.colorScheme.copy(
modifier = Modifier surface = MaterialTheme.colorScheme.surfaceContainerHigh
.fillMaxWidth() )
.padding(horizontal = 16.dp, vertical = 8.dp), ) {
shape = MaterialTheme.shapes.medium Column(modifier = modifier) {
) { ElevatedCard(
AppMenuBox(packageName) { modifier = Modifier
ListItem( .fillMaxWidth()
headlineContent = { .padding(horizontal = 16.dp, vertical = 8.dp),
Text( shape = MaterialTheme.shapes.medium,
text = appLabel, colors = cardColors,
style = MaterialTheme.typography.titleMedium elevation = getCardElevation(),
) ) {
}, AppMenuBox(packageName) {
supportingContent = { ListItem(
Text( headlineContent = {
text = packageName, Text(
style = MaterialTheme.typography.bodyMedium, text = appLabel,
color = MaterialTheme.colorScheme.onSurfaceVariant style = MaterialTheme.typography.titleMedium
) )
}, },
leadingContent = appIcon, supportingContent = {
Text(
text = packageName,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
},
leadingContent = appIcon,
)
}
}
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
SwitchItem(
icon = Icons.Filled.Security,
title = stringResource(id = R.string.superuser),
checked = isRootGranted,
onCheckedChange = { onProfileChange(profile.copy(allowSu = it)) },
) )
} }
}
ElevatedCard( Crossfade(
modifier = Modifier targetState = isRootGranted,
.fillMaxWidth() label = "RootAccess"
.padding(horizontal = 16.dp, vertical = 8.dp), ) { current ->
shape = MaterialTheme.shapes.medium Column(
) { modifier = Modifier.padding(bottom = 6.dp + 48.dp + 6.dp /* SnackBar height */)
SwitchItem( ) {
icon = Icons.Filled.Security, if (current) {
title = stringResource(id = R.string.superuser), val initialMode = if (profile.rootUseDefault) {
checked = isRootGranted, Mode.Default
onCheckedChange = { onProfileChange(profile.copy(allowSu = it)) }, } else if (profile.rootTemplate != null) {
) Mode.Template
} } else {
Mode.Custom
Crossfade( }
targetState = isRootGranted, var mode by rememberSaveable {
label = "RootAccess" mutableStateOf(initialMode)
) { current ->
Column(
modifier = Modifier.padding(bottom = 6.dp + 48.dp + 6.dp /* SnackBar height */)
) {
if (current) {
val initialMode = if (profile.rootUseDefault) {
Mode.Default
} else if (profile.rootTemplate != null) {
Mode.Template
} else {
Mode.Custom
}
var mode by rememberSaveable {
mutableStateOf(initialMode)
}
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
) {
ProfileBox(mode, true) {
// template mode shouldn't change profile here!
if (it == Mode.Default || it == Mode.Custom) {
onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
}
mode = it
} }
}
AnimatedVisibility(
visible = mode != Mode.Default,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
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,
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { ProfileBox(mode, true) {
Crossfade(targetState = mode, label = "ProfileMode") { currentMode -> // template mode shouldn't change profile here!
when (currentMode) { if (it == Mode.Default || it == Mode.Custom) {
Mode.Template -> { onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
TemplateConfig( }
profile = profile, mode = it
onViewTemplate = onViewTemplate, }
onManageTemplate = onManageTemplate, }
onProfileChange = onProfileChange
) AnimatedVisibility(
visible = mode != Mode.Default,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Crossfade(
targetState = mode,
label = "ProfileMode"
) { currentMode ->
when (currentMode) {
Mode.Template -> {
TemplateConfig(
profile = profile,
onViewTemplate = onViewTemplate,
onManageTemplate = onManageTemplate,
onProfileChange = onProfileChange
)
}
Mode.Custom -> {
RootProfileConfig(
fixedName = true,
profile = profile,
onProfileChange = onProfileChange
)
}
else -> {}
} }
Mode.Custom -> {
RootProfileConfig(
fixedName = true,
profile = profile,
onProfileChange = onProfileChange
)
}
else -> {}
} }
} }
} }
} }
} } else {
} else { val mode = if (profile.nonRootUseDefault) Mode.Default else Mode.Custom
val mode = if (profile.nonRootUseDefault) Mode.Default else Mode.Custom
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
) {
ProfileBox(mode, false) {
onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default)))
}
}
AnimatedVisibility(
visible = mode == Mode.Custom,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
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(),
) { ) {
Column(modifier = Modifier.padding(vertical = 8.dp)) { ProfileBox(mode, false) {
AppProfileConfig( onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default)))
fixedName = true, }
profile = profile, }
enabled = mode == Mode.Custom,
onProfileChange = onProfileChange AnimatedVisibility(
) visible = mode == Mode.Custom,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
AppProfileConfig(
fixedName = true,
profile = profile,
enabled = mode == Mode.Custom,
onProfileChange = onProfileChange
)
}
} }
} }
} }
@@ -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,20 +595,26 @@ 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("")) }
Surface { MaterialTheme(
AppProfileInner( colorScheme = MaterialTheme.colorScheme.copy(
packageName = "icu.nullptr.test", surface = MaterialTheme.colorScheme.surfaceContainerHigh
appLabel = "Test",
appIcon = {
Icon(
imageVector = Icons.Filled.Android,
contentDescription = null,
)
},
profile = profile,
onProfileChange = {
profile = it
},
) )
) {
Surface {
AppProfileInner(
packageName = "icu.nullptr.test",
appLabel = "Test",
appIcon = {
Icon(
imageVector = Icons.Filled.Android,
contentDescription = null,
)
},
profile = profile,
onProfileChange = {
profile = it
},
)
}
} }
} }

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)
@@ -489,24 +490,30 @@ private fun SelectInstallMethod(
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f) spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
) )
) { ) {
ListItem( MaterialTheme(
leadingContent = { colorScheme = MaterialTheme.colorScheme.copy(
Icon( surface = MaterialTheme.colorScheme.surfaceVariant
Icons.Filled.AutoFixHigh, )
contentDescription = null, ) {
tint = MaterialTheme.colorScheme.primary ListItem(
) leadingContent = {
}, Icon(
headlineContent = { Icons.Filled.AutoFixHigh,
Text( contentDescription = null,
stringResource(R.string.Lkm_install_methods), tint = MaterialTheme.colorScheme.primary
style = MaterialTheme.typography.titleMedium )
) },
}, headlineContent = {
modifier = Modifier.clickable { Text(
LKMExpanded = !LKMExpanded stringResource(R.string.Lkm_install_methods),
} style = MaterialTheme.typography.titleMedium
) )
},
modifier = Modifier.clickable {
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)
@@ -595,24 +602,30 @@ private fun SelectInstallMethod(
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f) spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
) )
) { ) {
ListItem( MaterialTheme(
leadingContent = { colorScheme = MaterialTheme.colorScheme.copy(
Icon( surface = MaterialTheme.colorScheme.surfaceVariant
Icons.Filled.FileUpload, )
contentDescription = null, ) {
tint = MaterialTheme.colorScheme.primary ListItem(
) leadingContent = {
}, Icon(
headlineContent = { Icons.Filled.FileUpload,
Text( contentDescription = null,
stringResource(R.string.GKI_install_methods), tint = MaterialTheme.colorScheme.primary
style = MaterialTheme.typography.titleMedium )
) },
}, headlineContent = {
modifier = Modifier.clickable { Text(
GKIExpanded = !GKIExpanded stringResource(R.string.GKI_install_methods),
} style = MaterialTheme.typography.titleMedium
) )
},
modifier = Modifier.clickable {
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

@@ -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,
) )
/** /**
* 复制图片到应用内部存储并提升持久性 * 复制图片到应用内部存储并提升持久性
*/ */