LazyColumn not fixed

This commit is contained in:
Rune Dyselinck 2023-04-27 17:01:39 +02:00
parent 601740f258
commit 2ca112ee0e
6 changed files with 303 additions and 28 deletions

View file

@ -34,6 +34,7 @@ import be.ugent.sel.studeez.screens.session.SessionRoute
import be.ugent.sel.studeez.screens.sign_up.SignUpRoute import be.ugent.sel.studeez.screens.sign_up.SignUpRoute
import be.ugent.sel.studeez.screens.splash.SplashRoute import be.ugent.sel.studeez.screens.splash.SplashRoute
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
import be.ugent.sel.studeez.screens.timer_overview.add_timer.AddTimerRoute
import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute
import be.ugent.sel.studeez.ui.theme.StudeezTheme import be.ugent.sel.studeez.ui.theme.StudeezTheme
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -167,5 +168,14 @@ fun StudeezNavGraph(
navBarViewModel = navBarViewModel, navBarViewModel = navBarViewModel,
) )
} }
composable(StudeezDestinations.ADD_TIMER_SCREEN) {
AddTimerRoute(
open = open,
openAndPopUp = openAndPopUp,
goBack = goBack,
viewModel = hiltViewModel()
)
}
} }
} }

View file

@ -23,7 +23,14 @@ import be.ugent.sel.studeez.common.ext.card
@Composable @Composable
fun BasicTextButton(@StringRes text: Int, modifier: Modifier, action: () -> Unit) { fun BasicTextButton(@StringRes text: Int, modifier: Modifier, action: () -> Unit) {
TextButton(onClick = action, modifier = modifier) { Text(text = stringResource(text)) } TextButton(
onClick = action,
modifier = modifier
) {
Text(
text = stringResource(text)
)
}
} }
@Composable @Composable

View file

@ -23,6 +23,7 @@ import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.resources import be.ugent.sel.studeez.resources
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
@ -31,15 +32,18 @@ data class TimerOverviewActions(
val getUserTimers: () -> Flow<List<TimerInfo>>, val getUserTimers: () -> Flow<List<TimerInfo>>,
val getDefaultTimers: () -> List<TimerInfo>, val getDefaultTimers: () -> List<TimerInfo>,
val onEditClick: (TimerInfo) -> Unit, val onEditClick: (TimerInfo) -> Unit,
val open: (String) -> Unit,
) )
fun getTimerOverviewActions( fun getTimerOverviewActions(
viewModel: TimerOverviewViewModel, viewModel: TimerOverviewViewModel,
open: (String) -> Unit,
): TimerOverviewActions { ): TimerOverviewActions {
return TimerOverviewActions( return TimerOverviewActions(
getUserTimers = viewModel::getUserTimers, getUserTimers = viewModel::getUserTimers,
getDefaultTimers = viewModel::getDefaultTimers, getDefaultTimers = viewModel::getDefaultTimers,
onEditClick = { viewModel.update(it) }, onEditClick = { viewModel.update(it) },
open = open
) )
} }
@ -52,7 +56,7 @@ fun TimerOverviewRoute(
navBarViewModel: NavigationBarViewModel, navBarViewModel: NavigationBarViewModel,
) { ) {
TimerOverviewScreen( TimerOverviewScreen(
timerOverviewActions = getTimerOverviewActions(viewModel), timerOverviewActions = getTimerOverviewActions(viewModel, open),
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp), drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
navigationBarActions = getNavigationBarActions(navBarViewModel, open), navigationBarActions = getNavigationBarActions(navBarViewModel, open),
) )
@ -95,7 +99,7 @@ fun TimerOverviewScreen(
} }
} }
BasicButton(R.string.add_timer, Modifier.basicButton()) { BasicButton(R.string.add_timer, Modifier.basicButton()) {
// TODO timerOverviewActions.open(StudeezDestinations.ADD_TIMER_SCREEN)
} }
} }
} }
@ -111,7 +115,9 @@ fun TimerOverviewPreview() {
timerOverviewActions = TimerOverviewActions( timerOverviewActions = TimerOverviewActions(
{ flowOf() }, { flowOf() },
{ listOf(customTimer, customTimer) }, { listOf(customTimer, customTimer) },
{}), {},
{}
),
drawerActions = DrawerActions({}, {}, {}, {}, {}), drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({}, {}, {}, {}) navigationBarActions = NavigationBarActions({}, {}, {}, {})
) )

