mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-26 09:44:55 +00:00
Section facelift: LIGHT canvas swap, equal padding, 2dp item dividers
- LIGHT canvas (themedBackground) now paints the off-white formula (bg.mixWith(onBackground, 0.95f)) so white cards read as raised. DARK/BLACK keep palette bg (cards already raised via founder's formula in Section.kt). SIMPLEX keeps its gradient. - Section cards in LIGHT switch from formula to pure white via Color.White. DARK/BLACK keep the formula, unchanged. - Section card horizontal padding equalized to 16dp on outer + inner for clean canvas-edge alignment. extraPadding (icon-indented rows) keeps DEFAULT_PADDING * 1.7f. - 2dp dividers between rows inside section cards, color matches the per-theme canvas (SIMPLEX uses gradient bottom stop). Implemented via Modifier.drawBehind on each SectionItemView, gated by a private LocalInSectionCard CompositionLocal set true only by SectionView's inner Column — standalone SectionItemView usage (alerts, pickers) stays unaffected. Single canvas helper canvasColorForCurrentTheme() in Theme.kt is the source of truth for both canvas paint and divider color. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+18
-1
@@ -596,13 +596,30 @@ data class ThemeModeOverride (
|
||||
}
|
||||
}
|
||||
|
||||
// Canvas color for settings/info screens (drawn behind cards by themedBackground)
|
||||
// and for the 2dp item divider inside section cards (matches canvas so dividers
|
||||
// read as gaps showing the screen behind).
|
||||
// LIGHT: formula derives off-white from palette bg + onBackground — lifts white
|
||||
// cards above. DARK/BLACK: palette bg (cards already raised via founder's
|
||||
// formula in Section.kt). SIMPLEX: gradient bottom stop (darker), since the
|
||||
// canvas itself is a gradient drawn by themedBackgroundBrush.
|
||||
fun canvasColorForCurrentTheme(): Color {
|
||||
val theme = CurrentColors.value
|
||||
val c = theme.colors
|
||||
return when (theme.base) {
|
||||
DefaultTheme.LIGHT -> c.background.mixWith(c.onBackground, 0.95f)
|
||||
DefaultTheme.SIMPLEX -> c.background.darker(0.4f)
|
||||
else -> c.background
|
||||
}
|
||||
}
|
||||
|
||||
fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, bgLayerSize: MutableState<IntSize>?, bgLayer: GraphicsLayer?/*, shape: Shape = RectangleShape*/): Modifier {
|
||||
return drawBehind {
|
||||
copyBackgroundToAppBar(bgLayerSize, bgLayer) {
|
||||
if (baseTheme == DefaultTheme.SIMPLEX) {
|
||||
drawRect(brush = themedBackgroundBrush())
|
||||
} else {
|
||||
drawRect(CurrentColors.value.colors.background)
|
||||
drawRect(canvasColorForCurrentTheme())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+62
-34
@@ -6,6 +6,8 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
@@ -23,10 +25,25 @@ import chat.simplex.common.views.usersettings.SettingsActionItemWithContent
|
||||
import chat.simplex.res.MR
|
||||
|
||||
private val SectionCardShape = RoundedCornerShape(16.dp)
|
||||
private val CARD_PADDING = 16.dp
|
||||
|
||||
// Set to true by SectionView around its inner Column. SectionItemView reads it
|
||||
// to decide whether to draw the 2dp bottom divider. False default keeps
|
||||
// standalone usage (alerts, pickers, custom contexts) unaffected.
|
||||
private val LocalInSectionCard = staticCompositionLocalOf { false }
|
||||
|
||||
@Composable
|
||||
private fun Modifier.sectionItemDivider(): Modifier {
|
||||
if (!LocalInSectionCard.current) return this
|
||||
return this.drawBehind {
|
||||
drawLine(canvasColorForCurrentTheme(), Offset(0f, size.height), Offset(size.width, size.height), strokeWidth = 2.dp.toPx())
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = 8.dp, content: (@Composable ColumnScope.() -> Unit)) {
|
||||
val cardColor = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f)
|
||||
val cardColor = if (CurrentColors.value.base == DefaultTheme.LIGHT) Color.White
|
||||
else MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f)
|
||||
Column {
|
||||
if (title != null) {
|
||||
Text(
|
||||
@@ -34,14 +51,16 @@ fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingVa
|
||||
modifier = Modifier.padding(start = DEFAULT_PADDING + DEFAULT_PADDING_HALF, bottom = headerBottomPadding), fontSize = 12.sp
|
||||
)
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = DEFAULT_PADDING_HALF)
|
||||
.fillMaxWidth()
|
||||
.clip(SectionCardShape)
|
||||
.background(cardColor)
|
||||
.padding(contentPadding)
|
||||
) { content() }
|
||||
CompositionLocalProvider(LocalInSectionCard provides true) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = CARD_PADDING)
|
||||
.fillMaxWidth()
|
||||
.clip(SectionCardShape)
|
||||
.background(cardColor)
|
||||
.padding(contentPadding)
|
||||
) { content() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +73,8 @@ fun SectionView(
|
||||
padding: PaddingValues = PaddingValues(),
|
||||
content: (@Composable ColumnScope.() -> Unit)
|
||||
) {
|
||||
val cardColor = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f)
|
||||
val cardColor = if (CurrentColors.value.base == DefaultTheme.LIGHT) Color.White
|
||||
else MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f)
|
||||
Column {
|
||||
val iconSize = with(LocalDensity.current) { 21.sp.toDp() }
|
||||
Row(Modifier.padding(start = DEFAULT_PADDING + DEFAULT_PADDING_HALF, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
@@ -62,20 +82,23 @@ fun SectionView(
|
||||
Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp)
|
||||
if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint)
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = DEFAULT_PADDING_HALF)
|
||||
.fillMaxWidth()
|
||||
.clip(SectionCardShape)
|
||||
.background(cardColor)
|
||||
.padding(padding)
|
||||
) { content() }
|
||||
CompositionLocalProvider(LocalInSectionCard provides true) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = CARD_PADDING)
|
||||
.fillMaxWidth()
|
||||
.clip(SectionCardShape)
|
||||
.background(cardColor)
|
||||
.padding(padding)
|
||||
) { content() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () -> Unit)?, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = 8.dp, content: (@Composable ColumnScope.() -> Unit)) {
|
||||
val cardColor = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f)
|
||||
val cardColor = if (CurrentColors.value.base == DefaultTheme.LIGHT) Color.White
|
||||
else MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.95f)
|
||||
Column {
|
||||
if (title != null || titleButton != null) {
|
||||
Row(modifier = Modifier.padding(start = DEFAULT_PADDING + DEFAULT_PADDING_HALF, end = DEFAULT_PADDING + DEFAULT_PADDING_HALF, bottom = headerBottomPadding).fillMaxWidth()) {
|
||||
@@ -88,14 +111,16 @@ fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () ->
|
||||
}
|
||||
}
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = DEFAULT_PADDING_HALF)
|
||||
.fillMaxWidth()
|
||||
.clip(SectionCardShape)
|
||||
.background(cardColor)
|
||||
.padding(contentPadding)
|
||||
) { content() }
|
||||
CompositionLocalProvider(LocalInSectionCard provides true) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = CARD_PADDING)
|
||||
.fillMaxWidth()
|
||||
.clip(SectionCardShape)
|
||||
.background(cardColor)
|
||||
.padding(contentPadding)
|
||||
) { content() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,14 +174,15 @@ fun SectionItemView(
|
||||
disabled: Boolean = false,
|
||||
extraPadding: Boolean = false,
|
||||
padding: PaddingValues = if (extraPadding)
|
||||
PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL)
|
||||
PaddingValues(start = DEFAULT_PADDING * 1.7f, end = CARD_PADDING, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL)
|
||||
else
|
||||
PaddingValues(horizontal = DEFAULT_PADDING, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL),
|
||||
PaddingValues(horizontal = CARD_PADDING, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL),
|
||||
content: (@Composable RowScope.() -> Unit)
|
||||
) {
|
||||
val modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.sizeIn(minHeight = minHeight)
|
||||
.sectionItemDivider()
|
||||
Row(
|
||||
if (click == null || disabled) modifier.padding(padding) else modifier.clickable(onClick = click).padding(padding),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@@ -172,9 +198,9 @@ fun SectionItemViewWithoutMinPadding(
|
||||
disabled: Boolean = false,
|
||||
extraPadding: Boolean = false,
|
||||
padding: PaddingValues = if (extraPadding)
|
||||
PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING)
|
||||
PaddingValues(start = DEFAULT_PADDING * 1.7f, end = CARD_PADDING)
|
||||
else
|
||||
PaddingValues(horizontal = DEFAULT_PADDING),
|
||||
PaddingValues(horizontal = CARD_PADDING),
|
||||
content: (@Composable RowScope.() -> Unit)
|
||||
) {
|
||||
SectionItemView(click, minHeight, disabled, extraPadding, padding, content)
|
||||
@@ -188,14 +214,15 @@ fun SectionItemViewLongClickable(
|
||||
disabled: Boolean = false,
|
||||
extraPadding: Boolean = false,
|
||||
padding: PaddingValues = if (extraPadding)
|
||||
PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL)
|
||||
PaddingValues(start = DEFAULT_PADDING * 1.7f, end = CARD_PADDING, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL)
|
||||
else
|
||||
PaddingValues(horizontal = DEFAULT_PADDING, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL),
|
||||
PaddingValues(horizontal = CARD_PADDING, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL),
|
||||
content: (@Composable RowScope.() -> Unit)
|
||||
) {
|
||||
val modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.sizeIn(minHeight = minHeight)
|
||||
.sectionItemDivider()
|
||||
Row(
|
||||
if (disabled) {
|
||||
modifier.padding(padding)
|
||||
@@ -213,13 +240,14 @@ fun SectionItemViewSpaceBetween(
|
||||
click: (() -> Unit)? = null,
|
||||
onLongClick: (() -> Unit)? = null,
|
||||
minHeight: Dp = DEFAULT_MIN_SECTION_ITEM_HEIGHT,
|
||||
padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING),
|
||||
padding: PaddingValues = PaddingValues(horizontal = CARD_PADDING),
|
||||
disabled: Boolean = false,
|
||||
content: (@Composable RowScope.() -> Unit)
|
||||
) {
|
||||
val modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.sizeIn(minHeight = minHeight)
|
||||
.sectionItemDivider()
|
||||
Row(
|
||||
if (click == null || disabled) modifier.padding(padding).padding(vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL) else modifier
|
||||
.combinedClickable(onClick = click, onLongClick = onLongClick).padding(padding)
|
||||
|
||||
Reference in New Issue
Block a user