feat(ui): complete app experience redesign
This commit is contained in:
+40
-6
@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
@@ -476,13 +477,19 @@ fun ABoxDeviceDetailScaffold(
|
||||
title: String,
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitle: String? = null,
|
||||
icon: ABoxIconKey = ABoxIconKey.UNKNOWN_DEVICE,
|
||||
action: (@Composable () -> Unit)? = null,
|
||||
content: @Composable (PaddingValues) -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.statusBarsPadding()
|
||||
.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
ABoxIconButton(
|
||||
@@ -490,11 +497,38 @@ fun ABoxDeviceDetailScaffold(
|
||||
contentDescription = "返回",
|
||||
onClick = onBack,
|
||||
)
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
)
|
||||
Surface(
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
color = MaterialTheme.colorScheme.primaryContainer,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
) {
|
||||
ABoxIcon(
|
||||
key = icon,
|
||||
contentDescription = subtitle ?: title,
|
||||
modifier = Modifier.padding(9.dp).size(24.dp),
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.weight(1f).padding(start = 12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
text = subtitle,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
action?.invoke()
|
||||
}
|
||||
},
|
||||
content = content,
|
||||
|
||||
+15
@@ -12,6 +12,8 @@ import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Density
|
||||
import com.flagship.abox.manager.designsystem.renderer.ABoxRendererAdapters
|
||||
import com.flagship.abox.manager.preferences.DesignRenderer
|
||||
import com.flagship.abox.manager.designsystem.tokens.ABoxColorTokens
|
||||
@@ -20,6 +22,7 @@ import com.flagship.abox.manager.designsystem.tokens.ABoxThemeDefaults
|
||||
import com.flagship.abox.manager.designsystem.tokens.ABoxThemeResolution
|
||||
import com.flagship.abox.manager.designsystem.tokens.ABoxThemeResolver
|
||||
import com.flagship.abox.manager.preferences.AppThemeMode
|
||||
import com.flagship.abox.manager.preferences.NavigationPresentation
|
||||
import com.flagship.abox.manager.preferences.UiPreferences
|
||||
|
||||
val LocalABoxColors = staticCompositionLocalOf { ABoxThemeDefaults.lightColors }
|
||||
@@ -29,6 +32,9 @@ val LocalABoxShapes = staticCompositionLocalOf { ABoxThemeDefaults.material3Shap
|
||||
val LocalABoxRenderer = staticCompositionLocalOf { DesignRenderer.MATERIAL3 }
|
||||
val LocalABoxReducedMotion = staticCompositionLocalOf { false }
|
||||
val LocalABoxBlurEnabled = staticCompositionLocalOf { false }
|
||||
val LocalABoxNavigationPresentation = staticCompositionLocalOf { NavigationPresentation.STANDARD }
|
||||
val LocalABoxLiquidGlassEnabled = staticCompositionLocalOf { false }
|
||||
val LocalABoxPredictiveBackEnabled = staticCompositionLocalOf { false }
|
||||
|
||||
@Composable
|
||||
fun ABoxTheme(
|
||||
@@ -78,8 +84,14 @@ internal fun ABoxThemeContent(
|
||||
dynamicColorTokens = dynamicColorTokens,
|
||||
)
|
||||
val renderer = ABoxRendererAdapters.forRenderer(resolution.renderer)
|
||||
val density = LocalDensity.current
|
||||
val scaledDensity = Density(
|
||||
density = density.density * (preferences.interfaceScale.percent / 100f),
|
||||
fontScale = density.fontScale,
|
||||
)
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalDensity provides scaledDensity,
|
||||
LocalABoxColors provides resolution.colorTokens,
|
||||
LocalABoxSpacing provides ABoxSpacing(),
|
||||
LocalABoxTypography provides ABoxTypography,
|
||||
@@ -87,6 +99,9 @@ internal fun ABoxThemeContent(
|
||||
LocalABoxRenderer provides resolution.renderer,
|
||||
LocalABoxReducedMotion provides reducedMotion,
|
||||
LocalABoxBlurEnabled provides resolution.blurEnabled,
|
||||
LocalABoxNavigationPresentation provides preferences.navigationPresentation,
|
||||
LocalABoxLiquidGlassEnabled provides preferences.liquidGlassEnabled,
|
||||
LocalABoxPredictiveBackEnabled provides preferences.predictiveBackEnabled,
|
||||
) {
|
||||
renderer.Render(
|
||||
resolution = resolution,
|
||||
|
||||
+15
@@ -11,6 +11,11 @@ import androidx.compose.material.icons.outlined.Edit
|
||||
import androidx.compose.material.icons.outlined.ErrorOutline
|
||||
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.outlined.History
|
||||
import androidx.compose.material.icons.outlined.Palette
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.Tune
|
||||
import androidx.compose.material.icons.outlined.Vibration
|
||||
import androidx.compose.material.icons.outlined.ViewCarousel
|
||||
import androidx.compose.material.icons.outlined.Layers
|
||||
import androidx.compose.material.icons.outlined.Power
|
||||
import androidx.compose.material.icons.outlined.PowerSettingsNew
|
||||
@@ -51,6 +56,11 @@ enum class ABoxIconKey {
|
||||
WARNING,
|
||||
ERROR,
|
||||
UNKNOWN_DEVICE,
|
||||
SETTINGS,
|
||||
THEME,
|
||||
EFFECTS,
|
||||
FEEDBACK,
|
||||
SCALE,
|
||||
}
|
||||
|
||||
/** Design-system-owned device categories; this module does not depend on domain models. */
|
||||
@@ -94,6 +104,11 @@ object ABoxIconMapper {
|
||||
ABoxIconKey.WARNING -> Icons.Outlined.Warning
|
||||
ABoxIconKey.ERROR -> Icons.Outlined.ErrorOutline
|
||||
ABoxIconKey.UNKNOWN_DEVICE -> Icons.AutoMirrored.Outlined.HelpOutline
|
||||
ABoxIconKey.SETTINGS -> Icons.Outlined.Settings
|
||||
ABoxIconKey.THEME -> Icons.Outlined.Palette
|
||||
ABoxIconKey.EFFECTS -> Icons.Outlined.ViewCarousel
|
||||
ABoxIconKey.FEEDBACK -> Icons.Outlined.Vibration
|
||||
ABoxIconKey.SCALE -> Icons.Outlined.Tune
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -6,10 +6,7 @@ import com.flagship.abox.manager.preferences.DesignRenderer
|
||||
|
||||
internal interface ABoxRendererAdapter {
|
||||
@Composable
|
||||
fun Render(
|
||||
resolution: ABoxThemeResolution,
|
||||
content: @Composable () -> Unit,
|
||||
)
|
||||
fun Render(resolution: ABoxThemeResolution, content: @Composable () -> Unit)
|
||||
}
|
||||
|
||||
internal object ABoxRendererAdapters {
|
||||
|
||||
+5
-5
@@ -13,11 +13,11 @@ internal object MiuixRendererAdapter : ABoxRendererAdapter {
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val colors = if (resolution.isDarkTheme) darkColorScheme() else lightColorScheme()
|
||||
MiuixTheme(
|
||||
colors = colors,
|
||||
) {
|
||||
Material3RendererAdapter.Render(
|
||||
resolution = resolution,
|
||||
MiuixTheme(colors = colors) {
|
||||
androidx.compose.material3.MaterialTheme(
|
||||
colorScheme = com.flagship.abox.manager.designsystem.materialColorScheme(resolution),
|
||||
typography = com.flagship.abox.manager.designsystem.ABoxTypography,
|
||||
shapes = com.flagship.abox.manager.designsystem.ABoxShapes(resolution.shapeTokens),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
+13
-1
@@ -5,6 +5,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.flagship.abox.manager.preferences.AppThemeMode
|
||||
import com.flagship.abox.manager.preferences.AccentPreference
|
||||
import com.flagship.abox.manager.preferences.DesignRenderer
|
||||
import com.flagship.abox.manager.preferences.UiPreferences
|
||||
|
||||
@@ -121,7 +122,7 @@ object ABoxThemeResolver {
|
||||
val colorTokens = if (preferences.dynamicColorEnabled && sdkInt >= 31 && dynamicColorTokens != null) {
|
||||
dynamicColorTokens
|
||||
} else {
|
||||
brandTokens
|
||||
brandTokens.withAccent(preferences.accentPreference, isDarkTheme)
|
||||
}
|
||||
val shapeTokens = when (preferences.renderer) {
|
||||
DesignRenderer.MATERIAL3 -> ABoxThemeDefaults.material3Shapes
|
||||
@@ -137,3 +138,14 @@ object ABoxThemeResolver {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ABoxColorTokens.withAccent(accent: AccentPreference, dark: Boolean): ABoxColorTokens {
|
||||
val selected = when (accent) {
|
||||
AccentPreference.BLUE -> if (dark) Color(0xFF9CCAFF) else Color(0xFF385F9D)
|
||||
AccentPreference.GREEN -> if (dark) Color(0xFF7EDFA7) else Color(0xFF247A4B)
|
||||
AccentPreference.AMBER -> if (dark) Color(0xFFFFC46B) else Color(0xFF8A5800)
|
||||
AccentPreference.ROSE -> if (dark) Color(0xFFFFB1C1) else Color(0xFFA43C59)
|
||||
AccentPreference.VIOLET -> if (dark) Color(0xFFD4BBFF) else Color(0xFF6D52A2)
|
||||
}
|
||||
return copy(primary = selected, deviceSocket = selected)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user