Merge pull request #95 from SELab1/timer_edit

Timer edit
This commit is contained in:
lbarraga 2023-05-04 00:13:25 +02:00 committed by GitHub Enterprise
commit d3159e0b2a
29 changed files with 583 additions and 110 deletions

View file

@ -32,6 +32,7 @@ import be.ugent.sel.studeez.screens.sessions.SessionsRoute
import be.ugent.sel.studeez.screens.settings.SettingsRoute
import be.ugent.sel.studeez.screens.sign_up.SignUpRoute
import be.ugent.sel.studeez.screens.splash.SplashRoute
import be.ugent.sel.studeez.screens.timer_edit.TimerEditRoute
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
@ -205,6 +206,14 @@ fun StudeezNavGraph(
)
}
composable(StudeezDestinations.TIMER_EDIT_SCREEN) {
TimerEditRoute(
open = open,
popUp = goBack,
viewModel = hiltViewModel()
)
}
// Friends flow
composable(StudeezDestinations.SEARCH_FRIENDS_SCREEN) {
// TODO

View file

@ -3,46 +3,113 @@ package be.ugent.sel.studeez.common.composable
import android.app.TimePickerDialog
import android.app.TimePickerDialog.OnTimeSetListener
import android.content.Context
import androidx.annotation.StringRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ButtonColors
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
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.ext.fieldModifier
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import java.util.*
import be.ugent.sel.studeez.ui.theme.StudeezTheme
@Composable
fun TimePickerCard(
@StringRes text: Int,
initialSeconds: Int,
onTimeChosen: (Int) -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.fieldModifier(),
elevation = 10.dp
) {
Row(
modifier = Modifier
.fillMaxWidth()
.fieldModifier(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(id = text),
fontWeight = FontWeight.Medium
)
TimePickerButton(
initialSeconds = initialSeconds,
onTimeChosen = onTimeChosen
)
}
}
}
@Composable
fun TimePickerButton(
hoursMinutesSeconds: HoursMinutesSeconds,
initialSeconds: Int,
modifier: Modifier = Modifier,
colors: ButtonColors = ButtonDefaults.buttonColors(),
border: BorderStroke? = null,
onTimeSetListener: OnTimeSetListener
onTimeChosen: (Int) -> Unit
) {
val context = LocalContext.current
val timeState: MutableState<Int> = remember {
mutableStateOf(initialSeconds)
}
Button(
onClick = { pickDuration(context, onTimeSetListener) },
onClick = { pickDuration(context, onTimeChosen, timeState) },
modifier = modifier,
shape = RoundedCornerShape(20.dp),
colors = colors,
border = border
) {
Text(text = hoursMinutesSeconds.toString())
Text(text = HoursMinutesSeconds(timeState.value).toString())
}
}
private fun pickDuration(context: Context, listener: OnTimeSetListener) {
val timePickerDialog = TimePickerDialog(
private fun pickDuration(context: Context, onTimeChosen: (Int) -> Unit, timeState: MutableState<Int>) {
val listener = OnTimeSetListener { _, hour, minute ->
timeState.value = HoursMinutesSeconds(hour, minute, 0).getTotalSeconds()
onTimeChosen(timeState.value)
}
val hms = HoursMinutesSeconds(timeState.value)
val mTimePickerDialog = TimePickerDialog(
context,
listener,
0,
0,
hms.hours,
hms.minutes,
true
)
timePickerDialog.show()
mTimePickerDialog.show()
}
@Preview
@Composable
fun TimePickerButtonPreview() {
StudeezTheme {
TimePickerButton(initialSeconds = 5 * 60 + 12, onTimeChosen = {})
}
}
@Preview
@Composable
fun TimePickerCardPreview() {
StudeezTheme {
TimePickerCard(text = R.string.studyTime, initialSeconds = 5 * 60 + 12, onTimeChosen = {})
}
}

View file

@ -1,4 +1,11 @@
package be.ugent.sel.studeez.data
class EditTimerState {
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class EditTimerState @Inject constructor(){
lateinit var timerInfo: TimerInfo
}

View file

@ -4,7 +4,7 @@ class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) {
override fun tick() {
if (!hasEnded()) {
time.minOne()
time--
totalStudyTime++
}
}

View file

@ -11,7 +11,7 @@ class FunctionalEndlessTimer : FunctionalTimer(0) {
}
override fun tick() {
time.plusOne()
time++
totalStudyTime++
}

View file

@ -22,7 +22,7 @@ class FunctionalPomodoroTimer(
}
isInBreak = !isInBreak
}
time.minOne()
time--
if (!isInBreak) {
totalStudyTime++

View file

@ -4,7 +4,7 @@ import be.ugent.sel.studeez.data.local.models.SessionReport
import com.google.firebase.Timestamp
abstract class FunctionalTimer(initialValue: Int) {
val time: Time = Time(initialValue)
var time: Time = Time(initialValue)
var totalStudyTime: Int = 0
fun getHoursMinutesSeconds(): HoursMinutesSeconds {

View file

@ -2,6 +2,12 @@ package be.ugent.sel.studeez.data.local.models.timer_functional
data class HoursMinutesSeconds(val hours: Int, val minutes: Int, val seconds: Int) {
constructor(sec: Int): this(
sec / (60 * 60),
(sec / (60)) % 60,
sec % 60
)
fun getTotalSeconds(): Int {
return hours * 60 * 60 + minutes * 60 + seconds
}

View file

@ -1,23 +1,13 @@
package be.ugent.sel.studeez.data.local.models.timer_functional
class Time(initialTime: Int) {
class Time(var time: Int) {
operator fun invoke() = time
var time = initialTime
operator fun inc(): Time = Time(time + 1)
fun minOne() {
time--
}
fun plusOne() {
time++
}
operator fun dec(): Time = Time(time - 1)
fun getAsHMS(): HoursMinutesSeconds {
val hours: Int = time / (60 * 60)
val minutes: Int = (time / (60)) % 60
val seconds: Int = time % 60
return HoursMinutesSeconds(hours, minutes, seconds)
return HoursMinutesSeconds(time)
}
}

View file

@ -7,8 +7,8 @@ import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimerVi
class PomodoroTimerInfo(
name: String,
description: String,
val studyTime: Int,
val breakTime: Int,
var studyTime: Int,
var breakTime: Int,
val repeats: Int,
id: String = ""
): TimerInfo(id, name, description) {

View file

@ -18,6 +18,7 @@ object StudeezDestinations {
// Studying flow
const val TIMER_SELECTION_SCREEN = "timer_selection"
const val TIMER_EDIT_SCREEN = "timer_edit"
const val SESSION_SCREEN = "session"
const val SESSION_RECAP = "session_recap"

View file

@ -78,7 +78,7 @@ abstract class AbstractSessionScreen {
val hms = sessionActions.getTimer().getHoursMinutesSeconds()
Column {
Text(
text = "${hms.hours} : ${hms.minutes} : ${hms.seconds}",
text = hms.toString(),
modifier = Modifier
.fillMaxWidth()
.padding(50.dp),

View file

@ -50,7 +50,7 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi
Column(
modifier = modifier
) {
Text(text = "You studied: ${hms.hours} : ${hms.minutes} : ${hms.seconds}")
Text(text = "You studied: $hms")
BasicButton(
R.string.save, Modifier.basicButton()

View file

@ -0,0 +1,44 @@
package be.ugent.sel.studeez.screens.timer_add
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.screens.timer_edit.GetTimerEditScreen
import be.ugent.sel.studeez.screens.timer_edit.TimerEditViewModel
import be.ugent.sel.studeez.screens.timer_edit.editScreens.AbstractTimerEditScreen
import be.ugent.sel.studeez.ui.theme.StudeezTheme
data class TimerEditActions(
val getTimerInfo: () -> TimerInfo,
val saveTimer: (TimerInfo, () -> Unit) -> Unit
)
fun getTimerEditActions(
viewModel: TimerEditViewModel,
open: (String) -> Unit
): TimerEditActions {
return TimerEditActions(
getTimerInfo = viewModel::getTimerInfo,
saveTimer = viewModel::saveTimer
)
}
@Composable
fun TimerEditRoute(
open: (String) -> Unit,
popUp: () -> Unit,
viewModel: TimerEditViewModel,
) {
val timerEditActions = getTimerEditActions(viewModel, open)
SecondaryScreenTemplate(title = "Edit Timer", popUp = popUp) {
val timerEditScreen = timerEditActions.getTimerInfo().accept(GetTimerEditScreen())
timerEditScreen { timerInfo ->
timerEditActions.saveTimer(timerInfo, popUp)
}
}
}

View file

@ -0,0 +1,29 @@
package be.ugent.sel.studeez.screens.timer_add
import be.ugent.sel.studeez.data.EditTimerState
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class TimerAddViewModel @Inject constructor(
private val editTimerState: EditTimerState,
private val timerDAO: TimerDAO,
logService: LogService
) : StudeezViewModel(logService) {
private val timerInfo: TimerInfo = editTimerState.timerInfo
fun getTimerInfo(): TimerInfo {
return timerInfo
}
fun saveTimer(timerInfo: TimerInfo, goBack: () -> Unit) {
timerDAO.updateTimer(timerInfo)
goBack()
}
}

View file

@ -0,0 +1,43 @@
package be.ugent.sel.studeez.screens.timer_add
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.data.local.models.timer_info.*
import be.ugent.sel.studeez.data.local.models.timer_info.TimerType.CUSTOM
import be.ugent.sel.studeez.data.local.models.timer_info.TimerType.BREAK
import be.ugent.sel.studeez.data.local.models.timer_info.TimerType.ENDLESS
val defaultTimerInfo: Map<TimerType, TimerInfo> = mapOf(
CUSTOM to CustomTimerInfo("", "", 0),
BREAK to PomodoroTimerInfo("", "", 0, 0, 0),
ENDLESS to EndlessTimerInfo("", ""),
)
@Composable
fun TimerTypeSelectScreen(
open: (String) -> Unit,
popUp: () -> Unit,
viewModel: TimerTypeSelectViewModel = hiltViewModel()
) {
SecondaryScreenTemplate(title = "Edit Timer", popUp = popUp) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
TimerType.values().forEach { timerType ->
Button(onClick = { viewModel.onTimerTypeChosen(defaultTimerInfo[timerType]!!, open) }) {
Text(text = timerType.name)
}
}
}
}
}

View file

@ -0,0 +1,25 @@
package be.ugent.sel.studeez.screens.timer_add
import be.ugent.sel.studeez.data.EditTimerState
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
@HiltViewModel
class TimerTypeSelectViewModel @Inject constructor(
private val editTimerState: EditTimerState,
private val timerDAO: TimerDAO,
logService: LogService
) : StudeezViewModel(logService) {
fun onTimerTypeChosen(timerInfo: TimerInfo, open: (String) -> Unit) {
editTimerState.timerInfo = timerInfo
open(StudeezDestinations.TIMER_EDIT_SCREEN)
}
}

View file

@ -1,34 +1,26 @@
package be.ugent.sel.studeez.screens.timer_edit
import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.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.EndlessTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.PomodoroTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfoVisitor
import be.ugent.sel.studeez.screens.timer_edit.editScreens.AbstractTimerEditScreen
import be.ugent.sel.studeez.screens.timer_edit.editScreens.BreakTimerEditScreen
import be.ugent.sel.studeez.screens.timer_edit.editScreens.CustomTimerEditScreen
import be.ugent.sel.studeez.screens.timer_edit.editScreens.EndlessTimerEditScreen
class GetTimerEditView: TimerInfoVisitor<Unit> {
@SuppressLint("ComposableNaming")
override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo) {
class GetTimerEditScreen: TimerInfoVisitor<AbstractTimerEditScreen> {
override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerEditScreen {
return CustomTimerEditScreen(customTimerInfo)
}
@SuppressLint("ComposableNaming")
override fun visitEndlessTimerInfo(endlessTimerInfo: EndlessTimerInfo) {
override fun visitEndlessTimerInfo(endlessTimerInfo: EndlessTimerInfo): AbstractTimerEditScreen {
return EndlessTimerEditScreen(endlessTimerInfo)
}
@SuppressLint("ComposableNaming")
override fun visitBreakTimerInfo(pomodoroTimerInfo: PomodoroTimerInfo) {
override fun visitBreakTimerInfo(pomodoroTimerInfo: PomodoroTimerInfo): AbstractTimerEditScreen {
return BreakTimerEditScreen(pomodoroTimerInfo)
}

View file

@ -1,2 +1,65 @@
package be.ugent.sel.studeez.screens.timer_edit
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.screens.timer_edit.editScreens.AbstractTimerEditScreen
import be.ugent.sel.studeez.ui.theme.StudeezTheme
data class TimerEditActions(
val getTimerInfo: () -> TimerInfo,
val saveTimer: (TimerInfo, () -> Unit) -> Unit
)
fun getTimerEditActions(
viewModel: TimerEditViewModel,
open: (String) -> Unit
): TimerEditActions {
return TimerEditActions(
getTimerInfo = viewModel::getTimerInfo,
saveTimer = viewModel::saveTimer
)
}
@Composable
fun TimerEditRoute(
open: (String) -> Unit,
popUp: () -> Unit,
viewModel: TimerEditViewModel,
) {
val timerEditActions = getTimerEditActions(viewModel, open)
SecondaryScreenTemplate(title = "Edit Timer", popUp = popUp) {
val timerEditScreen = timerEditActions.getTimerInfo().accept(GetTimerEditScreen())
timerEditScreen { timerInfo ->
timerEditActions.saveTimer(timerInfo, popUp)
}
}
}

View file

@ -1,4 +1,29 @@
package be.ugent.sel.studeez.screens.timer_edit
class TimerEditViewModel {
import be.ugent.sel.studeez.data.EditTimerState
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class TimerEditViewModel @Inject constructor(
private val editTimerState: EditTimerState,
private val timerDAO: TimerDAO,
logService: LogService
) : StudeezViewModel(logService) {
private val timerInfo: TimerInfo = editTimerState.timerInfo
fun getTimerInfo(): TimerInfo {
return timerInfo
}
fun saveTimer(timerInfo: TimerInfo, goBack: () -> Unit) {
timerDAO.updateTimer(timerInfo)
goBack()
}
}

View file

@ -1,4 +1,70 @@
package be.ugent.sel.studeez.screens.timer_edit
package be.ugent.sel.studeez.screens.timer_edit.editScreens
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.BasicButton
import be.ugent.sel.studeez.common.composable.LabelledInputField
import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
abstract class AbstractTimerEditScreen(private val timerInfo: TimerInfo) {
@Composable
operator fun invoke(onSaveClick: (TimerInfo) -> Unit) {
var name by remember { mutableStateOf(timerInfo.name) }
var description by remember { mutableStateOf(timerInfo.description) }
// This shall rerun whenever name and description change
timerInfo.name = name
timerInfo.description = description
Column(
verticalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxHeight().verticalScroll(rememberScrollState()),
) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Fields that every timer shares (ommited id)
LabelledInputField(
value = name,
onNewValue = { name = it },
label = R.string.name
)
repeat(20) {
LabelledInputField(
value = description,
onNewValue = { description = it },
label = R.string.description,
singleLine = false
)
}
ExtraFields()
}
BasicButton(R.string.save, Modifier.basicButton()) {
onSaveClick(timerInfo)
}
}
}
@Composable
open fun ExtraFields() {
// By default no extra fields, unless overwritten by subclass.
}
abstract class AbstractTimerEditScreen {
}

View file

@ -1,4 +1,46 @@
package be.ugent.sel.studeez.screens.timer_edit.editScreens
class BreakTimerEditScreen {
import androidx.compose.runtime.*
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.TimePickerButton
import be.ugent.sel.studeez.common.composable.TimePickerCard
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.data.local.models.timer_functional.Time
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.EndlessTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.PomodoroTimerInfo
import be.ugent.sel.studeez.ui.theme.StudeezTheme
class BreakTimerEditScreen(
private val breakTimerInfo: PomodoroTimerInfo
): AbstractTimerEditScreen(breakTimerInfo) {
@Composable
override fun ExtraFields() {
// If the user presses the OK button on the timepicker, the time in the button should change
TimePickerCard(R.string.studyTime, breakTimerInfo.studyTime) { newTime ->
breakTimerInfo.studyTime = newTime
}
TimePickerCard(R.string.breakTime, breakTimerInfo.breakTime) { newTime ->
breakTimerInfo.breakTime = newTime
}
}
}
@Preview
@Composable
fun BreakEditScreenPreview() {
val pomodoroTimerInfo = PomodoroTimerInfo(
"Breaky the Breaktimer",
"Breaky is a breakdancer",
10 * 60,
60,
5
)
StudeezTheme {
BreakTimerEditScreen(pomodoroTimerInfo).invoke(onSaveClick = {})
}
}

View file

@ -1,4 +1,34 @@
package be.ugent.sel.studeez.screens.timer_edit
package be.ugent.sel.studeez.screens.timer_edit.editScreens
import androidx.compose.runtime.*
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.common.composable.TimePickerCard
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import be.ugent.sel.studeez.R.string as AppText
class CustomTimerEditScreen(
private val customTimerInfo: CustomTimerInfo
): AbstractTimerEditScreen(customTimerInfo) {
@Composable
override fun ExtraFields() {
TimePickerCard(
text = AppText.studyTime,
initialSeconds = customTimerInfo.studyTime
) { newTime ->
customTimerInfo.studyTime = newTime
}
}
class CustomTimerEditScreen {
}
@Preview
@Composable
fun CustomEditScreenPreview() {
val customTimerInfo = CustomTimerInfo("custom", "my description", 25)
StudeezTheme {
CustomTimerEditScreen(customTimerInfo).invoke(onSaveClick = {})
}
}

View file

@ -1,4 +1,23 @@
package be.ugent.sel.studeez.screens.timer_edit.editScreens
class EndlessTimerEditScreen {
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.data.local.models.timer_info.EndlessTimerInfo
import be.ugent.sel.studeez.ui.theme.StudeezTheme
class EndlessTimerEditScreen(
endlessTimerInfo: EndlessTimerInfo
): AbstractTimerEditScreen(endlessTimerInfo) {
}
@Preview
@Composable
fun EndlessEditScreenPreview() {
val endlessTimerInfo = EndlessTimerInfo(
"Forever and beyond",
"My endless timer description",
)
StudeezTheme {
EndlessTimerEditScreen(endlessTimerInfo).invoke(onSaveClick = {})
}
}

View file

@ -1,5 +1,6 @@
package be.ugent.sel.studeez.screens.timer_overview
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
@ -24,7 +25,7 @@ data class TimerOverviewActions(
val getUserTimers: () -> Flow<List<TimerInfo>>,
val getDefaultTimers: () -> List<TimerInfo>,
val onEditClick: (TimerInfo) -> Unit,
val open: (String) -> Unit,
val onAddClick: () -> Unit,
)
fun getTimerOverviewActions(
@ -34,20 +35,20 @@ fun getTimerOverviewActions(
return TimerOverviewActions(
getUserTimers = viewModel::getUserTimers,
getDefaultTimers = viewModel::getDefaultTimers,
onEditClick = { viewModel.update(it) },
open = open
onEditClick = { viewModel.update(it, open) },
onAddClick = { viewModel.create(open) }
)
}
@Composable
fun TimerOverviewRoute(
open: (String) -> Unit,
viewModel: TimerOverviewViewModel,
drawerActions: DrawerActions,
open: (String) -> Unit
) {
TimerOverviewScreen(
timerOverviewActions = getTimerOverviewActions(viewModel, open),
drawerActions = drawerActions,
drawerActions = drawerActions
)
}
@ -63,6 +64,7 @@ fun TimerOverviewScreen(
title = resources().getString(R.string.timers),
drawerActions = drawerActions
) {
Column { // TODO knop beneden
LazyColumn {
// Custom timer, select new duration each time
item {
@ -88,9 +90,12 @@ fun TimerOverviewScreen(
}
}
// TODO uit lazy column
item {
BasicButton(R.string.add_timer, Modifier.basicButton()) {
timerOverviewActions.open(StudeezDestinations.ADD_TIMER_SCREEN)
timerOverviewActions.onAddClick()
}
}
}
}

View file

@ -1,9 +1,11 @@
package be.ugent.sel.studeez.screens.timer_overview
import be.ugent.sel.studeez.data.EditTimerState
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.domain.ConfigurationService
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
@ -13,6 +15,7 @@ import javax.inject.Inject
class TimerOverviewViewModel @Inject constructor(
private val configurationService: ConfigurationService,
private val timerDAO: TimerDAO,
private val editTimerState: EditTimerState,
logService: LogService
) : StudeezViewModel(logService) {
@ -24,7 +27,14 @@ class TimerOverviewViewModel @Inject constructor(
return configurationService.getDefaultTimers()
}
fun update(timerInfo: TimerInfo) = timerDAO.updateTimer(timerInfo)
fun update(timerInfo: TimerInfo, open: (String) -> Unit) {
editTimerState.timerInfo = timerInfo
open(StudeezDestinations.TIMER_EDIT_SCREEN)
}
fun create(open: (String) -> Unit) {
open(StudeezDestinations.ADD_TIMER_SCREEN)
}
fun delete(timerInfo: TimerInfo) =timerDAO.deleteTimer(timerInfo)

View file

@ -253,7 +253,7 @@ fun AddTimerScreen(
onClick = {
if (uiState.description != "" && uiState.name != "") {
addTimerActions.addTimer()
addTimerActions.open(StudeezDestinations.TIMER_OVERVIEW_SCREEN)
addTimerActions.open(StudeezDestinations.TIMER_SCREEN)
}
}
)

View file

@ -1,11 +1,9 @@
package be.ugent.sel.studeez.screens.timer_selection
import android.widget.TimePicker
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
@ -23,7 +21,6 @@ import kotlinx.coroutines.flow.flowOf
data class TimerSelectionActions(
val getAllTimers: () -> Flow<List<TimerInfo>>,
val startSession: (TimerInfo) -> Unit,
val pickDuration: (TimePicker?, Int, Int) -> Unit,
val customTimeStudyTime: Int
)
@ -34,9 +31,6 @@ fun getTimerSelectionActions(
return TimerSelectionActions(
getAllTimers = viewModel::getAllTimers,
startSession = { viewModel.startSession(open, it) },
pickDuration = { _, hour: Int, minute: Int ->
viewModel.customTimerStudyTime.value = hour * 60 * 60 + minute * 60
},
customTimeStudyTime = viewModel.customTimerStudyTime.value
)
}
@ -105,10 +99,9 @@ fun CustomTimerEntry(
)
},
rightButton = {
TimePickerButton(
hoursMinutesSeconds = hms,
onTimeSetListener = timerSelectionActions.pickDuration
)
TimePickerButton(initialSeconds = hms.getTotalSeconds()) { chosenTime ->
timerInfo.studyTime = chosenTime
}
}
)
}
@ -117,7 +110,7 @@ fun CustomTimerEntry(
@Composable
fun TimerSelectionPreview() {
TimerSelectionScreen(
timerSelectionActions = TimerSelectionActions({ flowOf() }, {}, { _, _, _ -> {} }, 0),
timerSelectionActions = TimerSelectionActions({ flowOf() }, {}, 0),
popUp = {}
)
}

View file

@ -123,4 +123,11 @@
<string name="addTimer_studytime_2">" minutes of studytime"</string>
<string name="addTimer_question">How long do you want to study?</string>
<!-- Edit Timer-->
<string name="name">Name</string>
<string name="description">Description</string>
<string name="studyTime">Study Time</string>
<string name="breakTime">Break Time</string>
<string name="repeats">Number of Repeats</string>
</resources>