From 83a88d98a38f3f7a14af9855c287fbab3fefd92f Mon Sep 17 00:00:00 2001 From: fy59 Date: Sun, 6 Sep 2026 21:40:00 +0200 Subject: [PATCH] Polish flat Android interface --- .../com/labfytools/trainlog/ui/BodyScreen.kt | 81 ++------- .../labfytools/trainlog/ui/ExerciseScreen.kt | 89 +++------- .../labfytools/trainlog/ui/SessionScreen.kt | 130 ++++---------- .../trainlog/ui/TrainlogComponents.kt | 168 ++++++++++++++---- .../trainlog/ui/theme/TrainlogTheme.kt | 8 +- 5 files changed, 203 insertions(+), 273 deletions(-) diff --git a/android/app/src/main/java/com/labfytools/trainlog/ui/BodyScreen.kt b/android/app/src/main/java/com/labfytools/trainlog/ui/BodyScreen.kt index 15c1705..e0ef8a2 100644 --- a/android/app/src/main/java/com/labfytools/trainlog/ui/BodyScreen.kt +++ b/android/app/src/main/java/com/labfytools/trainlog/ui/BodyScreen.kt @@ -1,12 +1,8 @@ package com.labfytools.trainlog.ui 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.padding -import androidx.compose.foundation.text.BasicText -import androidx.compose.foundation.text.BasicTextField import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue 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.KeyboardType 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.TrainlogRepository import com.labfytools.trainlog.model.BodyObservationDraft import com.labfytools.trainlog.ui.theme.LocalTrainlogColors -import com.labfytools.trainlog.ui.theme.TrainlogTypography @Composable fun BodyScreen( @@ -503,67 +496,19 @@ private fun BodyMetricField( value: String, onValueChange: (String) -> Unit, ) { - val colors = - LocalTrainlogColors.current - - Column( - modifier = - Modifier.padding( - bottom = 11.dp - ) - ) { - BasicText( - text = - "$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), - ) - } + TrainlogInputField( + label = "$label ($unit)", + value = value, + onValueChange = + onValueChange, + keyboardOptions = + KeyboardOptions( + keyboardType = + KeyboardType.Decimal, + imeAction = + ImeAction.Next, + ), + ) } private sealed interface MetricParse { diff --git a/android/app/src/main/java/com/labfytools/trainlog/ui/ExerciseScreen.kt b/android/app/src/main/java/com/labfytools/trainlog/ui/ExerciseScreen.kt index da6d63a..4c93d6b 100644 --- a/android/app/src/main/java/com/labfytools/trainlog/ui/ExerciseScreen.kt +++ b/android/app/src/main/java/com/labfytools/trainlog/ui/ExerciseScreen.kt @@ -1,21 +1,19 @@ package com.labfytools.trainlog.ui import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth 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.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue 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 com.labfytools.trainlog.data.CreateExerciseResult import com.labfytools.trainlog.data.TrainlogRepository @@ -315,54 +313,12 @@ private fun TrainlogField( value: String, onValueChange: (String) -> Unit, ) { - val colors = - LocalTrainlogColors.current - - Column( - modifier = - 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), - ) - } + TrainlogInputField( + label = label, + value = value, + onValueChange = + onValueChange, + ) } @Composable @@ -408,18 +364,7 @@ private fun TrainlogChoice( modifier = Modifier .fillMaxWidth() - .padding( - vertical = 3.dp - ) - .border( - width = 1.dp, - color = - if (selected) { - colors.warning - } else { - colors.surfaceAlt - }, - ) + .padding(vertical = 2.dp) .background( if (selected) { colors.surfaceAlt @@ -427,17 +372,18 @@ private fun TrainlogChoice( colors.surface } ) - .clickable( - onClick = onClick + .clickable(onClick = onClick) + .padding( + horizontal = 10.dp, + vertical = 9.dp, ) - .padding(11.dp) ) { BasicText( text = if (selected) { - "[X] $label" + "▌ $label" } else { - "[ ] $label" + " $label" }, style = TrainlogTypography.normal.copy( @@ -447,11 +393,18 @@ private fun TrainlogChoice( } else { colors.text }, + fontWeight = + if (selected) { + FontWeight.Bold + } else { + FontWeight.Normal + }, ), ) } } + private fun profilePreview( recordingMode: RecordingMode, trackingMode: TrackingMode, diff --git a/android/app/src/main/java/com/labfytools/trainlog/ui/SessionScreen.kt b/android/app/src/main/java/com/labfytools/trainlog/ui/SessionScreen.kt index d008c3d..fb8eea6 100644 --- a/android/app/src/main/java/com/labfytools/trainlog/ui/SessionScreen.kt +++ b/android/app/src/main/java/com/labfytools/trainlog/ui/SessionScreen.kt @@ -7,14 +7,12 @@ package com.labfytools.trainlog.ui /* TRAINLOG_VARIABLE_SET_REPS_V1 */ import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth 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.getValue import androidx.compose.runtime.mutableIntStateOf @@ -22,7 +20,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue 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 com.labfytools.trainlog.data.SaveSessionResult import com.labfytools.trainlog.data.TrainlogRepository @@ -425,23 +423,7 @@ private fun CatalogChoice( modifier = Modifier .fillMaxWidth() - .padding( - vertical = 3.dp - ) - .border( - width = 1.dp, - color = - when { - selected -> - colors.warning - - disabled -> - colors.muted - - else -> - colors.surfaceAlt - }, - ) + .padding(vertical = 2.dp) .background( if (selected) { colors.surfaceAlt @@ -450,40 +432,45 @@ private fun CatalogChoice( } ) .clickable( - enabled = - !disabled, - onClick = - onClick, + enabled = !disabled, + onClick = onClick, + ) + .padding( + horizontal = 10.dp, + vertical = 9.dp, ) - .padding(11.dp) ) { BasicText( text = ( if (disabled) { - "[✓] " + "✓ " } else if (selected) { - "[>] " + "▌ " } else { - "[ ] " + " " } ) + exercise.name + - " [$profile]", + " · " + + profile, style = - TrainlogTypography.normal - .copy( - color = - if (disabled) { - colors.muted - } else if ( - selected - ) { - colors.warning - } else { - colors.text - }, - ), + TrainlogTypography.normal.copy( + color = + if (disabled) { + colors.muted + } else if (selected) { + colors.warning + } else { + colors.text + }, + fontWeight = + if (selected) { + FontWeight.Bold + } else { + FontWeight.Normal + }, + ), ) } } @@ -701,59 +688,12 @@ private fun SessionNumberField( value: String, onValueChange: (String) -> Unit, ) { - val colors = - LocalTrainlogColors.current - - Column( - modifier = - 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), - ) - } + TrainlogInputField( + label = label, + value = value, + onValueChange = + onValueChange, + ) } private const val MAX_SESSION_SETS = 64 diff --git a/android/app/src/main/java/com/labfytools/trainlog/ui/TrainlogComponents.kt b/android/app/src/main/java/com/labfytools/trainlog/ui/TrainlogComponents.kt index 9c4891f..cc0782a 100644 --- a/android/app/src/main/java/com/labfytools/trainlog/ui/TrainlogComponents.kt +++ b/android/app/src/main/java/com/labfytools/trainlog/ui/TrainlogComponents.kt @@ -6,20 +6,32 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.IntrinsicSize 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.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState 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.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.Modifier +import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -46,9 +58,7 @@ fun TrainlogScreen( Column( modifier = Modifier - .background( - colors.background - ) + .background(colors.background) .statusBarsPadding() .navigationBarsPadding() .imePadding() @@ -58,7 +68,7 @@ fun TrainlogScreen( .padding( PaddingValues( horizontal = 16.dp, - vertical = 14.dp, + vertical = 12.dp, ) ), ) { @@ -81,9 +91,7 @@ private fun TrainlogBanner( modifier = Modifier .fillMaxWidth() - .padding( - bottom = 22.dp - ) + .padding(bottom = 18.dp) ) { val wide = maxWidth >= 560.dp @@ -107,9 +115,9 @@ private fun TrainlogBanner( fontWeight = FontWeight.Bold, fontSize = if (wide) { - 15.sp + 14.sp } else { - 22.sp + 21.sp }, ), ) @@ -117,9 +125,7 @@ private fun TrainlogBanner( BasicText( text = subtitle, modifier = - Modifier.padding( - top = 6.dp - ), + Modifier.padding(top = 5.dp), style = TrainlogTypography.small.copy( color = colors.muted, @@ -152,9 +158,7 @@ fun TrainlogFrame( modifier = modifier .fillMaxWidth() - .padding( - bottom = 20.dp - ) + .padding(bottom = 16.dp) ) { BasicText( text = title.uppercase(), @@ -171,8 +175,8 @@ fun TrainlogFrame( Modifier .fillMaxWidth() .padding( - top = 7.dp, - bottom = 10.dp, + top = 6.dp, + bottom = 8.dp, ) .height(1.dp) .background(accent) @@ -196,25 +200,30 @@ fun TrainlogAction( val actualAccent = accent ?: colors.accent - Box( + Row( modifier = modifier .fillMaxWidth() - .padding( - vertical = 4.dp - ) - .background( - colors.surface - ) - .clickable( - onClick = onClick - ) - .padding( - horizontal = 14.dp, - vertical = 12.dp, - ) + .padding(vertical = 3.dp) + .height(IntrinsicSize.Min) + .background(colors.surface) + .clickable(onClick = onClick) ) { - Column { + Box( + modifier = + Modifier + .width(3.dp) + .fillMaxHeight() + .background(actualAccent) + ) + + Column( + modifier = + Modifier.padding( + horizontal = 12.dp, + vertical = 10.dp, + ) + ) { BasicText( text = label, style = @@ -229,9 +238,7 @@ fun TrainlogAction( BasicText( text = description, modifier = - Modifier.padding( - top = 3.dp - ), + Modifier.padding(top = 2.dp), style = TrainlogTypography.small.copy( 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 fun TrainlogInfo( text: String, @@ -253,9 +347,7 @@ fun TrainlogInfo( BasicText( text = text, modifier = - Modifier.padding( - vertical = 3.dp - ), + Modifier.padding(vertical = 3.dp), style = TrainlogTypography.normal.copy( color = diff --git a/android/app/src/main/java/com/labfytools/trainlog/ui/theme/TrainlogTheme.kt b/android/app/src/main/java/com/labfytools/trainlog/ui/theme/TrainlogTheme.kt index 3061704..cfe604c 100644 --- a/android/app/src/main/java/com/labfytools/trainlog/ui/theme/TrainlogTheme.kt +++ b/android/app/src/main/java/com/labfytools/trainlog/ui/theme/TrainlogTheme.kt @@ -44,25 +44,25 @@ object TrainlogTypography { val normal = TextStyle( fontFamily = FontFamily.Monospace, - fontSize = 16.sp, + fontSize = 15.sp, ) val small = TextStyle( fontFamily = FontFamily.Monospace, - fontSize = 13.sp, + fontSize = 12.sp, ) val title = TextStyle( fontFamily = FontFamily.Monospace, - fontSize = 20.sp, + fontSize = 19.sp, ) val banner = TextStyle( fontFamily = FontFamily.Monospace, - fontSize = 24.sp, + fontSize = 22.sp, ) }