View file

@ -0,0 +1,11 @@
package be.ugent.sel.studeez.screens.timer_overview.add_timer
data class AddTimerUiState(
val studyTimeHours: Float = 1f,
val studyTimeMinutes: Float = 0f,
val withBreaks: Boolean = false,
val breakTime: Float = 5f,
val repeats: Float = 1f,
val name: String = "",
val description: String = "",
)

View file

@ -1,13 +1,85 @@
package be.ugent.sel.studeez.screens.timer_overview.add_timer package be.ugent.sel.studeez.screens.timer_overview.add_timer
import androidx.compose.runtime.mutableStateOf
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.PomodoroTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
import be.ugent.sel.studeez.screens.StudeezViewModel import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class AddTimerViewModel @Inject constructor( class AddTimerViewModel @Inject constructor(
logService: LogService logService: LogService,
private val timerDAO: TimerDAO,
): StudeezViewModel(logService) { ): StudeezViewModel(logService) {
var uiState = mutableStateOf(AddTimerUiState())
private set
private val studyTimeHours
get() = uiState.value.studyTimeHours
private val studyTimeMinutes
get() = uiState.value.studyTimeMinutes
private val breakTime
get() = uiState.value.breakTime
private val repeats
get() = uiState.value.repeats
private val name
get() = uiState.value.name
private val description
get() = uiState.value.description
fun onStudyTimeHoursChange(newValue: Float) {
uiState.value = uiState.value.copy(studyTimeHours = newValue)
}
fun onStudyTimeMinutesChange(newValue: Float) {
uiState.value = uiState.value.copy(studyTimeMinutes = newValue)
}
fun onWithBreaksChange(newValue: Boolean) {
uiState.value = uiState.value.copy(withBreaks = newValue)
}
fun onBreakTimeChange(newValue: Float) {
uiState.value = uiState.value.copy(breakTime = newValue)
}
fun onRepeatsChange(newValue: Float) {
uiState.value = uiState.value.copy(repeats = newValue)
}
fun addTimer() {
if (uiState.value.withBreaks) {
timerDAO.saveTimer(PomodoroTimerInfo(
name = uiState.value.name,
description = uiState.value.description,
studyTime = studyTimeHours.toInt() * 60 * 60 + studyTimeMinutes.toInt() * 60,
breakTime = breakTime.toInt() * 60,
repeats = repeats.toInt()
))
} else {
timerDAO.saveTimer(CustomTimerInfo(
name = uiState.value.name,
description = uiState.value.description,
studyTime = studyTimeHours.toInt() * 60 * 60 + studyTimeMinutes.toInt() * 60
))
}
}
fun onNameChange(newValue: String) {
uiState.value = uiState.value.copy(name = newValue)
}
fun onDescriptionChange(newValue: String) {
uiState.value = uiState.value.copy(description = newValue)
}
} }

View file

