Polish flat Android interface

This commit is contained in:
fy59 2026-09-06 21:40:00 +02:00
parent 276b27f781
commit 83a88d98a3
5 changed files with 203 additions and 273 deletions

View file

@ -1,12 +1,8 @@
package com.labfytools.trainlog.ui package com.labfytools.trainlog.ui
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
@ -20,13 +16,10 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.labfytools.trainlog.data.SaveBodyObservationResult import com.labfytools.trainlog.data.SaveBodyObservationResult
import com.labfytools.trainlog.data.TrainlogRepository import com.labfytools.trainlog.data.TrainlogRepository
import com.labfytools.trainlog.model.BodyObservationDraft import com.labfytools.trainlog.model.BodyObservationDraft
import com.labfytools.trainlog.ui.theme.LocalTrainlogColors import com.labfytools.trainlog.ui.theme.LocalTrainlogColors
import com.labfytools.trainlog.ui.theme.TrainlogTypography
@Composable @Composable
fun BodyScreen( fun BodyScreen(
@ -503,67 +496,19 @@ private fun BodyMetricField(
value: String, value: String,
onValueChange: (String) -> Unit, onValueChange: (String) -> Unit,
) { ) {
val colors = TrainlogInputField(
LocalTrainlogColors.current label = "$label ($unit)",
value = value,
Column( onValueChange =
modifier = onValueChange,
Modifier.padding( keyboardOptions =
bottom = 11.dp KeyboardOptions(
) keyboardType =
) { KeyboardType.Decimal,
BasicText( imeAction =
text = ImeAction.Next,
"$label ($unit)" ),
.uppercase(), )
modifier =
Modifier.padding(
bottom = 5.dp
),
style =
TrainlogTypography.small
.copy(
color =
colors.muted,
),
)
BasicTextField(
value = value,
onValueChange =
onValueChange,
singleLine = true,
keyboardOptions =
KeyboardOptions(
keyboardType =
KeyboardType.Decimal,
imeAction =
ImeAction.Next,
),
cursorBrush =
SolidColor(
colors.accent
),
textStyle =
TrainlogTypography.normal
.copy(
color =
colors.text,
),
modifier =
Modifier
.fillMaxWidth()
.border(
width = 1.dp,
color =
colors.surfaceAlt,
)
.background(
colors.surface
)
.padding(12.dp),
)
}
} }
private sealed interface MetricParse { private sealed interface MetricParse {

View file

@ -1,21 +1,19 @@
package com.labfytools.trainlog.ui package com.labfytools.trainlog.ui
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.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.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.labfytools.trainlog.data.CreateExerciseResult import com.labfytools.trainlog.data.CreateExerciseResult
import com.labfytools.trainlog.data.TrainlogRepository import com.labfytools.trainlog.data.TrainlogRepository
@ -315,54 +313,12 @@ private fun TrainlogField(
value: String, value: String,
onValueChange: (String) -> Unit, onValueChange: (String) -> Unit,
) { ) {
val colors = TrainlogInputField(
LocalTrainlogColors.current label = label,
value = value,
Column( onValueChange =
modifier = onValueChange,
Modifier.padding( )
bottom = 14.dp
)
) {
BasicText(
text = label.uppercase(),
modifier =
Modifier.padding(
bottom = 6.dp
),
style =
TrainlogTypography.small.copy(
color = colors.muted,
),
)
BasicTextField(
value = value,
onValueChange = onValueChange,
singleLine = true,
cursorBrush =
SolidColor(
colors.accent
),
textStyle =
TrainlogTypography.normal
.copy(
color = colors.text
),
modifier =
Modifier
.fillMaxWidth()
.border(
width = 1.dp,
color =
colors.surfaceAlt,
)
.background(
colors.surface
)
.padding(12.dp),
)
}
} }
@Composable @Composable
@ -408,18 +364,7 @@ private fun TrainlogChoice(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(vertical = 2.dp)
vertical = 3.dp
)
.border(
width = 1.dp,
color =
if (selected) {
colors.warning
} else {
colors.surfaceAlt
},
)
.background( .background(
if (selected) { if (selected) {
colors.surfaceAlt colors.surfaceAlt
@ -427,17 +372,18 @@ private fun TrainlogChoice(
colors.surface colors.surface
} }
) )
.clickable( .clickable(onClick = onClick)
onClick = onClick .padding(
horizontal = 10.dp,
vertical = 9.dp,
) )
.padding(11.dp)
) { ) {
BasicText( BasicText(
text = text =
if (selected) { if (selected) {
"[X] $label" " $label"
} else { } else {
"[ ] $label" " $label"
}, },
style = style =
TrainlogTypography.normal.copy( TrainlogTypography.normal.copy(
@ -447,11 +393,18 @@ private fun TrainlogChoice(
} else { } else {
colors.text colors.text
}, },
fontWeight =
if (selected) {
FontWeight.Bold
} else {
FontWeight.Normal
},
), ),
) )
} }
} }
private fun profilePreview( private fun profilePreview(
recordingMode: RecordingMode, recordingMode: RecordingMode,
trackingMode: TrackingMode, trackingMode: TrackingMode,

View file

@ -7,14 +7,12 @@ package com.labfytools.trainlog.ui
/* TRAINLOG_VARIABLE_SET_REPS_V1 */ /* TRAINLOG_VARIABLE_SET_REPS_V1 */
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.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.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
@ -22,7 +20,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.labfytools.trainlog.data.SaveSessionResult import com.labfytools.trainlog.data.SaveSessionResult
import com.labfytools.trainlog.data.TrainlogRepository import com.labfytools.trainlog.data.TrainlogRepository
@ -425,23 +423,7 @@ private fun CatalogChoice(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(vertical = 2.dp)
vertical = 3.dp
)
.border(
width = 1.dp,
color =
when {
selected ->
colors.warning
disabled ->
colors.muted
else ->
colors.surfaceAlt
},
)
.background( .background(
if (selected) { if (selected) {
colors.surfaceAlt colors.surfaceAlt
@ -450,40 +432,45 @@ private fun CatalogChoice(
} }
) )
.clickable( .clickable(
enabled = enabled = !disabled,
!disabled, onClick = onClick,
onClick = )
onClick, .padding(
horizontal = 10.dp,
vertical = 9.dp,
) )
.padding(11.dp)
) { ) {
BasicText( BasicText(
text = text =
( (
if (disabled) { if (disabled) {
"[] " ""
} else if (selected) { } else if (selected) {
"[>] " " "
} else { } else {
"[ ] " " "
} }
) + ) +
exercise.name + exercise.name +
" [$profile]", " · " +
profile,
style = style =
TrainlogTypography.normal TrainlogTypography.normal.copy(
.copy( color =
color = if (disabled) {
if (disabled) { colors.muted
colors.muted } else if (selected) {
} else if ( colors.warning
selected } else {
) { colors.text
colors.warning },
} else { fontWeight =
colors.text if (selected) {
}, FontWeight.Bold
), } else {
FontWeight.Normal
},
),
) )
} }
} }
@ -701,59 +688,12 @@ private fun SessionNumberField(
value: String, value: String,
onValueChange: (String) -> Unit, onValueChange: (String) -> Unit,
) { ) {
val colors = TrainlogInputField(
LocalTrainlogColors.current label = label,
value = value,
Column( onValueChange =
modifier = onValueChange,
Modifier.padding( )
bottom = 12.dp
)
) {
BasicText(
text =
label.uppercase(),
modifier =
Modifier.padding(
bottom = 5.dp
),
style =
TrainlogTypography.small
.copy(
color =
colors.muted,
),
)
BasicTextField(
value = value,
onValueChange =
onValueChange,
singleLine = true,
cursorBrush =
SolidColor(
colors.accent
),
textStyle =
TrainlogTypography.normal
.copy(
color =
colors.text,
),
modifier =
Modifier
.fillMaxWidth()
.border(
width = 1.dp,
color =
colors.surfaceAlt,
)
.background(
colors.surface
)
.padding(12.dp),
)
}
} }
private const val MAX_SESSION_SETS = 64 private const val MAX_SESSION_SETS = 64

