Add a basic UI in settings for customizing timers

The UI is non-functional for now, functionality will be added in further commits
This commit is contained in:
Nishant Mishra
2025-07-05 09:03:21 +05:30
parent fb499a9cc2
commit 998a16ab4e
3 changed files with 194 additions and 16 deletions

View File

@@ -149,7 +149,16 @@ fun AppScreen(
}
entry<Screen.Settings> {
SettingsScreen()
SettingsScreen(
25 * 60 * 1000,
5 * 60 * 1000,
15 * 60 * 1000,
modifier = modifier.padding(
start = contentPadding.calculateStartPadding(layoutDirection),
end = contentPadding.calculateEndPadding(layoutDirection),
bottom = contentPadding.calculateBottomPadding()
)
)
}
entry<Screen.Stats> {

View File

@@ -1,27 +1,55 @@
package org.nsh07.pomodoro.ui.settingsScreen
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.nsh07.pomodoro.ui.theme.AppFonts.openRundeClock
import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTitle
import org.nsh07.pomodoro.ui.theme.TomatoTheme
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun SettingsScreen(modifier: Modifier = Modifier) {
Column(modifier) {
fun SettingsScreen(
focusTime: Int,
shortBreakTime: Int,
longBreakTime: Int,
modifier: Modifier = Modifier
) {
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Column(modifier.nestedScroll(scrollBehavior.nestedScrollConnection)) {
TopAppBar(
title = {
Text(
@@ -34,13 +62,154 @@ fun SettingsScreen(modifier: Modifier = Modifier) {
)
},
subtitle = {},
titleHorizontalAlignment = Alignment.CenterHorizontally
titleHorizontalAlignment = Alignment.CenterHorizontally,
scrollBehavior = scrollBehavior
)
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().background(colorScheme.surface)) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
LoadingIndicator()
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
item {
Text(
"Durations",
style = typography.titleSmall,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(rememberScrollState())
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.clip(
RoundedCornerShape(
topStart = 16.dp,
bottomStart = 16.dp,
topEnd = 4.dp,
bottomEnd = 4.dp
)
)
.size(112.dp, 100.dp)
.background(colorScheme.surfaceContainer)
) {
Text(
text = remember(focusTime) { (focusTime / 60000).toString() },
style = TextStyle(
fontFamily = openRundeClock,
fontWeight = FontWeight.Bold,
fontSize = 57.sp,
letterSpacing = (-2).sp
),
textAlign = TextAlign.Center,
maxLines = 1,
color = colorScheme.onSurfaceVariant
)
}
Text(
"Focus",
style = typography.titleSmallEmphasized,
color = colorScheme.onPrimaryContainer,
modifier = Modifier.padding(horizontal = 8.dp)
)
}
Spacer(Modifier.width(2.dp))
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.clip(RoundedCornerShape(4.dp))
.size(112.dp, 100.dp)
.background(colorScheme.surfaceContainer)
) {
Text(
text = remember(shortBreakTime) {
(shortBreakTime / 60000).toString().padStart(2, '0')
},
style = TextStyle(
fontFamily = openRundeClock,
fontWeight = FontWeight.Bold,
fontSize = 57.sp,
letterSpacing = (-2).sp
),
textAlign = TextAlign.Center,
maxLines = 1,
color = colorScheme.onSurfaceVariant
)
}
Text(
"Short break",
style = typography.titleSmallEmphasized,
color = colorScheme.onTertiaryContainer,
modifier = Modifier.padding(horizontal = 8.dp)
)
}
Spacer(Modifier.width(2.dp))
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.clip(
RoundedCornerShape(
topStart = 4.dp,
bottomStart = 4.dp,
topEnd = 16.dp,
bottomEnd = 16.dp
)
)
.size(112.dp, 100.dp)
.background(colorScheme.surfaceContainer)
) {
Text(
text = remember(shortBreakTime) {
(longBreakTime / 60000).toString().padStart(2, '0')
},
style = TextStyle(
fontFamily = openRundeClock,
fontWeight = FontWeight.Bold,
fontSize = 57.sp,
letterSpacing = (-2).sp
),
textAlign = TextAlign.Center,
maxLines = 1,
color = colorScheme.onSurfaceVariant
)
}
Text(
"Long break",
style = typography.titleSmallEmphasized,
color = colorScheme.onTertiaryContainer,
modifier = Modifier.padding(horizontal = 8.dp)
)
}
}
}
}
}
}
}
@Preview(
showSystemUi = true,
device = Devices.PIXEL_9_PRO
)
@Composable
fun SettingsScreenPreview() {
TomatoTheme {
SettingsScreen(
focusTime = 88 * 60 * 1000,
shortBreakTime = 88 * 60 * 1000,
longBreakTime = 88 * 60 * 1000,
modifier = Modifier.fillMaxSize()
)
}
}

View File

@@ -197,12 +197,6 @@ class UiViewModel(
}
}
private fun millisecondsToStr(t: Int): String {
val min = (ceil(t / 1000.0).toInt() / 60)
val sec = (ceil(t / 1000.0).toInt() % 60)
return String.format(locale = Locale.getDefault(), "%02d:%02d", min, sec)
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
initializer {
@@ -212,4 +206,10 @@ class UiViewModel(
}
}
}
}
fun millisecondsToStr(t: Int): String {
val min = (ceil(t / 1000.0).toInt() / 60)
val sec = (ceil(t / 1000.0).toInt() % 60)
return String.format(locale = Locale.getDefault(), "%02d:%02d", min, sec)
}