@ -1,42 +1,211 @@
package be.ugent.sel.studeez.screens.timer_overview.add_timer package be.ugent.sel.studeez.screens.timer_overview.add_timer
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Checkbox
import androidx.compose.material.Slider
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.BasicButton
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel
import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions data class AddTimerActions(
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions val goBack: () -> Unit,
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel val onStudyTimeHoursChange: (Float) -> Unit,
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions val onStudyTimeMinutesChange: (Float) -> Unit,
val onBreakTimeChange: (Float) -> Unit,
val onRepeatsChange: (Float) -> Unit,
val onWithBreaksChange: (Boolean) -> Unit,
val addTimer: () -> Unit,
val onNameChange: (String) -> Unit,
val onDescriptionChange: (String) -> Unit,
)
fun getAddTimerActions(
goBack: () -> Unit,
viewModel: AddTimerViewModel,
): AddTimerActions {
return AddTimerActions(
goBack = goBack,
onWithBreaksChange = viewModel::onWithBreaksChange,
onStudyTimeHoursChange = viewModel::onStudyTimeHoursChange,
onStudyTimeMinutesChange = viewModel::onStudyTimeMinutesChange,
onBreakTimeChange = viewModel::onBreakTimeChange,
onRepeatsChange = viewModel::onRepeatsChange,
addTimer = viewModel::addTimer,
onNameChange = viewModel::onNameChange,
onDescriptionChange = viewModel::onDescriptionChange
)
}
@Composable @Composable
fun AddTimerRoute( fun AddTimerRoute(
open: (String) -> Unit, open: (String) -> Unit,
openAndPopUp: (String, String) -> Unit openAndPopUp: (String, String) -> Unit,
goBack: () -> Unit,
viewModel: AddTimerViewModel, viewModel: AddTimerViewModel,
drawerViewModel: DrawerViewModel,
navBarViewModel: NavigationBarViewModel,
) { ) {
addTimerScreen( val uiState by viewModel.uiState
drawerActions = getDrawerActions(
drawerViewModel = drawerViewModel, AddTimerScreen(
open = open, addTimerActions = getAddTimerActions(
openAndPopUp = openAndPopUp goBack = goBack,
viewModel = viewModel,
), ),
navigationBarActions = getNavigationBarActions( uiState = uiState
navigationBarViewModel = navBarViewModel,
open = open
)
) )
} }
fun addTimerScreen( @Composable
drawerActions: DrawerActions, fun AddTimerScreen(
navigationBarActions: NavigationBarActions addTimerActions: AddTimerActions,
uiState: AddTimerUiState,
) { ) {
SecondaryScreenTemplate( SecondaryScreenTemplate(
title = , title = resources().getString(R.string.add_timer),
popUp = { /*TODO*/ }) { popUp = addTimerActions.goBack
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(
text = "How long do you want to study?",
textAlign = TextAlign.Center
)
}
LazyColumn(
modifier = Modifier
.padding(16.dp)
) {
item{
Text(
text = "${uiState.studyTimeHours.toInt()} hour${ if (uiState.studyTimeHours == 1f) "" else "s"}"
)
Slider(
value = uiState.studyTimeHours,
onValueChange = {
addTimerActions.onStudyTimeHoursChange(it)
},
steps = 8,
valueRange = 1f..10f,
enabled = true
)
Text(
text = "${uiState.studyTimeMinutes.toInt()} minutes"
)
Slider(
value = uiState.studyTimeMinutes,
onValueChange = {
addTimerActions.onStudyTimeMinutesChange(it)
},
steps = 11,
valueRange = 0f..60f,
enabled = true
)
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(
text = "With breaks?",
)
Checkbox(
checked = uiState.withBreaks,
onCheckedChange = { addTimerActions.onWithBreaksChange(it) }
)
}
Text(
text = if (uiState.withBreaks) "breaks of ${uiState.breakTime.toInt()} minutes" else "",
)
Slider(
value = uiState.breakTime,
onValueChange = {
addTimerActions.onBreakTimeChange(it)
},
steps = 11,
valueRange = 0f..60f,
enabled = uiState.withBreaks
)
Text(
text = if (uiState.withBreaks) "${uiState.repeats.toInt()} breaks" else ""
)
Slider(
value = uiState.repeats,
onValueChange = {
addTimerActions.onRepeatsChange(it)
},
steps = 8,
valueRange = 1f..10f,
enabled = uiState.withBreaks
)
Text(
text = "Timer name"
)
TextField(
value = uiState.name,
onValueChange = { addTimerActions.onNameChange(it) }
)
Text(
text = "Timer description"
)
TextField(
value = uiState.description,
onValueChange = { addTimerActions.onDescriptionChange(it) }
)
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center
) {
BasicButton(
text = R.string.add_timer,
modifier = Modifier,
onClick = addTimerActions.addTimer
)
}
}
}
}
} }
}
@Preview
@Composable
fun AddTimerScreenPreview() {
AddTimerScreen(
addTimerActions = AddTimerActions({}, {}, {}, {}, {}, {}, {}, {}, {}),
uiState = AddTimerUiState()
)
} }