From 998a16ab4e35b05dcbe9b929d25841b19692bcde Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sat, 5 Jul 2025 09:03:21 +0530 Subject: [PATCH] Add a basic UI in settings for customizing timers The UI is non-functional for now, functionality will be added in further commits --- .../java/org/nsh07/pomodoro/ui/AppScreen.kt | 11 +- .../ui/settingsScreen/SettingsScreen.kt | 187 +++++++++++++++++- .../pomodoro/ui/viewModel/UiViewModel.kt | 12 +- 3 files changed, 194 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt index ddfe1f7..8a20365 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt @@ -149,7 +149,16 @@ fun AppScreen( } entry { - 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 { diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt index 310159e..fb57b9c 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt @@ -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) + ) + } + } } } } -} \ No newline at end of file +} + +@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() + ) + } +} diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/viewModel/UiViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/viewModel/UiViewModel.kt index 264d766..075c072 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/viewModel/UiViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/viewModel/UiViewModel.kt @@ -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) } \ No newline at end of file