diff --git a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt index 91cc208..7216f4f 100644 --- a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt +++ b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt @@ -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 diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/TimePickerButtonComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/TimePickerButtonComposable.kt index 02bd0d7..c5e75cc 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/TimePickerButtonComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/TimePickerButtonComposable.kt @@ -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 = 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) { + 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 = {}) + } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/EditTimerState.kt b/app/src/main/java/be/ugent/sel/studeez/data/EditTimerState.kt index 9686e94..dceec8c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/EditTimerState.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/EditTimerState.kt @@ -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 } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt index 7038c7d..7bc51f8 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt @@ -4,7 +4,7 @@ class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) { override fun tick() { if (!hasEnded()) { - time.minOne() + time-- totalStudyTime++ } } diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt index 41be874..51ee182 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt @@ -11,7 +11,7 @@ class FunctionalEndlessTimer : FunctionalTimer(0) { } override fun tick() { - time.plusOne() + time++ totalStudyTime++ } diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt index 8eeb1c6..6d4f868 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt @@ -22,7 +22,7 @@ class FunctionalPomodoroTimer( } isInBreak = !isInBreak } - time.minOne() + time-- if (!isInBreak) { totalStudyTime++ diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt index e95bbfb..1f4231a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt @@ -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 { diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/HoursMinutesSeconds.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/HoursMinutesSeconds.kt index 2f630c9..d09d8a7 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/HoursMinutesSeconds.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/HoursMinutesSeconds.kt @@ -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 } diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt index c512d96..7260faa 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt @@ -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) } - -} \ No newline at end of file +} diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt index dbbb0be..6dd6797 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt @@ -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) { diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt index b5bcfda..ef4868a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt @@ -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" diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/AbstractSessionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/AbstractSessionScreen.kt index 4c0cc3e..06a80b6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/AbstractSessionScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/AbstractSessionScreen.kt @@ -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), diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index 477d174..2d06e0b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -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() diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddScreen.kt new file mode 100644 index 0000000..7cb6a8f --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddScreen.kt @@ -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) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddViewModel.kt new file mode 100644 index 0000000..9ab766c --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddViewModel.kt @@ -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() + } + +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectScreen.kt new file mode 100644 index 0000000..d14bb86 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectScreen.kt @@ -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 = 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) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectViewModel.kt new file mode 100644 index 0000000..1892833 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectViewModel.kt @@ -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) + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/GetTimerEditScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/GetTimerEditScreen.kt index c6579e8..b22b775 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/GetTimerEditScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/GetTimerEditScreen.kt @@ -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 { - - @SuppressLint("ComposableNaming") - override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo) { +class GetTimerEditScreen: TimerInfoVisitor { + 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) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditScreen.kt index ac1ff8a..649caf6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditScreen.kt @@ -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) + } + } +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditViewModel.kt index 20f5952..3258f24 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditViewModel.kt @@ -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() + } + } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/AbstractTimerEditScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/AbstractTimerEditScreen.kt index 59b04e7..898492e 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/AbstractTimerEditScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/AbstractTimerEditScreen.kt @@ -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 { } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/BreakTimerEditScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/BreakTimerEditScreen.kt index 1405682..b6104b6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/BreakTimerEditScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/BreakTimerEditScreen.kt @@ -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 = {}) + } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/CustomTimerEditScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/CustomTimerEditScreen.kt index bbe66ec..f3278d5 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/CustomTimerEditScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/CustomTimerEditScreen.kt @@ -1,4 +1,34 @@ -package be.ugent.sel.studeez.screens.timer_edit +package be.ugent.sel.studeez.screens.timer_edit.editScreens -class CustomTimerEditScreen { +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 + } + } + + +} + +@Preview +@Composable +fun CustomEditScreenPreview() { + val customTimerInfo = CustomTimerInfo("custom", "my description", 25) + StudeezTheme { + CustomTimerEditScreen(customTimerInfo).invoke(onSaveClick = {}) + } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/EndlessTimerEditScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/EndlessTimerEditScreen.kt index 5c6263d..0e26209 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/EndlessTimerEditScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/EndlessTimerEditScreen.kt @@ -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 = {}) + } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt index f5b7c3b..dd3f062 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt @@ -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>, val getDefaultTimers: () -> List, 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,34 +64,38 @@ fun TimerOverviewScreen( title = resources().getString(R.string.timers), drawerActions = drawerActions ) { - LazyColumn { - // Custom timer, select new duration each time - item { - TimerEntry(timerInfo = CustomTimerInfo( - name = resources().getString(R.string.custom_name), - description = resources().getString(R.string.custom_name), - studyTime = 0 - )) - } - // Default Timers, cannot be edited - items(timerOverviewActions.getDefaultTimers()) { - TimerEntry(timerInfo = it) {} - } - // User timers, can be edited - items(timers.value) { timerInfo -> - TimerEntry( - timerInfo = timerInfo, - ) { - StealthButton( - text = R.string.edit, - onClick = { timerOverviewActions.onEditClick(timerInfo) } - ) + Column { // TODO knop beneden + LazyColumn { + // Custom timer, select new duration each time + item { + TimerEntry(timerInfo = CustomTimerInfo( + name = resources().getString(R.string.custom_name), + description = resources().getString(R.string.custom_name), + studyTime = 0 + )) + } + // Default Timers, cannot be edited + items(timerOverviewActions.getDefaultTimers()) { + TimerEntry(timerInfo = it) {} + } + // User timers, can be edited + items(timers.value) { timerInfo -> + TimerEntry( + timerInfo = timerInfo, + ) { + StealthButton( + text = R.string.edit, + onClick = { timerOverviewActions.onEditClick(timerInfo) } + ) + } + } - } - item { - BasicButton(R.string.add_timer, Modifier.basicButton()) { - timerOverviewActions.open(StudeezDestinations.ADD_TIMER_SCREEN) + // TODO uit lazy column + item { + BasicButton(R.string.add_timer, Modifier.basicButton()) { + timerOverviewActions.onAddClick() + } } } } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewViewModel.kt index c2be1e9..77a5a6e 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewViewModel.kt @@ -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) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt index 77bdeda..dc7bbda 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt @@ -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) } } ) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt index 5ef775e..2f17e65 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt @@ -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>, 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 = {} ) } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8f02fc5..2c5ec3a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -107,7 +107,7 @@ Creating sessions still needs to be implemented. Hang on tight! - + Timer description cannot be empty! Timer description @@ -123,4 +123,11 @@ " minutes of studytime" How long do you want to study? + + Name + Description + Study Time + Break Time + Number of Repeats +