View file

@ -6,20 +6,32 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.focus.onFocusChanged
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@ -46,9 +58,7 @@ fun TrainlogScreen(
Column( Column(
modifier = modifier =
Modifier Modifier
.background( .background(colors.background)
colors.background
)
.statusBarsPadding() .statusBarsPadding()
.navigationBarsPadding() .navigationBarsPadding()
.imePadding() .imePadding()
@ -58,7 +68,7 @@ fun TrainlogScreen(
.padding( .padding(
PaddingValues( PaddingValues(
horizontal = 16.dp, horizontal = 16.dp,
vertical = 14.dp, vertical = 12.dp,
) )
), ),
) { ) {
@ -81,9 +91,7 @@ private fun TrainlogBanner(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(bottom = 18.dp)
bottom = 22.dp
)
) { ) {
val wide = val wide =
maxWidth >= 560.dp maxWidth >= 560.dp
@ -107,9 +115,9 @@ private fun TrainlogBanner(
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = fontSize =
if (wide) { if (wide) {
15.sp 14.sp
} else { } else {
22.sp 21.sp
}, },
), ),
) )
@ -117,9 +125,7 @@ private fun TrainlogBanner(
BasicText( BasicText(
text = subtitle, text = subtitle,
modifier = modifier =
Modifier.padding( Modifier.padding(top = 5.dp),
top = 6.dp
),
style = style =
TrainlogTypography.small.copy( TrainlogTypography.small.copy(
color = colors.muted, color = colors.muted,
@ -152,9 +158,7 @@ fun TrainlogFrame(
modifier = modifier =
modifier modifier
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(bottom = 16.dp)
bottom = 20.dp
)
) { ) {
BasicText( BasicText(
text = title.uppercase(), text = title.uppercase(),
@ -171,8 +175,8 @@ fun TrainlogFrame(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(
top = 7.dp, top = 6.dp,
bottom = 10.dp, bottom = 8.dp,
) )
.height(1.dp) .height(1.dp)
.background(accent) .background(accent)
@ -196,25 +200,30 @@ fun TrainlogAction(
val actualAccent = val actualAccent =
accent ?: colors.accent accent ?: colors.accent
Box( Row(
modifier = modifier =
modifier modifier
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(vertical = 3.dp)
vertical = 4.dp .height(IntrinsicSize.Min)
) .background(colors.surface)
.background( .clickable(onClick = onClick)
colors.surface
)
.clickable(
onClick = onClick
)
.padding(
horizontal = 14.dp,
vertical = 12.dp,
)
) { ) {
Column { Box(
modifier =
Modifier
.width(3.dp)
.fillMaxHeight()
.background(actualAccent)
)
Column(
modifier =
Modifier.padding(
horizontal = 12.dp,
vertical = 10.dp,
)
) {
BasicText( BasicText(
text = label, text = label,
style = style =
@ -229,9 +238,7 @@ fun TrainlogAction(
BasicText( BasicText(
text = description, text = description,
modifier = modifier =
Modifier.padding( Modifier.padding(top = 2.dp),
top = 3.dp
),
style = style =
TrainlogTypography.small.copy( TrainlogTypography.small.copy(
color = colors.text, color = colors.text,
@ -242,6 +249,93 @@ fun TrainlogAction(
} }
} }
@Composable
fun TrainlogInputField(
label: String,
value: String,
onValueChange: (String) -> Unit,
keyboardOptions: KeyboardOptions =
KeyboardOptions.Default,
) {
val colors =
LocalTrainlogColors.current
var focused by
remember {
mutableStateOf(false)
}
Column(
modifier =
Modifier.padding(bottom = 10.dp)
) {
BasicText(
text = label.uppercase(),
modifier =
Modifier.padding(bottom = 4.dp),
style =
TrainlogTypography.small.copy(
color =
if (focused) {
colors.accent
} else {
colors.muted
},
fontWeight =
if (focused) {
FontWeight.Bold
} else {
FontWeight.Normal
},
),
)
BasicTextField(
value = value,
onValueChange = onValueChange,
singleLine = true,
keyboardOptions = keyboardOptions,
cursorBrush =
SolidColor(colors.accent),
textStyle =
TrainlogTypography.normal.copy(
color = colors.text,
),
modifier =
Modifier
.fillMaxWidth()
.onFocusChanged {
focused = it.isFocused
}
.background(colors.surface)
.padding(
horizontal = 12.dp,
vertical = 10.dp,
),
)
Box(
modifier =
Modifier
.fillMaxWidth()
.height(
if (focused) {
2.dp
} else {
1.dp
}
)
.background(
if (focused) {
colors.accent
} else {
colors.surfaceAlt
}
)
)
}
}
@Composable @Composable
fun TrainlogInfo( fun TrainlogInfo(
text: String, text: String,
@ -253,9 +347,7 @@ fun TrainlogInfo(
BasicText( BasicText(
text = text, text = text,
modifier = modifier =
Modifier.padding( Modifier.padding(vertical = 3.dp),
vertical = 3.dp
),
style = style =
TrainlogTypography.normal.copy( TrainlogTypography.normal.copy(
color = color =

View file

@ -44,25 +44,25 @@ object TrainlogTypography {
val normal = val normal =
TextStyle( TextStyle(
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
fontSize = 16.sp, fontSize = 15.sp,
) )
val small = val small =
TextStyle( TextStyle(
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
fontSize = 13.sp, fontSize = 12.sp,
) )
val title = val title =
TextStyle( TextStyle(
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
fontSize = 20.sp, fontSize = 19.sp,
) )
val banner = val banner =
TextStyle( TextStyle(
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
fontSize = 24.sp, fontSize = 22.sp,
) )
} }