commit
						81fa345453
					
				
					 23 changed files with 232 additions and 604 deletions
				
			
		|  | @ -2,18 +2,8 @@ package be.ugent.sel.studeez | |||
| 
 | ||||
| import android.content.res.Resources | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.material.Scaffold | ||||
| import androidx.compose.material.ScaffoldState | ||||
| import androidx.compose.material.Snackbar | ||||
| import androidx.compose.material.SnackbarHost | ||||
| import androidx.compose.material.Surface | ||||
| import androidx.compose.material.rememberScaffoldState | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.ReadOnlyComposable | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.remember | ||||
| import androidx.compose.runtime.rememberCoroutineScope | ||||
| import androidx.compose.material.* | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.platform.LocalConfiguration | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
|  | @ -48,9 +38,10 @@ import be.ugent.sel.studeez.screens.tasks.forms.SubjectAddRoute | |||
| import be.ugent.sel.studeez.screens.tasks.forms.SubjectEditRoute | ||||
| import be.ugent.sel.studeez.screens.tasks.forms.TaskAddRoute | ||||
| import be.ugent.sel.studeez.screens.tasks.forms.TaskEditRoute | ||||
| import be.ugent.sel.studeez.screens.timer_edit.TimerEditRoute | ||||
| import be.ugent.sel.studeez.screens.timer_form.timer_type_select.TimerTypeSelectScreen | ||||
| import be.ugent.sel.studeez.screens.timer_form.TimerAddRoute | ||||
| import be.ugent.sel.studeez.screens.timer_form.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 | ||||
| import be.ugent.sel.studeez.ui.theme.StudeezTheme | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
|  | @ -245,6 +236,13 @@ fun StudeezNavGraph( | |||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composable(StudeezDestinations.TIMER_TYPE_CHOOSING_SCREEN) { | ||||
|             TimerTypeSelectScreen( | ||||
|                 open = open, | ||||
|                 popUp = goBack | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composable(StudeezDestinations.SESSION_SCREEN) { | ||||
|             SessionRoute( | ||||
|                 open, | ||||
|  | @ -261,16 +259,14 @@ fun StudeezNavGraph( | |||
|         } | ||||
| 
 | ||||
|         composable(StudeezDestinations.ADD_TIMER_SCREEN) { | ||||
|             AddTimerRoute( | ||||
|                 open = open, | ||||
|                 goBack = goBack, | ||||
|             TimerAddRoute( | ||||
|                 popUp = goBack, | ||||
|                 viewModel = hiltViewModel() | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composable(StudeezDestinations.TIMER_EDIT_SCREEN) { | ||||
|             TimerEditRoute( | ||||
|                 open = open, | ||||
|                 popUp = goBack, | ||||
|                 viewModel = hiltViewModel() | ||||
|             ) | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| package be.ugent.sel.studeez.common.composable | ||||
| 
 | ||||
| import androidx.annotation.StringRes | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.text.KeyboardActions | ||||
| import androidx.compose.foundation.text.KeyboardOptions | ||||
| import androidx.compose.material.Icon | ||||
| import androidx.compose.material.IconButton | ||||
| import androidx.compose.material.OutlinedTextField | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material.* | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.Email | ||||
| import androidx.compose.material.icons.filled.Lock | ||||
|  | @ -14,10 +14,15 @@ import androidx.compose.runtime.* | |||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.res.painterResource | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.text.input.ImeAction | ||||
| import androidx.compose.ui.text.input.KeyboardType | ||||
| import androidx.compose.ui.text.input.PasswordVisualTransformation | ||||
| import androidx.compose.ui.text.input.VisualTransformation | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import be.ugent.sel.studeez.common.ext.fieldModifier | ||||
| import be.ugent.sel.studeez.resources | ||||
| import kotlin.math.sin | ||||
| import be.ugent.sel.studeez.R.drawable as AppIcon | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
|  | @ -85,6 +90,86 @@ fun EmailField( | |||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun LabeledNumberInputField( | ||||
|     value: Int, | ||||
|     onNewValue: (Int) -> Unit, | ||||
|     @StringRes label: Int, | ||||
|     singleLine: Boolean = false | ||||
| ) { | ||||
|     var number by remember { mutableStateOf(value) } | ||||
|     OutlinedTextField( | ||||
|         value = number.toString(), | ||||
|         singleLine = singleLine, | ||||
|         label = { Text(resources().getString(label)) }, | ||||
|         keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), | ||||
|         onValueChange = {typedInt -> | ||||
|             val isNumber = typedInt.matches(Regex("[1-9]+\\d*]")) | ||||
|             if (isNumber) { | ||||
|                 number = typedInt.toInt() | ||||
|                 onNewValue(typedInt.toInt()) | ||||
|             } | ||||
|         } | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun LabeledErrorTextField( | ||||
|     modifier: Modifier = Modifier, | ||||
|     initialValue: String, | ||||
|     @StringRes label: Int, | ||||
|     singleLine: Boolean = false, | ||||
|     errorText: Int, | ||||
|     keyboardType: KeyboardType, | ||||
|     predicate: (String) -> Boolean, | ||||
|     onNewCorrectValue: (String) -> Unit | ||||
| ) { | ||||
|     var value by remember { | ||||
|         mutableStateOf(initialValue) | ||||
|     } | ||||
| 
 | ||||
|     var isValid by remember { | ||||
|         mutableStateOf(predicate(value)) | ||||
|     } | ||||
| 
 | ||||
|     Column { | ||||
|         OutlinedTextField( | ||||
|             modifier = modifier.fieldModifier(), | ||||
|             value = value, | ||||
|             onValueChange = { newText -> | ||||
|                 value = newText | ||||
|                 isValid = predicate(value) | ||||
|                 if (isValid) { | ||||
|                     onNewCorrectValue(newText) | ||||
|                 } | ||||
|             }, | ||||
|             singleLine = singleLine, | ||||
|             label = { Text(text = stringResource(id = label)) }, | ||||
|             isError = !isValid, | ||||
|             keyboardOptions = KeyboardOptions( | ||||
|                 keyboardType = keyboardType, | ||||
|                 imeAction = ImeAction.Done | ||||
|             ) | ||||
|         ) | ||||
| 
 | ||||
|         if (!isValid) { | ||||
|             Text( | ||||
|                 modifier = Modifier.padding(start = 16.dp), | ||||
|                 text = stringResource(id = errorText), | ||||
|                 color = MaterialTheme.colors.error | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  @Preview(showBackground = true) | ||||
|  @Composable | ||||
|  fun IntInputPreview() { | ||||
|      LabeledNumberInputField(value = 1, onNewValue = {}, label = AppText.email) | ||||
|  } | ||||
| 
 | ||||
| @Composable | ||||
| fun PasswordField( | ||||
|     value: String, | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ class PomodoroTimerInfo( | |||
|     description: String, | ||||
|     var studyTime: Int, | ||||
|     var breakTime: Int, | ||||
|     val repeats: Int, | ||||
|     var repeats: Int, | ||||
|     id: String = "" | ||||
| ):  TimerInfo(id, name, description) { | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ object StudeezDestinations { | |||
|     // Studying flow | ||||
|     const val TIMER_SELECTION_SCREEN = "timer_selection" | ||||
|     const val TIMER_EDIT_SCREEN = "timer_edit" | ||||
|     const val TIMER_TYPE_CHOOSING_SCREEN = "timer_type_choosing_screen" | ||||
|     const val SESSION_SCREEN = "session" | ||||
|     const val SESSION_RECAP = "session_recap" | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,44 +0,0 @@ | |||
| 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) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,29 +0,0 @@ | |||
| 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() | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,27 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.timer_edit | ||||
| 
 | ||||
| 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 GetTimerEditScreen: TimerInfoVisitor<AbstractTimerEditScreen> { | ||||
| 
 | ||||
|     override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerEditScreen { | ||||
|         return CustomTimerEditScreen(customTimerInfo) | ||||
|     } | ||||
| 
 | ||||
|     override fun visitEndlessTimerInfo(endlessTimerInfo: EndlessTimerInfo): AbstractTimerEditScreen { | ||||
|         return EndlessTimerEditScreen(endlessTimerInfo) | ||||
|     } | ||||
| 
 | ||||
|     override fun visitBreakTimerInfo(pomodoroTimerInfo: PomodoroTimerInfo): AbstractTimerEditScreen { | ||||
|         return BreakTimerEditScreen(pomodoroTimerInfo) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -1,65 +0,0 @@ | |||
| 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) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,27 @@ | |||
| package be.ugent.sel.studeez.screens.timer_form | ||||
| 
 | ||||
| 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_form.form_screens.AbstractTimerFormScreen | ||||
| import be.ugent.sel.studeez.screens.timer_form.form_screens.BreakTimerFormScreen | ||||
| import be.ugent.sel.studeez.screens.timer_form.form_screens.CustomTimerFormScreen | ||||
| import be.ugent.sel.studeez.screens.timer_form.form_screens.EndlessTimerFormScreen | ||||
| 
 | ||||
| class GetTimerFormScreen: TimerInfoVisitor<AbstractTimerFormScreen> { | ||||
| 
 | ||||
|     override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerFormScreen { | ||||
|         return CustomTimerFormScreen(customTimerInfo) | ||||
|     } | ||||
| 
 | ||||
|     override fun visitEndlessTimerInfo(endlessTimerInfo: EndlessTimerInfo): AbstractTimerFormScreen { | ||||
|         return EndlessTimerFormScreen(endlessTimerInfo) | ||||
|     } | ||||
| 
 | ||||
|     override fun visitBreakTimerInfo(pomodoroTimerInfo: PomodoroTimerInfo): AbstractTimerFormScreen { | ||||
|         return BreakTimerFormScreen(pomodoroTimerInfo) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,42 @@ | |||
| package be.ugent.sel.studeez.screens.timer_form | ||||
| 
 | ||||
| import androidx.annotation.StringRes | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| @Composable | ||||
| fun TimerAddRoute( | ||||
|     popUp: () -> Unit, | ||||
|     viewModel: TimerFormViewModel | ||||
| ) { | ||||
|     TimerFormScreen(popUp = popUp, getTimerInfo = viewModel::getTimerInfo, AppText.add_timer) { | ||||
|         viewModel.saveTimer(it, goBack = popUp) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun TimerEditRoute( | ||||
|     popUp: () -> Unit, | ||||
|     viewModel: TimerFormViewModel | ||||
| ) { | ||||
|     TimerFormScreen(popUp = popUp, getTimerInfo = viewModel::getTimerInfo, AppText.edit_timer) { | ||||
|         viewModel.editTimer(it, goBack = popUp) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun TimerFormScreen( | ||||
|     popUp: () -> Unit, | ||||
|     getTimerInfo: () -> TimerInfo, | ||||
|     @StringRes label: Int, | ||||
|     onConfirmClick: (TimerInfo) -> Unit | ||||
| ) { | ||||
|     val timerFormScreen = getTimerInfo().accept(GetTimerFormScreen()) | ||||
| 
 | ||||
|     SecondaryScreenTemplate(title = stringResource(id = label), popUp = popUp) { | ||||
|         timerFormScreen(onConfirmClick) | ||||
|     } | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package be.ugent.sel.studeez.screens.timer_edit | ||||
| package be.ugent.sel.studeez.screens.timer_form | ||||
| 
 | ||||
| import be.ugent.sel.studeez.data.EditTimerState | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo | ||||
|  | @ -9,7 +9,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel | |||
| import javax.inject.Inject | ||||
| 
 | ||||
| @HiltViewModel | ||||
| class TimerEditViewModel @Inject constructor( | ||||
| class TimerFormViewModel @Inject constructor( | ||||
|     private val editTimerState: EditTimerState, | ||||
|     private val timerDAO: TimerDAO, | ||||
|     logService: LogService | ||||
|  | @ -21,9 +21,13 @@ class TimerEditViewModel @Inject constructor( | |||
|         return timerInfo | ||||
|     } | ||||
| 
 | ||||
|     fun saveTimer(timerInfo: TimerInfo, goBack: () -> Unit) { | ||||
|     fun editTimer(timerInfo: TimerInfo, goBack: () -> Unit) { | ||||
|         timerDAO.updateTimer(timerInfo) | ||||
|         goBack() | ||||
|     } | ||||
| 
 | ||||
|     fun saveTimer(timerInfo: TimerInfo, goBack: () -> Unit) { | ||||
|         timerDAO.saveTimer(timerInfo) | ||||
|         goBack() | ||||
|     } | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package be.ugent.sel.studeez.screens.timer_edit.editScreens | ||||
| package be.ugent.sel.studeez.screens.timer_form.form_screens | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.Arrangement | ||||
| import androidx.compose.foundation.layout.Column | ||||
|  | @ -18,8 +18,9 @@ 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 | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| abstract class AbstractTimerEditScreen(private val timerInfo: TimerInfo) { | ||||
| abstract class AbstractTimerFormScreen(private val timerInfo: TimerInfo) { | ||||
| 
 | ||||
|     @Composable | ||||
|     operator fun invoke(onSaveClick: (TimerInfo) -> Unit) { | ||||
|  | @ -50,7 +51,7 @@ abstract class AbstractTimerEditScreen(private val timerInfo: TimerInfo) { | |||
|                 LabelledInputField( | ||||
|                     value = description, | ||||
|                     onNewValue = { description = it }, | ||||
|                     label = R.string.description, | ||||
|                     label = AppText.description, | ||||
|                     singleLine = false | ||||
|                 ) | ||||
| 
 | ||||
|  | @ -1,20 +1,19 @@ | |||
| package be.ugent.sel.studeez.screens.timer_edit.editScreens | ||||
| package be.ugent.sel.studeez.screens.timer_form.form_screens | ||||
| 
 | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.text.input.KeyboardType | ||||
| 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.LabeledErrorTextField | ||||
| 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 | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| class BreakTimerEditScreen( | ||||
| 
 | ||||
| class BreakTimerFormScreen( | ||||
|     private val breakTimerInfo: PomodoroTimerInfo | ||||
| ): AbstractTimerEditScreen(breakTimerInfo) { | ||||
| ): AbstractTimerFormScreen(breakTimerInfo) { | ||||
| 
 | ||||
|     @Composable | ||||
|     override fun ExtraFields() { | ||||
|  | @ -26,8 +25,18 @@ class BreakTimerEditScreen( | |||
|         TimePickerCard(R.string.breakTime, breakTimerInfo.breakTime) { newTime -> | ||||
|             breakTimerInfo.breakTime = newTime | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         LabeledErrorTextField( | ||||
|             initialValue = breakTimerInfo.repeats.toString(), | ||||
|             label = R.string.repeats, | ||||
|             errorText = AppText.repeats_error, | ||||
|             keyboardType = KeyboardType.Decimal, | ||||
|             predicate = { it.matches(Regex("[1-9]+\\d*")) } | ||||
|         ) { correctlyTypedInt -> | ||||
|             breakTimerInfo.repeats = correctlyTypedInt.toInt() | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
|  | @ -41,6 +50,6 @@ fun BreakEditScreenPreview() { | |||
|         5 | ||||
|     ) | ||||
|     StudeezTheme { | ||||
|         BreakTimerEditScreen(pomodoroTimerInfo).invoke(onSaveClick = {}) | ||||
|         BreakTimerFormScreen(pomodoroTimerInfo).invoke(onSaveClick = {}) | ||||
|     } | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package be.ugent.sel.studeez.screens.timer_edit.editScreens | ||||
| package be.ugent.sel.studeez.screens.timer_form.form_screens | ||||
| 
 | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
|  | @ -7,9 +7,9 @@ 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( | ||||
| class CustomTimerFormScreen( | ||||
|     private val customTimerInfo: CustomTimerInfo | ||||
|     ): AbstractTimerEditScreen(customTimerInfo) { | ||||
|     ): AbstractTimerFormScreen(customTimerInfo) { | ||||
| 
 | ||||
|     @Composable | ||||
|     override fun ExtraFields() { | ||||
|  | @ -29,6 +29,6 @@ class CustomTimerEditScreen( | |||
| fun CustomEditScreenPreview() { | ||||
|     val customTimerInfo = CustomTimerInfo("custom", "my description", 25) | ||||
|     StudeezTheme { | ||||
|         CustomTimerEditScreen(customTimerInfo).invoke(onSaveClick = {}) | ||||
|         CustomTimerFormScreen(customTimerInfo).invoke(onSaveClick = {}) | ||||
|     } | ||||
| } | ||||
|  | @ -1,13 +1,13 @@ | |||
| package be.ugent.sel.studeez.screens.timer_edit.editScreens | ||||
| package be.ugent.sel.studeez.screens.timer_form.form_screens | ||||
| 
 | ||||
| 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( | ||||
| class EndlessTimerFormScreen( | ||||
|     endlessTimerInfo: EndlessTimerInfo | ||||
| ): AbstractTimerEditScreen(endlessTimerInfo) { | ||||
| ): AbstractTimerFormScreen(endlessTimerInfo) { | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
|  | @ -18,6 +18,6 @@ fun EndlessEditScreenPreview() { | |||
|         "My endless timer description", | ||||
|     ) | ||||
|     StudeezTheme { | ||||
|         EndlessTimerEditScreen(endlessTimerInfo).invoke(onSaveClick = {}) | ||||
|         EndlessTimerFormScreen(endlessTimerInfo).invoke(onSaveClick = {}) | ||||
|     } | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package be.ugent.sel.studeez.screens.timer_add | ||||
| package be.ugent.sel.studeez.screens.timer_form.timer_type_select | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
|  | @ -7,16 +7,18 @@ import androidx.compose.material.Text | |||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.res.stringResource | ||||
| 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.R.string as AppText | ||||
| 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), | ||||
|     BREAK to PomodoroTimerInfo("", "", 0, 0, 1), | ||||
|     ENDLESS to EndlessTimerInfo("", ""), | ||||
| ) | ||||
| 
 | ||||
|  | @ -28,13 +30,14 @@ fun TimerTypeSelectScreen( | |||
|     viewModel: TimerTypeSelectViewModel = hiltViewModel() | ||||
| ) { | ||||
| 
 | ||||
|     SecondaryScreenTemplate(title = "Edit Timer", popUp = popUp) { | ||||
|     SecondaryScreenTemplate(title = stringResource(id = AppText.timer_type_select), popUp = popUp) { | ||||
|         Column( | ||||
|             horizontalAlignment = Alignment.CenterHorizontally, | ||||
|             modifier = Modifier.fillMaxWidth() | ||||
|         ) { | ||||
|             TimerType.values().forEach { timerType -> | ||||
|                 Button(onClick = { viewModel.onTimerTypeChosen(defaultTimerInfo[timerType]!!, open) }) { | ||||
|                 val default: TimerInfo = defaultTimerInfo.getValue(timerType) | ||||
|                 Button(onClick = { viewModel.onTimerTypeChosen(default, open) }) { | ||||
|                     Text(text = timerType.name) | ||||
|                 } | ||||
|             } | ||||
|  | @ -1,25 +1,22 @@ | |||
| package be.ugent.sel.studeez.screens.timer_add | ||||
| package be.ugent.sel.studeez.screens.timer_form.timer_type_select | ||||
| 
 | ||||
| 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) | ||||
|         open(StudeezDestinations.ADD_TIMER_SCREEN) | ||||
|     } | ||||
| } | ||||
|  | @ -25,7 +25,7 @@ data class TimerOverviewActions( | |||
|     val getUserTimers: () -> Flow<List<TimerInfo>>, | ||||
|     val getDefaultTimers: () -> List<TimerInfo>, | ||||
|     val onEditClick: (TimerInfo) -> Unit, | ||||
|     val onAddClick: () -> Unit, | ||||
|     val onAddClick: () -> Unit | ||||
| ) | ||||
| 
 | ||||
| fun getTimerOverviewActions( | ||||
|  | @ -36,7 +36,7 @@ fun getTimerOverviewActions( | |||
|         getUserTimers = viewModel::getUserTimers, | ||||
|         getDefaultTimers = viewModel::getDefaultTimers, | ||||
|         onEditClick = { viewModel.update(it, open) }, | ||||
|         onAddClick = { viewModel.create(open) } | ||||
|         onAddClick = { viewModel.onAddClick(open) } | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
|  | @ -48,14 +48,14 @@ fun TimerOverviewRoute( | |||
| ) { | ||||
|     TimerOverviewScreen( | ||||
|         timerOverviewActions = getTimerOverviewActions(viewModel, open), | ||||
|         drawerActions = drawerActions | ||||
|         drawerActions = drawerActions, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun TimerOverviewScreen( | ||||
|     timerOverviewActions: TimerOverviewActions, | ||||
|     drawerActions: DrawerActions | ||||
|     drawerActions: DrawerActions, | ||||
| ) { | ||||
| 
 | ||||
|     val timers = timerOverviewActions.getUserTimers().collectAsState(initial = emptyList()) | ||||
|  |  | |||
|  | @ -32,8 +32,8 @@ class TimerOverviewViewModel @Inject constructor( | |||
|         open(StudeezDestinations.TIMER_EDIT_SCREEN) | ||||
|     } | ||||
| 
 | ||||
|     fun create(open: (String) -> Unit) { | ||||
|         open(StudeezDestinations.ADD_TIMER_SCREEN) | ||||
|     fun onAddClick(open: (String) -> Unit) { | ||||
|         open(StudeezDestinations.TIMER_TYPE_CHOOSING_SCREEN) | ||||
|     } | ||||
| 
 | ||||
|     fun delete(timerInfo: TimerInfo) =timerDAO.deleteTimer(timerInfo) | ||||
|  |  | |||
|  | @ -1,12 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.timer_overview.add_timer | ||||
| 
 | ||||
| data class AddTimerUiState( | ||||
|     val studyTimeHours: Int = 1, | ||||
|     val studyTimeMinutes: Int = 0, | ||||
|     val withBreaks: Boolean = false, | ||||
|     val breakTimeMinutes: Int = 5, | ||||
|     val breakTimeHours: Int = 0, | ||||
|     val repeats: Int = 1, | ||||
|     val name: String = "Timer", | ||||
|     val description: String = "Long study session", | ||||
| ) | ||||
|  | @ -1,91 +0,0 @@ | |||
| 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.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 AddTimerViewModel @Inject constructor( | ||||
|     logService: LogService, | ||||
|     private val timerDAO: TimerDAO, | ||||
| ): StudeezViewModel(logService) { | ||||
|     var uiState = mutableStateOf(AddTimerUiState()) | ||||
|         private set | ||||
| 
 | ||||
|     private val studyTimeHours | ||||
|         get() = uiState.value.studyTimeHours | ||||
| 
 | ||||
|     private val studyTimeMinutes | ||||
|         get() = uiState.value.studyTimeMinutes | ||||
| 
 | ||||
|     private val breakTimeHours | ||||
|         get() = uiState.value.breakTimeHours | ||||
| 
 | ||||
|     private val breakTimeMinutes | ||||
|         get() = uiState.value.breakTimeMinutes | ||||
| 
 | ||||
|     private val repeats | ||||
|         get() = uiState.value.repeats | ||||
| 
 | ||||
|     private val name | ||||
|         get() = uiState.value.name | ||||
| 
 | ||||
|     private val description | ||||
|         get() = uiState.value.description | ||||
| 
 | ||||
|     fun onStudyTimeHoursChange(newValue: Int) { | ||||
|         uiState.value = uiState.value.copy(studyTimeHours = newValue) | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     fun onStudyTimeMinutesChange(newValue: Int) { | ||||
|         uiState.value = uiState.value.copy(studyTimeMinutes = newValue) | ||||
|     } | ||||
| 
 | ||||
|     fun onWithBreaksChange() { | ||||
|         uiState.value = uiState.value.copy(withBreaks = !uiState.value.withBreaks) | ||||
|     } | ||||
| 
 | ||||
|     fun onBreakTimeHourChange(newValue: Int) { | ||||
|         uiState.value = uiState.value.copy(breakTimeHours = newValue) | ||||
|     } | ||||
| 
 | ||||
|     fun onBreakTimeMinutesChange(newValue: Int) { | ||||
|         uiState.value = uiState.value.copy(breakTimeMinutes = newValue) | ||||
|     } | ||||
| 
 | ||||
|     fun onRepeatsChange(newValue: Int) { | ||||
|         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 * 60 * 60 + studyTimeMinutes * 60, | ||||
|                 breakTime = breakTimeHours * 60 * 60 + breakTimeMinutes * 60, | ||||
|                 repeats = repeats | ||||
|             )) | ||||
|         } else { | ||||
|             timerDAO.saveTimer(CustomTimerInfo( | ||||
|                 name = uiState.value.name, | ||||
|                 description = uiState.value.description, | ||||
|                 studyTime = studyTimeHours * 60 * 60 + studyTimeMinutes * 60 | ||||
|             )) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun onNameChange(newValue: String) { | ||||
|         uiState.value = uiState.value.copy(name = newValue) | ||||
|     } | ||||
| 
 | ||||
|     fun onDescriptionChange(newValue: String) { | ||||
|         uiState.value = uiState.value.copy(description = newValue) | ||||
|     } | ||||
| } | ||||
|  | @ -1,274 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.timer_overview.add_timer | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.Arrangement | ||||
| 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.Button | ||||
| import androidx.compose.material.Checkbox | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material.TextField | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.Color | ||||
| import androidx.compose.ui.res.stringResource | ||||
| 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.navbar.BasicTimePicker | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.resources | ||||
| import be.ugent.sel.studeez.ui.theme.StudeezTheme | ||||
| 
 | ||||
| data class AddTimerActions( | ||||
|     val open: (String) -> Unit, | ||||
|     val goBack: () -> Unit, | ||||
|     val onStudyTimeHoursChange: (Int) -> Unit, | ||||
|     val onStudyTimeMinutesChange: (Int) -> Unit, | ||||
|     val onBreakTimeHourChange: (Int) -> Unit, | ||||
|     val onBreakTimeMinutesChange: (Int) -> Unit, | ||||
|     val onRepeatsChange: (Int) -> Unit, | ||||
|     val onWithBreaksChange: () -> Unit, | ||||
|     val addTimer: () -> Unit, | ||||
|     val onNameChange: (String) -> Unit, | ||||
|     val onDescriptionChange: (String) -> Unit, | ||||
| ) | ||||
| 
 | ||||
| fun getAddTimerActions( | ||||
|     open: (String) -> Unit, | ||||
|     goBack: () -> Unit, | ||||
|     viewModel: AddTimerViewModel, | ||||
| ): AddTimerActions { | ||||
|     return AddTimerActions( | ||||
|         open = open, | ||||
|         goBack = goBack, | ||||
|         onWithBreaksChange = viewModel::onWithBreaksChange, | ||||
|         onStudyTimeHoursChange = viewModel::onStudyTimeHoursChange, | ||||
|         onStudyTimeMinutesChange = viewModel::onStudyTimeMinutesChange, | ||||
|         onBreakTimeHourChange = viewModel::onBreakTimeHourChange, | ||||
|         onBreakTimeMinutesChange = viewModel::onBreakTimeMinutesChange, | ||||
|         onRepeatsChange = viewModel::onRepeatsChange, | ||||
|         addTimer = viewModel::addTimer, | ||||
|         onNameChange = viewModel::onNameChange, | ||||
|         onDescriptionChange = viewModel::onDescriptionChange | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun AddTimerRoute( | ||||
|     open: (String) -> Unit, | ||||
|     goBack: () -> Unit, | ||||
|     viewModel: AddTimerViewModel, | ||||
| ) { | ||||
|     val uiState by viewModel.uiState | ||||
| 
 | ||||
|     AddTimerScreen( | ||||
|         addTimerActions = getAddTimerActions( | ||||
|             open = open, | ||||
|             goBack = goBack, | ||||
|             viewModel = viewModel, | ||||
|         ), | ||||
|         uiState = uiState | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun AddTimerScreen( | ||||
|     addTimerActions: AddTimerActions, | ||||
|     uiState: AddTimerUiState, | ||||
| ) { | ||||
|     val mStudyTimePicker = BasicTimePicker( | ||||
|         onHoursChange = addTimerActions.onStudyTimeHoursChange, | ||||
|         onMinutesChange = addTimerActions.onStudyTimeMinutesChange, | ||||
|         Hours = uiState.studyTimeHours, | ||||
|         Minutes = uiState.studyTimeMinutes | ||||
|     ) | ||||
| 
 | ||||
|     val mBreakTimePicker = BasicTimePicker( | ||||
|         onHoursChange = addTimerActions.onBreakTimeHourChange, | ||||
|         onMinutesChange = addTimerActions.onBreakTimeMinutesChange, | ||||
|         Hours = uiState.breakTimeHours, | ||||
|         Minutes = uiState.breakTimeMinutes | ||||
|     ) | ||||
| 
 | ||||
|     SecondaryScreenTemplate( | ||||
|         title = resources().getString(R.string.add_timer), | ||||
|         popUp = addTimerActions.goBack | ||||
|     ) { | ||||
|         LazyColumn( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth() | ||||
|                 .padding(16.dp), | ||||
|             horizontalAlignment = Alignment.CenterHorizontally | ||||
|         ) { | ||||
|             item { | ||||
|                 Row( | ||||
|                     modifier = Modifier | ||||
|                         .padding(16.dp) | ||||
|                 ) { | ||||
|                     Text( | ||||
|                         text = stringResource(R.string.addTimer_question), | ||||
|                         textAlign = TextAlign.Center | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Text( | ||||
|                     text = uiState.studyTimeHours.toString() + stringResource(R.string.addTimer_studytime_1) + uiState.studyTimeMinutes + stringResource( | ||||
|                                             R.string.addTimer_studytime_2) | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Button( | ||||
|                     onClick = { | ||||
|                         mStudyTimePicker.show() | ||||
|                     }, | ||||
|                 ) { | ||||
|                     Text( | ||||
|                         text = stringResource(R.string.addTimer_timepicker), | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Row( | ||||
|                     modifier = Modifier.fillMaxWidth(), | ||||
|                     verticalAlignment = Alignment.CenterVertically, | ||||
|                     horizontalArrangement = Arrangement.Center | ||||
|                 ) { | ||||
|                     Text( | ||||
|                         text = stringResource(R.string.addTimer_break_question), | ||||
|                     ) | ||||
|                     Checkbox( | ||||
|                         checked = uiState.withBreaks, | ||||
|                         onCheckedChange = { addTimerActions.onWithBreaksChange() } | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (uiState.withBreaks) { | ||||
|                 item { | ||||
|                     Text( | ||||
|                         text = if (uiState.repeats == 1) uiState.repeats.toString() + stringResource( | ||||
|                                                     R.string.addTimer_break_1) | ||||
|                                else uiState.repeats.toString() + stringResource( | ||||
|                                                     R.string.addTimer_break_s) | ||||
|                     ) | ||||
|                     TextField( | ||||
|                         value = uiState.repeats.toString(), | ||||
|                         onValueChange = { it: String -> | ||||
|                             it.toIntOrNull()?.let { it1 -> | ||||
|                                 addTimerActions.onRepeatsChange( | ||||
|                                     kotlin.math.abs(it1) | ||||
|                                 ) | ||||
|                             } | ||||
|                         } | ||||
|                     ) | ||||
|                 } | ||||
| 
 | ||||
|                 item { | ||||
|                     Text( | ||||
|                         text = uiState.breakTimeHours.toString() + stringResource(R.string.breakTime_1) + uiState.breakTimeMinutes + stringResource( | ||||
|                                                     R.string.breakTime_2) | ||||
|                     ) | ||||
|                 } | ||||
| 
 | ||||
|                 item { | ||||
|                     Button( | ||||
|                         onClick = { | ||||
|                             mBreakTimePicker.show() | ||||
|                         }, | ||||
|                     ) { | ||||
|                         Text( | ||||
|                             text = stringResource(R.string.addTimer_timepicker), | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Text( | ||||
|                     text = stringResource(R.string.addTimer_name) | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 TextField( | ||||
|                     value = uiState.name, | ||||
|                     onValueChange = { addTimerActions.onNameChange(it) } | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 if (uiState.name == "") { | ||||
|                     Text( | ||||
|                         text = stringResource(R.string.addTimer_name_error), | ||||
|                         color = Color.Red | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 Text( | ||||
|                     text = stringResource(R.string.addTimer_description) | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 TextField( | ||||
|                     value = uiState.description, | ||||
|                     onValueChange = { addTimerActions.onDescriptionChange(it) } | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|             item { | ||||
|                 if (uiState.description == "") { | ||||
|                     Text( | ||||
|                         text = stringResource(R.string.addTimer_description_error), | ||||
|                         color = Color.Red | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             item { | ||||
|                 Row( | ||||
|                     modifier = Modifier | ||||
|                         .fillMaxWidth() | ||||
|                         .fillMaxHeight(), | ||||
|                     verticalAlignment = Alignment.Bottom, | ||||
|                     horizontalArrangement = Arrangement.Center | ||||
|                 ) { | ||||
|                     BasicButton( | ||||
|                         text = R.string.add_timer, | ||||
|                         modifier = Modifier, | ||||
|                         onClick = { | ||||
|                             if (uiState.description != "" && uiState.name != "") { | ||||
|                                 addTimerActions.addTimer() | ||||
|                                 addTimerActions.open(StudeezDestinations.TIMER_SCREEN) | ||||
|                             } | ||||
|                          } | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun AddTimerScreenPreview() { StudeezTheme { | ||||
|     AddTimerScreen( | ||||
|         addTimerActions = AddTimerActions({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}), | ||||
|         uiState = AddTimerUiState() | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -131,8 +131,13 @@ | |||
|     <string name="addTimer_studytime_2">" minutes of studytime"</string> | ||||
|     <string name="addTimer_question">How long do you want to study?</string> | ||||
| 
 | ||||
|     <!-- Timer Type Select --> | ||||
|     <string name="timer_type_select">Select Timer Type</string> | ||||
| 
 | ||||
|     <!-- Edit Timer--> | ||||
|     <string name="name">Name</string> | ||||
|     <string name="edit_timer">Edit Timer</string> | ||||
|     <string name="repeats_error">Repeats must be a positive non-zero number</string> | ||||
|     <string name="description">Description</string> | ||||
|     <string name="studyTime">Study Time</string> | ||||
|     <string name="breakTime">Break Time</string> | ||||
|  |  | |||
		Reference in a new issue
	
	 lbarraga
						lbarraga