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:
@@ -149,7 +149,16 @@ fun AppScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry<Screen.Settings> {
|
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> {
|
entry<Screen.Stats> {
|
||||||
|
|||||||
@@ -1,27 +1,55 @@
|
|||||||
package org.nsh07.pomodoro.ui.settingsScreen
|
package org.nsh07.pomodoro.ui.settingsScreen
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
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.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
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.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.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.LoadingIndicator
|
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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 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.AppFonts.robotoFlexTitle
|
||||||
|
import org.nsh07.pomodoro.ui.theme.TomatoTheme
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(modifier: Modifier = Modifier) {
|
fun SettingsScreen(
|
||||||
Column(modifier) {
|
focusTime: Int,
|
||||||
|
shortBreakTime: Int,
|
||||||
|
longBreakTime: Int,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
|
Column(modifier.nestedScroll(scrollBehavior.nestedScrollConnection)) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
@@ -34,13 +62,154 @@ fun SettingsScreen(modifier: Modifier = Modifier) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
subtitle = {},
|
subtitle = {},
|
||||||
titleHorizontalAlignment = Alignment.CenterHorizontally
|
titleHorizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
)
|
)
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().background(colorScheme.surface)) {
|
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
LazyColumn(
|
||||||
LoadingIndicator()
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)
|
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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 {
|
companion object {
|
||||||
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
initializer {
|
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)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user