From 3fb8b08cb4b89248df6b7066f6d03dea9abf6084 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Tue, 2 May 2023 00:18:36 +0200 Subject: [PATCH 01/87] added midsection --- .../session/sessionScreens/AbstractSessionScreen.kt | 7 +++++++ 1 file changed, 7 insertions(+) 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 06a80b6..3937ab9 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 @@ -95,6 +95,8 @@ abstract class AbstractSessionScreen { fontSize = 30.sp ) + MidSection() + Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() @@ -121,6 +123,11 @@ abstract class AbstractSessionScreen { @Composable abstract fun motivationString(): String + @Composable + open fun MidSection() { + // Default has no midsection, unless overwritten. + } + abstract fun callMediaPlayer() } From 47620f69ed3a8ab18d900976336f4b0e80c1d17f Mon Sep 17 00:00:00 2001 From: lbarraga Date: Tue, 2 May 2023 00:18:59 +0200 Subject: [PATCH 02/87] added midsection implementation --- .../sessionScreens/BreakSessionScreen.kt | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt index 8fa45ff..1caeacc 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt @@ -1,7 +1,20 @@ package be.ugent.sel.studeez.screens.session.sessionScreens import android.media.MediaPlayer +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import be.ugent.sel.studeez.R import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer import be.ugent.sel.studeez.resources @@ -12,6 +25,37 @@ class BreakSessionScreen( private var mediaplayer: MediaPlayer? ): AbstractSessionScreen() { + @Composable + override fun MidSection() { + Dots() + } + + @Composable + fun Dots() { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + ) { + repeat(funPomoDoroTimer.breaksRemaining - 1) { + Dot(color = Color.DarkGray) + } + if (funPomoDoroTimer.isInBreak) Dot(Color.Green) else Dot(Color.DarkGray) + repeat(funPomoDoroTimer.repeats - funPomoDoroTimer.breaksRemaining) { + Dot(color = Color.Gray) + } + } + } + + @Composable + private fun Dot(color: Color) { + Box(modifier = Modifier + .padding(5.dp) + .size(10.dp) + .clip(CircleShape) + .background(color)) + } + @Composable override fun motivationString(): String { if (funPomoDoroTimer.isInBreak) { @@ -22,11 +66,7 @@ class BreakSessionScreen( return resources().getString(AppText.state_done) } - return resources().getQuantityString( - R.plurals.state_focus_remaining, - funPomoDoroTimer.breaksRemaining, - funPomoDoroTimer.breaksRemaining - ) + return resources().getString(AppText.state_focus) } override fun callMediaPlayer() { @@ -42,4 +82,12 @@ class BreakSessionScreen( mediaplayer?.start() } } +} + +@Preview +@Composable +fun MidsectionPreview() { + val funPomoDoroTimer = FunctionalPomodoroTimer(15, 60, 5) + val breakSessionScreen = BreakSessionScreen(funPomoDoroTimer, MediaPlayer()) + breakSessionScreen.MidSection() } \ No newline at end of file From 173eeb10736dffaae0066e8cb02d45ab5df970ab Mon Sep 17 00:00:00 2001 From: lbarraga Date: Tue, 2 May 2023 00:19:52 +0200 Subject: [PATCH 03/87] make repeats public --- .../local/models/timer_functional/FunctionalPomodoroTimer.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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..9771bde 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 @@ -2,7 +2,8 @@ package be.ugent.sel.studeez.data.local.models.timer_functional class FunctionalPomodoroTimer( private var studyTime: Int, - private var breakTime: Int, repeats: Int + private var breakTime: Int, + val repeats: Int ) : FunctionalTimer(studyTime) { var breaksRemaining = repeats From 6fb597c7e169020d0dc904c5c2d727c289c50d30 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 2 May 2023 16:17:12 +0200 Subject: [PATCH 04/87] dots in omgekeerde volgorde --- .../screens/session/sessionScreens/BreakSessionScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt index 1caeacc..9c59b46 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/sessionScreens/BreakSessionScreen.kt @@ -37,11 +37,11 @@ class BreakSessionScreen( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { - repeat(funPomoDoroTimer.breaksRemaining - 1) { + repeat(funPomoDoroTimer.repeats - funPomoDoroTimer.breaksRemaining) { Dot(color = Color.DarkGray) } - if (funPomoDoroTimer.isInBreak) Dot(Color.Green) else Dot(Color.DarkGray) - repeat(funPomoDoroTimer.repeats - funPomoDoroTimer.breaksRemaining) { + if (!funPomoDoroTimer.isInBreak) Dot(Color.Green) else Dot(Color.DarkGray) + repeat(funPomoDoroTimer.breaksRemaining - 1) { Dot(color = Color.Gray) } } From 968842609382d5f1269e919dd57b7f6bdce5841f Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 10:27:20 +0200 Subject: [PATCH 05/87] intermediate type select screen for add and route to edit instead of add --- app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt | 8 ++++++++ .../ugent/sel/studeez/navigation/StudeezDestinations.kt | 1 + .../studeez/screens/timer_overview/TimerOverviewScreen.kt | 8 ++++---- .../screens/timer_overview/TimerOverviewViewModel.kt | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) 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 7216f4f..f8c5572 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_add.TimerTypeSelectScreen 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 @@ -183,6 +184,13 @@ fun StudeezNavGraph( ) } + composable(StudeezDestinations.TIMER_TYPE_CHOOSING_SCREEN) { + TimerTypeSelectScreen( + open = open, + popUp = goBack + ) + } + composable(StudeezDestinations.SESSION_SCREEN) { SessionRoute( open, 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 ef4868a..999ece1 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 @@ -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" 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 dd3f062..a07dd67 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 @@ -25,7 +25,7 @@ data class TimerOverviewActions( val getUserTimers: () -> Flow>, val getDefaultTimers: () -> List, 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()) 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 77a5a6e..3e10053 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 @@ -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) From 61b3c8714239129e85a00344376e9ac0faae2b42 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 10:29:34 +0200 Subject: [PATCH 06/87] forgot to remove 20 labels test --- .../editScreens/AbstractTimerEditScreen.kt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) 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 898492e..c4ec5a5 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 @@ -43,15 +43,12 @@ abstract class AbstractTimerEditScreen(private val timerInfo: TimerInfo) { label = R.string.name ) - repeat(20) { - LabelledInputField( - value = description, - onNewValue = { description = it }, - label = R.string.description, - singleLine = false - ) - - } + LabelledInputField( + value = description, + onNewValue = { description = it }, + label = R.string.description, + singleLine = false + ) ExtraFields() From 7934154af92a1130392da58b939f155b1816b645 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 10:46:14 +0200 Subject: [PATCH 07/87] removed own add screenn (niet dat van Rune) + minor refactor --- .../screens/timer_add/TimerAddScreen.kt | 44 ------------------- .../screens/timer_add/TimerAddViewModel.kt | 29 ------------ .../timer_add/TimerTypeSelectScreen.kt | 3 +- .../timer_add/TimerTypeSelectViewModel.kt | 1 - 4 files changed, 2 insertions(+), 75 deletions(-) delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddScreen.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddViewModel.kt 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 deleted file mode 100644 index 7cb6a8f..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddScreen.kt +++ /dev/null @@ -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) - } - } -} \ 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 deleted file mode 100644 index 9ab766c..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddViewModel.kt +++ /dev/null @@ -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() - } - -} \ 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 index d14bb86..f950c23 100644 --- 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 @@ -34,7 +34,8 @@ fun TimerTypeSelectScreen( 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) } } 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 index 1892833..11b512d 100644 --- 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 @@ -13,7 +13,6 @@ import javax.inject.Inject @HiltViewModel class TimerTypeSelectViewModel @Inject constructor( private val editTimerState: EditTimerState, - private val timerDAO: TimerDAO, logService: LogService ) : StudeezViewModel(logService) { From 0b65c44da120b8a6c60f958103e91ea139894580 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 12:22:42 +0200 Subject: [PATCH 08/87] added error inputfield --- .../common/composable/TextFieldComposable.kt | 97 ++++++++++++++++++- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt index 47dbb0b..8d158be 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt @@ -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,90 @@ 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: String, + 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 = resources().getString(label)) }, + isError = !isValid, + keyboardOptions = KeyboardOptions( + keyboardType = keyboardType, + imeAction = ImeAction.Done + ) + ) + + if (!isValid) { + Text( + modifier = Modifier.padding(start = 16.dp), + text = errorText, + color = MaterialTheme.colors.error + ) + } + } +} + +fun isNumber(string: String): Boolean { + return string.matches(Regex("[1-9]+\\d*")) +} + + + + @Preview(showBackground = true) + @Composable + fun IntInputPreview() { + LabeledNumberInputField(value = 1, onNewValue = {}, label = AppText.email) + } + @Composable fun PasswordField( value: String, From 4d064ad319dc5a5ba5f1c717d54c6e4e6cc267b6 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 12:23:05 +0200 Subject: [PATCH 09/87] made repeats public --- .../studeez/data/local/models/timer_info/PomodoroTimerInfo.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6dd6797..7316630 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 @@ -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) { From 3fc3bee8c2ca617632c2ea22a13f5eaa87844287 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 12:23:26 +0200 Subject: [PATCH 10/87] added error label for breaktimeEdit --- .../editScreens/BreakTimerEditScreen.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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 b6104b6..3f4b520 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,8 +1,13 @@ package be.ugent.sel.studeez.screens.timer_edit.editScreens +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +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.LabeledErrorTextField +import be.ugent.sel.studeez.common.composable.LabeledNumberInputField 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 @@ -10,6 +15,7 @@ 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.resources import be.ugent.sel.studeez.ui.theme.StudeezTheme class BreakTimerEditScreen( @@ -26,8 +32,18 @@ class BreakTimerEditScreen( TimePickerCard(R.string.breakTime, breakTimerInfo.breakTime) { newTime -> breakTimerInfo.breakTime = newTime } - } + LabeledErrorTextField( + initialValue = breakTimerInfo.repeats.toString(), + label = R.string.repeats, + errorText = resources().getString(R.string.repeats_error), + keyboardType = KeyboardType.Decimal, + predicate = { it.matches(Regex("[1-9]+\\d*")) } + ) { correctlyTypedInt -> + breakTimerInfo.repeats = correctlyTypedInt.toInt() + } + + } } @Preview From cfb624b6b65ddb3992996d4c81b14c121884ac1a Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Thu, 4 May 2023 12:23:58 +0200 Subject: [PATCH 11/87] added error for invalid repeats --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c5ec3a..a1ea6ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -125,6 +125,7 @@ Name + Repeats must be a positive non-zero number Description Study Time Break Time From a28a425c3ccba1e7f3b7f0760af3fe1459a1013d Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 21:37:02 +0200 Subject: [PATCH 12/87] fix string resource inconsistencies --- .../common/composable/TextFieldComposable.kt | 10 +++------- .../editScreens/AbstractTimerEditScreen.kt | 3 ++- .../timer_edit/editScreens/BreakTimerEditScreen.kt | 13 +++---------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt index 8d158be..aadcee3 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/TextFieldComposable.kt @@ -119,7 +119,7 @@ fun LabeledErrorTextField( initialValue: String, @StringRes label: Int, singleLine: Boolean = false, - errorText: String, + errorText: Int, keyboardType: KeyboardType, predicate: (String) -> Boolean, onNewCorrectValue: (String) -> Unit @@ -144,7 +144,7 @@ fun LabeledErrorTextField( } }, singleLine = singleLine, - label = { Text(text = resources().getString(label)) }, + label = { Text(text = stringResource(id = label)) }, isError = !isValid, keyboardOptions = KeyboardOptions( keyboardType = keyboardType, @@ -155,17 +155,13 @@ fun LabeledErrorTextField( if (!isValid) { Text( modifier = Modifier.padding(start = 16.dp), - text = errorText, + text = stringResource(id = errorText), color = MaterialTheme.colors.error ) } } } -fun isNumber(string: String): Boolean { - return string.matches(Regex("[1-9]+\\d*")) -} - @Preview(showBackground = true) 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 c4ec5a5..6e38938 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 @@ -14,6 +14,7 @@ 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) { @@ -46,7 +47,7 @@ abstract class AbstractTimerEditScreen(private val timerInfo: TimerInfo) { LabelledInputField( value = description, onNewValue = { description = it }, - label = R.string.description, + label = AppText.description, singleLine = false ) 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 3f4b520..8b00b94 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,22 +1,15 @@ package be.ugent.sel.studeez.screens.timer_edit.editScreens -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.* -import androidx.compose.ui.Modifier 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.LabeledErrorTextField -import be.ugent.sel.studeez.common.composable.LabeledNumberInputField -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.resources import be.ugent.sel.studeez.ui.theme.StudeezTheme +import be.ugent.sel.studeez.R.string as AppText + class BreakTimerEditScreen( private val breakTimerInfo: PomodoroTimerInfo @@ -36,7 +29,7 @@ class BreakTimerEditScreen( LabeledErrorTextField( initialValue = breakTimerInfo.repeats.toString(), label = R.string.repeats, - errorText = resources().getString(R.string.repeats_error), + errorText = AppText.repeats_error, keyboardType = KeyboardType.Decimal, predicate = { it.matches(Regex("[1-9]+\\d*")) } ) { correctlyTypedInt -> From 24fe1b4f7802b0d137141561773dc8e4944c3050 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 22:54:12 +0200 Subject: [PATCH 13/87] added add screen to routes --- app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt | 5 +++-- .../be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt 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 f8c5572..402a2bc 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_add.TimerAddRoute import be.ugent.sel.studeez.screens.timer_add.TimerTypeSelectScreen import be.ugent.sel.studeez.screens.timer_edit.TimerEditRoute import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute @@ -207,9 +208,9 @@ fun StudeezNavGraph( } composable(StudeezDestinations.ADD_TIMER_SCREEN) { - AddTimerRoute( + TimerAddRoute( open = open, - goBack = goBack, + popUp = goBack, viewModel = hiltViewModel() ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt new file mode 100644 index 0000000..dbf0f30 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt @@ -0,0 +1,4 @@ +package be.ugent.sel.studeez.screens.timer_add + +class TimerAddRoute { +} \ No newline at end of file From 11e7990ee9feffddbaa67121d8724f98ecde4c63 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 22:54:51 +0200 Subject: [PATCH 14/87] added timer add route --- .../screens/timer_add/TimerAddRoute.kt | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt index dbf0f30..d656aab 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt @@ -1,4 +1,40 @@ package be.ugent.sel.studeez.screens.timer_add -class TimerAddRoute { +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import be.ugent.sel.studeez.R +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 + +data class TimerEditActions( + val getTimerInfo: () -> TimerInfo, + val saveTimer: (TimerInfo) -> Unit +) + +fun getTimerAddActions( + viewModel: TimerEditViewModel, + goBack: () -> Unit +): TimerEditActions { + return TimerEditActions( + getTimerInfo = viewModel::getTimerInfo, + saveTimer = { timerInfo -> viewModel.saveTimer(timerInfo, goBack) } + ) +} + +@Composable +fun TimerAddRoute( + open: (String) -> Unit, + popUp: () -> Unit, + viewModel: TimerEditViewModel, +) { + + val timerEditActions = getTimerAddActions(viewModel, goBack = popUp) + + SecondaryScreenTemplate(title = stringResource(id = R.string.edit_timer), popUp = popUp) { + + val timerEditScreen = timerEditActions.getTimerInfo().accept(GetTimerEditScreen()) + timerEditScreen { timerEditActions.saveTimer(it) } + } } \ No newline at end of file From b909c7dd158503de6f0f619c1c2734ab9333ef8c Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 22:55:41 +0200 Subject: [PATCH 15/87] open add route instead of edit screen --- .../sel/studeez/screens/timer_add/TimerTypeSelectViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 11b512d..58d46a1 100644 --- 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 @@ -19,6 +19,6 @@ class TimerTypeSelectViewModel @Inject constructor( fun onTimerTypeChosen(timerInfo: TimerInfo, open: (String) -> Unit) { editTimerState.timerInfo = timerInfo - open(StudeezDestinations.TIMER_EDIT_SCREEN) + open(StudeezDestinations.ADD_TIMER_SCREEN) } } \ No newline at end of file From 534a88db5d94a338a9c342d6071770e2ca2e2f61 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 22:56:26 +0200 Subject: [PATCH 16/87] changed savedTimer to editTimer --- .../studeez/screens/timer_edit/TimerEditScreen.kt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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 649caf6..68aa3a4 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,16 +1,14 @@ 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 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.screens.timer_edit.editScreens.AbstractTimerEditScreen -import be.ugent.sel.studeez.ui.theme.StudeezTheme +import be.ugent.sel.studeez.R.string as AppText data class TimerEditActions( val getTimerInfo: () -> TimerInfo, - val saveTimer: (TimerInfo, () -> Unit) -> Unit + val editTimer: (TimerInfo, () -> Unit) -> Unit ) fun getTimerEditActions( @@ -19,7 +17,7 @@ fun getTimerEditActions( ): TimerEditActions { return TimerEditActions( getTimerInfo = viewModel::getTimerInfo, - saveTimer = viewModel::saveTimer + editTimer = viewModel::editTimer ) } @@ -32,11 +30,11 @@ fun TimerEditRoute( val timerEditActions = getTimerEditActions(viewModel, open) - SecondaryScreenTemplate(title = "Edit Timer", popUp = popUp) { + SecondaryScreenTemplate(title = stringResource(id = AppText.edit_timer), popUp = popUp) { val timerEditScreen = timerEditActions.getTimerInfo().accept(GetTimerEditScreen()) timerEditScreen { timerInfo -> - timerEditActions.saveTimer(timerInfo, popUp) + timerEditActions.editTimer(timerInfo, popUp) } } } From 4015a806be7bb2dcc92b61ac3e0e9afbd503b1c9 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 22:57:31 +0200 Subject: [PATCH 17/87] saveTimer -> editTimer --- .../sel/studeez/screens/timer_edit/TimerEditViewModel.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 3258f24..b2bb172 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 @@ -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() + } } \ No newline at end of file From 165fe4ca8632a540bf463ea12798597ff58c9539 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Thu, 4 May 2023 22:58:35 +0200 Subject: [PATCH 18/87] added edit screen string --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a1ea6ef..e40ffe4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -125,6 +125,7 @@ Name + Edit Timer Repeats must be a positive non-zero number Description Study Time From 86c7a0e6a8000222dfc0b8bcccfc3311bcb0e711 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:01:01 +0200 Subject: [PATCH 19/87] *EditScreen -> *FormScreen --- .../screens/timer_add/TimerAddRoute.kt | 40 ----------- .../screens/timer_edit/TimerEditScreen.kt | 63 ----------------- .../GetTimerFormScreen.kt} | 10 +-- .../screens/timer_form/TimerFormRoute.kt | 68 +++++++++++++++++++ .../TimerFormViewModel.kt} | 2 +- .../form_screens/AbstractTimerFormScreen.kt} | 4 +- .../form_screens/BreakTimerFormScreen.kt} | 8 +-- .../form_screens/CustomTimerFormScreen.kt} | 8 +-- .../form_screens/EndlessTimerFormScreen.kt} | 8 +-- .../TimerTypeSelectScreen.kt | 2 +- .../TimerTypeSelectViewModel.kt | 2 +- 11 files changed, 90 insertions(+), 125 deletions(-) delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditScreen.kt rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_edit/GetTimerEditScreen.kt => timer_form/GetTimerFormScreen.kt} (68%) create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_edit/TimerEditViewModel.kt => timer_form/TimerFormViewModel.kt} (94%) rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_edit/editScreens/AbstractTimerEditScreen.kt => timer_form/form_screens/AbstractTimerFormScreen.kt} (94%) rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_edit/editScreens/BreakTimerEditScreen.kt => timer_form/form_screens/BreakTimerFormScreen.kt} (89%) rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_edit/editScreens/CustomTimerEditScreen.kt => timer_form/form_screens/CustomTimerFormScreen.kt} (79%) rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_edit/editScreens/EndlessTimerEditScreen.kt => timer_form/form_screens/EndlessTimerFormScreen.kt} (70%) rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_add => timer_form/timer_type_select}/TimerTypeSelectScreen.kt (96%) rename app/src/main/java/be/ugent/sel/studeez/screens/{timer_add => timer_form/timer_type_select}/TimerTypeSelectViewModel.kt (93%) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt deleted file mode 100644 index d656aab..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerAddRoute.kt +++ /dev/null @@ -1,40 +0,0 @@ -package be.ugent.sel.studeez.screens.timer_add - -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import be.ugent.sel.studeez.R -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 - -data class TimerEditActions( - val getTimerInfo: () -> TimerInfo, - val saveTimer: (TimerInfo) -> Unit -) - -fun getTimerAddActions( - viewModel: TimerEditViewModel, - goBack: () -> Unit -): TimerEditActions { - return TimerEditActions( - getTimerInfo = viewModel::getTimerInfo, - saveTimer = { timerInfo -> viewModel.saveTimer(timerInfo, goBack) } - ) -} - -@Composable -fun TimerAddRoute( - open: (String) -> Unit, - popUp: () -> Unit, - viewModel: TimerEditViewModel, -) { - - val timerEditActions = getTimerAddActions(viewModel, goBack = popUp) - - SecondaryScreenTemplate(title = stringResource(id = R.string.edit_timer), popUp = popUp) { - - val timerEditScreen = timerEditActions.getTimerInfo().accept(GetTimerEditScreen()) - timerEditScreen { timerEditActions.saveTimer(it) } - } -} \ No newline at end of file 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 deleted file mode 100644 index 68aa3a4..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditScreen.kt +++ /dev/null @@ -1,63 +0,0 @@ -package be.ugent.sel.studeez.screens.timer_edit - -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 - -data class TimerEditActions( - val getTimerInfo: () -> TimerInfo, - val editTimer: (TimerInfo, () -> Unit) -> Unit -) - -fun getTimerEditActions( - viewModel: TimerEditViewModel, - open: (String) -> Unit -): TimerEditActions { - return TimerEditActions( - getTimerInfo = viewModel::getTimerInfo, - editTimer = viewModel::editTimer - ) -} - -@Composable -fun TimerEditRoute( - open: (String) -> Unit, - popUp: () -> Unit, - viewModel: TimerEditViewModel, -) { - - val timerEditActions = getTimerEditActions(viewModel, open) - - SecondaryScreenTemplate(title = stringResource(id = AppText.edit_timer), popUp = popUp) { - - val timerEditScreen = timerEditActions.getTimerInfo().accept(GetTimerEditScreen()) - timerEditScreen { timerInfo -> - timerEditActions.editTimer(timerInfo, popUp) - } - } -} - - - - - - - - - - - - - - - - - - - - - - - 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_form/GetTimerFormScreen.kt similarity index 68% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/GetTimerEditScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/GetTimerFormScreen.kt index b22b775..8a66919 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_form/GetTimerFormScreen.kt @@ -1,13 +1,13 @@ -package be.ugent.sel.studeez.screens.timer_edit +package be.ugent.sel.studeez.screens.timer_form.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 +import be.ugent.sel.studeez.screens.timer_form.form_screens.AbstractTimerEditScreen +import be.ugent.sel.studeez.screens.timer_form.form_screens.BreakTimerEditScreen +import be.ugent.sel.studeez.screens.timer_form.form_screens.CustomTimerEditScreen +import be.ugent.sel.studeez.screens.timer_form.form_screens.EndlessTimerEditScreen class GetTimerEditScreen: TimerInfoVisitor { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt new file mode 100644 index 0000000..607116f --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt @@ -0,0 +1,68 @@ +package be.ugent.sel.studeez.screens.timer_form.timer_edit + +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.screens.timer_form.GetTimerFormScreen +import be.ugent.sel.studeez.screens.timer_form.TimerFormViewModel +import java.util.Timer +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 timerEditScreen = getTimerInfo().accept(GetTimerFormScreen()) + + SecondaryScreenTemplate(title = stringResource(id = label), popUp = popUp) { + timerEditScreen(onConfirmClick) + } +} + + + + + + + + + + + + + + + + + + + + + + + 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_form/TimerFormViewModel.kt similarity index 94% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/TimerEditViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt index b2bb172..4b9a24c 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_form/TimerFormViewModel.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.timer_edit +package be.ugent.sel.studeez.screens.timer_form.timer_edit import be.ugent.sel.studeez.data.EditTimerState import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo 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_form/form_screens/AbstractTimerFormScreen.kt similarity index 94% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/AbstractTimerEditScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/AbstractTimerFormScreen.kt index 6e38938..44043ed 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_form/form_screens/AbstractTimerFormScreen.kt @@ -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 @@ -16,7 +16,7 @@ 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) { 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_form/form_screens/BreakTimerFormScreen.kt similarity index 89% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/BreakTimerEditScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/BreakTimerFormScreen.kt index 8b00b94..12d07a4 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_form/form_screens/BreakTimerFormScreen.kt @@ -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.text.input.KeyboardType @@ -11,9 +11,9 @@ 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() { @@ -50,6 +50,6 @@ fun BreakEditScreenPreview() { 5 ) StudeezTheme { - BreakTimerEditScreen(pomodoroTimerInfo).invoke(onSaveClick = {}) + BreakTimerFormScreen(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_form/form_screens/CustomTimerFormScreen.kt similarity index 79% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/CustomTimerEditScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/CustomTimerFormScreen.kt index f3278d5..27c0657 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_form/form_screens/CustomTimerFormScreen.kt @@ -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 = {}) } } \ 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_form/form_screens/EndlessTimerFormScreen.kt similarity index 70% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_edit/editScreens/EndlessTimerEditScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/EndlessTimerFormScreen.kt index 0e26209..9009fff 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_form/form_screens/EndlessTimerFormScreen.kt @@ -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 = {}) } } \ 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_form/timer_type_select/TimerTypeSelectScreen.kt similarity index 96% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt index f950c23..197f10c 100644 --- 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_form/timer_type_select/TimerTypeSelectScreen.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.timer_add +package be.ugent.sel.studeez.screens.timer_form.timer_add import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth 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_form/timer_type_select/TimerTypeSelectViewModel.kt similarity index 93% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_add/TimerTypeSelectViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt index 58d46a1..d2f048b 100644 --- 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_form/timer_type_select/TimerTypeSelectViewModel.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.timer_add +package be.ugent.sel.studeez.screens.timer_form.timer_add import be.ugent.sel.studeez.data.EditTimerState import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo From 853a2d8c285ac5e4ed41b24b2c48d87df3329202 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:03:05 +0200 Subject: [PATCH 20/87] select timer type string resource and package refactor --- .../timer_form/timer_type_select/TimerTypeSelectScreen.kt | 8 +++++--- .../timer_type_select/TimerTypeSelectViewModel.kt | 4 +--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt index 197f10c..fa8d650 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectScreen.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.timer_form.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 = mapOf( CUSTOM to CustomTimerInfo("", "", 0), - BREAK to PomodoroTimerInfo("", "", 0, 0, 0), + BREAK to PomodoroTimerInfo("", "", 0, 0, 1), ENDLESS to EndlessTimerInfo("", ""), ) @@ -28,7 +30,7 @@ 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() diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt index d2f048b..569a36c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt @@ -1,13 +1,11 @@ -package be.ugent.sel.studeez.screens.timer_form.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 From 7f615c94a1b9733f65a26bf5b8b274150ecaa584 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:03:53 +0200 Subject: [PATCH 21/87] GetTimerEditScreen -> GetTimerFormScreen --- .../screens/timer_form/GetTimerFormScreen.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/GetTimerFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/GetTimerFormScreen.kt index 8a66919..99426e4 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/GetTimerFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/GetTimerFormScreen.kt @@ -1,26 +1,26 @@ -package be.ugent.sel.studeez.screens.timer_form.timer_edit +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.AbstractTimerEditScreen -import be.ugent.sel.studeez.screens.timer_form.form_screens.BreakTimerEditScreen -import be.ugent.sel.studeez.screens.timer_form.form_screens.CustomTimerEditScreen -import be.ugent.sel.studeez.screens.timer_form.form_screens.EndlessTimerEditScreen +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 GetTimerEditScreen: TimerInfoVisitor { +class GetTimerFormScreen: TimerInfoVisitor { - override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerEditScreen { - return CustomTimerEditScreen(customTimerInfo) + override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerFormScreen { + return CustomTimerFormScreen(customTimerInfo) } - override fun visitEndlessTimerInfo(endlessTimerInfo: EndlessTimerInfo): AbstractTimerEditScreen { - return EndlessTimerEditScreen(endlessTimerInfo) + override fun visitEndlessTimerInfo(endlessTimerInfo: EndlessTimerInfo): AbstractTimerFormScreen { + return EndlessTimerFormScreen(endlessTimerInfo) } - override fun visitBreakTimerInfo(pomodoroTimerInfo: PomodoroTimerInfo): AbstractTimerEditScreen { - return BreakTimerEditScreen(pomodoroTimerInfo) + override fun visitBreakTimerInfo(pomodoroTimerInfo: PomodoroTimerInfo): AbstractTimerFormScreen { + return BreakTimerFormScreen(pomodoroTimerInfo) } From 51af1f576625818eadf7a6e8776609eb648d6827 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:04:52 +0200 Subject: [PATCH 22/87] edit route en add route staan in dezelfde TimerFormRoute File --- .../sel/studeez/screens/timer_form/TimerFormRoute.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt index 607116f..7ad21fa 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt @@ -1,13 +1,10 @@ -package be.ugent.sel.studeez.screens.timer_form.timer_edit +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.screens.timer_form.GetTimerFormScreen -import be.ugent.sel.studeez.screens.timer_form.TimerFormViewModel -import java.util.Timer import be.ugent.sel.studeez.R.string as AppText @Composable @@ -37,10 +34,10 @@ fun TimerFormScreen( @StringRes label: Int, onConfirmClick: (TimerInfo) -> Unit ) { - val timerEditScreen = getTimerInfo().accept(GetTimerFormScreen()) + val timerFormScreen = getTimerInfo().accept(GetTimerFormScreen()) SecondaryScreenTemplate(title = stringResource(id = label), popUp = popUp) { - timerEditScreen(onConfirmClick) + timerFormScreen(onConfirmClick) } } From 2556e1c658c759473b87860b10fc6b2693f89b68 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:05:27 +0200 Subject: [PATCH 23/87] TimerFormViewModel ipv TimerEditViewModel --- .../sel/studeez/screens/timer_form/TimerFormViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt index 4b9a24c..4c2079c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.timer_form.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 From 6144afe03f2bbf988baa98618fada29c78539a5e Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:06:13 +0200 Subject: [PATCH 24/87] TimerEditRoute en TimerAddRoute staan op andere plaatsen --- app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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 402a2bc..c002c61 100644 --- a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt +++ b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt @@ -32,11 +32,10 @@ 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_add.TimerAddRoute -import be.ugent.sel.studeez.screens.timer_add.TimerTypeSelectScreen -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 @@ -209,7 +208,6 @@ fun StudeezNavGraph( composable(StudeezDestinations.ADD_TIMER_SCREEN) { TimerAddRoute( - open = open, popUp = goBack, viewModel = hiltViewModel() ) @@ -217,7 +215,6 @@ fun StudeezNavGraph( composable(StudeezDestinations.TIMER_EDIT_SCREEN) { TimerEditRoute( - open = open, popUp = goBack, viewModel = hiltViewModel() ) From d087783e12b4514054224c4a5268bc952bef1ab8 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:06:50 +0200 Subject: [PATCH 25/87] timer type select resource --- app/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e40ffe4..263dc69 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -123,6 +123,9 @@ " minutes of studytime" How long do you want to study? + + Select Timer Type + Name Edit Timer From 0b1ff3f02dfa8fed23ddd16fa42d48a83ebaf86f Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 00:09:52 +0200 Subject: [PATCH 26/87] removed previous add screen --- .../add_timer/AddTimerUiState.kt | 12 - .../add_timer/AddTimerViewModel.kt | 91 ------ .../add_timer/addTimerScreen.kt | 274 ------------------ 3 files changed, 377 deletions(-) delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt deleted file mode 100644 index fcfa79a..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt +++ /dev/null @@ -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", -) \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt deleted file mode 100644 index d507974..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt +++ /dev/null @@ -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) - } -} 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 deleted file mode 100644 index dc7bbda..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt +++ /dev/null @@ -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() - ) - } -} From 620722038d0733b15f58953bd6cce875a025afbb Mon Sep 17 00:00:00 2001 From: lbarraga Date: Fri, 5 May 2023 08:27:10 +0200 Subject: [PATCH 27/87] Update app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt Co-authored-by: Tibo De Peuter --- .../screens/timer_form/TimerFormRoute.kt | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt index 7ad21fa..0323dc2 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt @@ -40,26 +40,3 @@ fun TimerFormScreen( timerFormScreen(onConfirmClick) } } - - - - - - - - - - - - - - - - - - - - - - - From 47edf650ed74f2fb63679f17a01aa464df150b53 Mon Sep 17 00:00:00 2001 From: Rune Dyselinck Date: Fri, 5 May 2023 10:48:34 +0200 Subject: [PATCH 28/87] testen gefixt --- .../studeez/timer_functional/TimeUnitTest.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt index 86fdce8..0d9bf4b 100644 --- a/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt @@ -10,7 +10,7 @@ class TimeUnitTest { private val hours = 4 private val minutes = 20 private val seconds = 39 - private val time: Time = Time(seconds + minutes * 60 + hours * 60 * 60) + private var time: Time = Time(seconds + minutes * 60 + hours * 60 * 60) @Before fun setup() { @@ -21,9 +21,9 @@ class TimeUnitTest { fun formatTime() { Assert.assertEquals( HoursMinutesSeconds( - hours.toString().padStart(2, '0'), - minutes.toString().padStart(2, '0'), - seconds.toString().padStart(2, '0'), + hours, + minutes, + seconds, ), time.getAsHMS(), ) @@ -39,7 +39,11 @@ class TimeUnitTest { @Test fun minOne() { - time.minOne() + Assert.assertEquals( + (seconds + minutes * 60 + hours * 60 * 60), + time.time, + ) + time-- Assert.assertEquals( (seconds + minutes * 60 + hours * 60 * 60) - 1, time.time, @@ -48,7 +52,7 @@ class TimeUnitTest { @Test fun plusOne() { - time.plusOne() + time++ Assert.assertEquals( (seconds + minutes * 60 + hours * 60 * 60) + 1, time.time, @@ -59,7 +63,7 @@ class TimeUnitTest { fun minMultiple() { val n = 10 for (i in 1 .. n) { - time.minOne() + time-- } Assert.assertEquals( (seconds + minutes * 60 + hours * 60 * 60) - n, @@ -71,7 +75,7 @@ class TimeUnitTest { fun plusMultiple() { val n = 10 for (i in 1 .. n) { - time.plusOne() + time++ } Assert.assertEquals( (seconds + minutes * 60 + hours * 60 * 60) + n, From f7a3d68c3e6a782427a70950fff501e4658ad7f9 Mon Sep 17 00:00:00 2001 From: brreynie Date: Fri, 5 May 2023 11:10:59 +0200 Subject: [PATCH 29/87] extract StudeezNavGraph out of StudeezApp --- .../java/be/ugent/sel/studeez/StudeezApp.kt | 243 +----------------- .../sel/studeez/navigation/StudeezNavGraph.kt | 238 +++++++++++++++++ 2 files changed, 240 insertions(+), 241 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt 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 11454ff..c3d1634 100644 --- a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt +++ b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt @@ -2,56 +2,19 @@ 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.material.* 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.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import be.ugent.sel.studeez.common.composable.drawer.DrawerActions -import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel -import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions -import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions -import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel -import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions import be.ugent.sel.studeez.common.snackbar.SnackbarManager -import be.ugent.sel.studeez.navigation.StudeezDestinations -import be.ugent.sel.studeez.screens.home.HomeRoute -import be.ugent.sel.studeez.screens.log_in.LoginRoute -import be.ugent.sel.studeez.screens.profile.EditProfileRoute -import be.ugent.sel.studeez.screens.profile.ProfileRoute -import be.ugent.sel.studeez.screens.session.SessionRoute -import be.ugent.sel.studeez.screens.session_recap.SessionRecapRoute -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.tasks.SubjectRoute -import be.ugent.sel.studeez.screens.tasks.TaskRoute -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_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.navigation.StudeezNavGraph import be.ugent.sel.studeez.ui.theme.StudeezTheme import kotlinx.coroutines.CoroutineScope @@ -97,205 +60,3 @@ fun resources(): Resources { LocalConfiguration.current return LocalContext.current.resources } - -@Composable -fun StudeezNavGraph( - appState: StudeezAppstate, - modifier: Modifier = Modifier, -) { - val drawerViewModel: DrawerViewModel = hiltViewModel() - val navBarViewModel: NavigationBarViewModel = hiltViewModel() - - val backStackEntry by appState.navController.currentBackStackEntryAsState() - val getCurrentScreen: () -> String? = { backStackEntry?.destination?.route } - - val goBack: () -> Unit = { appState.popUp() } - val open: (String) -> Unit = { appState.navigate(it) } - val openAndPopUp: (String, String) -> Unit = - { route, popUp -> appState.navigateAndPopUp(route, popUp) } - - val drawerActions: DrawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp) - val navigationBarActions: NavigationBarActions = - getNavigationBarActions(navBarViewModel, open, getCurrentScreen) - - NavHost( - navController = appState.navController, - startDestination = StudeezDestinations.SPLASH_SCREEN, - modifier = modifier, - ) { - // NavBar - composable(StudeezDestinations.HOME_SCREEN) { - HomeRoute( - open, - viewModel = hiltViewModel(), - drawerActions = drawerActions, - navigationBarActions = navigationBarActions - ) - } - - composable(StudeezDestinations.SUBJECT_SCREEN) { - SubjectRoute( - open = open, - viewModel = hiltViewModel(), - drawerActions = drawerActions, - navigationBarActions = navigationBarActions, - ) - } - - composable(StudeezDestinations.ADD_SUBJECT_FORM) { - SubjectAddRoute( - goBack = goBack, - openAndPopUp = openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.EDIT_SUBJECT_FORM) { - SubjectEditRoute( - goBack = goBack, - openAndPopUp = openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.TASKS_SCREEN) { - TaskRoute( - goBack = goBack, - open = open, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.ADD_TASK_FORM) { - TaskAddRoute( - goBack = goBack, - openAndPopUp = openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.EDIT_TASK_FORM) { - TaskEditRoute( - goBack = goBack, - openAndPopUp = openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - - composable(StudeezDestinations.SESSIONS_SCREEN) { - SessionsRoute( - drawerActions = drawerActions, - navigationBarActions = navigationBarActions - ) - } - - composable(StudeezDestinations.PROFILE_SCREEN) { - ProfileRoute( - open, - viewModel = hiltViewModel(), - drawerActions = drawerActions, - navigationBarActions = navigationBarActions, - ) - } - - // Drawer - composable(StudeezDestinations.TIMER_SCREEN) { - TimerOverviewRoute( - viewModel = hiltViewModel(), - drawerActions = drawerActions, - open = open - ) - } - - composable(StudeezDestinations.SETTINGS_SCREEN) { - SettingsRoute( - drawerActions = drawerActions - ) - } - - // Login flow - composable(StudeezDestinations.SPLASH_SCREEN) { - SplashRoute( - openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.LOGIN_SCREEN) { - LoginRoute( - openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.SIGN_UP_SCREEN) { - SignUpRoute( - openAndPopUp, - viewModel = hiltViewModel(), - ) - } - - // Studying flow - composable(StudeezDestinations.TIMER_SELECTION_SCREEN) { - TimerSelectionRoute( - open, - goBack, - viewModel = hiltViewModel(), - ) - } - - composable(StudeezDestinations.SESSION_SCREEN) { - SessionRoute( - open, - openAndPopUp, - viewModel = hiltViewModel() - ) - } - - composable(StudeezDestinations.SESSION_RECAP) { - SessionRecapRoute( - openAndPopUp = openAndPopUp, - viewModel = hiltViewModel() - ) - } - - composable(StudeezDestinations.ADD_TIMER_SCREEN) { - AddTimerRoute( - open = open, - goBack = goBack, - viewModel = hiltViewModel() - ) - } - - composable(StudeezDestinations.TIMER_EDIT_SCREEN) { - TimerEditRoute( - open = open, - popUp = goBack, - viewModel = hiltViewModel() - ) - } - - // Friends flow - composable(StudeezDestinations.SEARCH_FRIENDS_SCREEN) { - // TODO - } - - // Create & edit screens - composable(StudeezDestinations.CREATE_TASK_SCREEN) { - // TODO - } - - composable(StudeezDestinations.CREATE_SESSION_SCREEN) { - // TODO - } - - composable(StudeezDestinations.EDIT_PROFILE_SCREEN) { - EditProfileRoute( - goBack, - openAndPopUp, - viewModel = hiltViewModel(), - ) - } - } -} diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt new file mode 100644 index 0000000..8ac135e --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt @@ -0,0 +1,238 @@ +package be.ugent.sel.studeez.navigation + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import be.ugent.sel.studeez.StudeezAppstate +import be.ugent.sel.studeez.common.composable.drawer.DrawerActions +import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel +import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions +import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions +import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel +import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions +import be.ugent.sel.studeez.screens.home.HomeRoute +import be.ugent.sel.studeez.screens.log_in.LoginRoute +import be.ugent.sel.studeez.screens.profile.EditProfileRoute +import be.ugent.sel.studeez.screens.profile.ProfileRoute +import be.ugent.sel.studeez.screens.session.SessionRoute +import be.ugent.sel.studeez.screens.session_recap.SessionRecapRoute +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.tasks.SubjectRoute +import be.ugent.sel.studeez.screens.tasks.TaskRoute +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_overview.TimerOverviewRoute +import be.ugent.sel.studeez.screens.timer_overview.add_timer.AddTimerRoute +import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute + +@Composable +fun StudeezNavGraph( + appState: StudeezAppstate, + modifier: Modifier = Modifier, +) { + val drawerViewModel: DrawerViewModel = hiltViewModel() + val navBarViewModel: NavigationBarViewModel = hiltViewModel() + + val backStackEntry by appState.navController.currentBackStackEntryAsState() + val getCurrentScreen: () -> String? = { backStackEntry?.destination?.route } + + val goBack: () -> Unit = { appState.popUp() } + val open: (String) -> Unit = { appState.navigate(it) } + val openAndPopUp: (String, String) -> Unit = + { route, popUp -> appState.navigateAndPopUp(route, popUp) } + + val drawerActions: DrawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp) + val navigationBarActions: NavigationBarActions = + getNavigationBarActions(navBarViewModel, open, getCurrentScreen) + + NavHost( + navController = appState.navController, + startDestination = StudeezDestinations.SPLASH_SCREEN, + modifier = modifier, + ) { + // NavBar + composable(StudeezDestinations.HOME_SCREEN) { + HomeRoute( + open, + viewModel = hiltViewModel(), + drawerActions = drawerActions, + navigationBarActions = navigationBarActions + ) + } + + composable(StudeezDestinations.SUBJECT_SCREEN) { + SubjectRoute( + open = open, + viewModel = hiltViewModel(), + drawerActions = drawerActions, + navigationBarActions = navigationBarActions, + ) + } + + composable(StudeezDestinations.ADD_SUBJECT_FORM) { + SubjectAddRoute( + goBack = goBack, + openAndPopUp = openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.EDIT_SUBJECT_FORM) { + SubjectEditRoute( + goBack = goBack, + openAndPopUp = openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.TASKS_SCREEN) { + TaskRoute( + goBack = goBack, + open = open, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.ADD_TASK_FORM) { + TaskAddRoute( + goBack = goBack, + openAndPopUp = openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.EDIT_TASK_FORM) { + TaskEditRoute( + goBack = goBack, + openAndPopUp = openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + + composable(StudeezDestinations.SESSIONS_SCREEN) { + SessionsRoute( + drawerActions = drawerActions, + navigationBarActions = navigationBarActions + ) + } + + composable(StudeezDestinations.PROFILE_SCREEN) { + ProfileRoute( + open, + viewModel = hiltViewModel(), + drawerActions = drawerActions, + navigationBarActions = navigationBarActions, + ) + } + + // Drawer + composable(StudeezDestinations.TIMER_SCREEN) { + TimerOverviewRoute( + viewModel = hiltViewModel(), + drawerActions = drawerActions, + open = open + ) + } + + composable(StudeezDestinations.SETTINGS_SCREEN) { + SettingsRoute( + drawerActions = drawerActions + ) + } + + // Login flow + composable(StudeezDestinations.SPLASH_SCREEN) { + SplashRoute( + openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.LOGIN_SCREEN) { + LoginRoute( + openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.SIGN_UP_SCREEN) { + SignUpRoute( + openAndPopUp, + viewModel = hiltViewModel(), + ) + } + + // Studying flow + composable(StudeezDestinations.TIMER_SELECTION_SCREEN) { + TimerSelectionRoute( + open, + goBack, + viewModel = hiltViewModel(), + ) + } + + composable(StudeezDestinations.SESSION_SCREEN) { + SessionRoute( + open, + openAndPopUp, + viewModel = hiltViewModel() + ) + } + + composable(StudeezDestinations.SESSION_RECAP) { + SessionRecapRoute( + openAndPopUp = openAndPopUp, + viewModel = hiltViewModel() + ) + } + + composable(StudeezDestinations.ADD_TIMER_SCREEN) { + AddTimerRoute( + open = open, + goBack = goBack, + viewModel = hiltViewModel() + ) + } + + composable(StudeezDestinations.TIMER_EDIT_SCREEN) { + TimerEditRoute( + open = open, + popUp = goBack, + viewModel = hiltViewModel() + ) + } + + // Friends flow + composable(StudeezDestinations.SEARCH_FRIENDS_SCREEN) { + // TODO + } + + // Create & edit screens + composable(StudeezDestinations.CREATE_TASK_SCREEN) { + // TODO + } + + composable(StudeezDestinations.CREATE_SESSION_SCREEN) { + // TODO + } + + composable(StudeezDestinations.EDIT_PROFILE_SCREEN) { + EditProfileRoute( + goBack, + openAndPopUp, + viewModel = hiltViewModel(), + ) + } + } +} From 1eff33a6db0c5d101f9d54d3046cf14e4e5bfb3e Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 09:37:07 +0200 Subject: [PATCH 30/87] start task now goes to timer selection screen --- .../sel/studeez/common/composable/tasks/TaskEntry.kt | 8 +++++--- .../ugent/sel/studeez/screens/session/SessionViewModel.kt | 7 +++++-- .../java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt | 6 +++++- .../be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt | 7 +++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt index fefb924..bf3a7cf 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt @@ -32,6 +32,7 @@ fun TaskEntry( task: Task, onCheckTask: (Boolean) -> Unit, onDeleteTask: () -> Unit, + onStartTask: () -> Unit ) { Card( modifier = Modifier @@ -95,6 +96,7 @@ fun TaskEntry( modifier = Modifier .padding(end = 5.dp), ) { + onStartTask() } } } @@ -110,7 +112,7 @@ fun TaskEntryPreview() { name = "Test Task", completed = false, ), - {}, {}, + {}, {}, {} ) } @@ -122,7 +124,7 @@ fun CompletedTaskEntryPreview() { name = "Test Task", completed = true, ), - {}, {}, + {}, {}, {}, ) } @@ -134,6 +136,6 @@ fun OverflowTaskEntryPreview() { name = "Test Taskkkkkkkkkkkkkkkkkkkkkkkkkkk", completed = false, ), - {}, {}, + {}, {}, {} ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt index d5e2bab..4b486fc 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt @@ -1,7 +1,9 @@ package be.ugent.sel.studeez.screens.session +import be.ugent.sel.studeez.data.SelectedTask import be.ugent.sel.studeez.data.SelectedTimerState import be.ugent.sel.studeez.data.SessionReportState +import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.navigation.StudeezDestinations @@ -13,17 +15,18 @@ import javax.inject.Inject class SessionViewModel @Inject constructor( private val selectedTimerState: SelectedTimerState, private val sessionReportState: SessionReportState, + private val selectedTask: SelectedTask, logService: LogService ) : StudeezViewModel(logService) { - private val task : String = "No task selected" // placeholder for tasks implementation + private val task : Task = selectedTask() fun getTimer() : FunctionalTimer { return selectedTimerState.selectedTimer!! } fun getTask(): String { - return task + return task.name } fun endSession(openAndPopUp: (String, String) -> Unit) { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt index 67f0e93..8a35717 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt @@ -30,6 +30,7 @@ data class TaskActions( val deleteTask: (Task) -> Unit, val onCheckTask: (Task, Boolean) -> Unit, val editSubject: () -> Unit, + val startTask: (Task) -> Unit ) fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskActions { @@ -39,7 +40,8 @@ fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskAction getSubject = viewModel::getSelectedSubject, deleteTask = viewModel::deleteTask, onCheckTask = { task, isChecked -> viewModel.toggleTaskCompleted(task, isChecked) }, - editSubject = { viewModel.editSubject(open) } + editSubject = { viewModel.editSubject(open) }, + startTask = { task -> viewModel.startTask(task, open) } ) } @@ -75,6 +77,7 @@ fun TaskScreen( task = it, onCheckTask = { isChecked -> taskActions.onCheckTask(it, isChecked) }, onDeleteTask = { taskActions.deleteTask(it) }, + onStartTask = { taskActions.startTask(it) } ) } } @@ -108,6 +111,7 @@ fun TaskScreenPreview() { {}, { _, _ -> run {} }, {}, + {} ) ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt index 138d32c..37f1c91 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt @@ -1,6 +1,7 @@ package be.ugent.sel.studeez.screens.tasks import be.ugent.sel.studeez.data.SelectedSubject +import be.ugent.sel.studeez.data.SelectedTask import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.domain.LogService @@ -17,6 +18,7 @@ class TaskViewModel @Inject constructor( private val taskDAO: TaskDAO, private val subjectDAO: SubjectDAO, private val selectedSubject: SelectedSubject, + private val selectedTask: SelectedTask, logService: LogService, ) : StudeezViewModel(logService) { fun addTask(open: (String) -> Unit) { @@ -47,4 +49,9 @@ class TaskViewModel @Inject constructor( fun editSubject(open: (String) -> Unit) { open(StudeezDestinations.EDIT_SUBJECT_FORM) } + + fun startTask(task: Task, open: (String) -> Unit) { + selectedTask.set(task) + open(StudeezDestinations.TIMER_SELECTION_SCREEN) + } } \ No newline at end of file From 45f28592abb43d9077572b73c3feaba19985b8c5 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 10:08:02 +0200 Subject: [PATCH 31/87] sessionreport now has the id of the task --- .../be/ugent/sel/studeez/data/local/models/SessionReport.kt | 3 ++- .../data/local/models/timer_functional/FunctionalTimer.kt | 6 ++++-- .../ugent/sel/studeez/screens/session/SessionViewModel.kt | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt index 20a44a8..9ed8450 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt @@ -6,5 +6,6 @@ import com.google.firebase.firestore.DocumentId data class SessionReport( @DocumentId val id: String = "", val studyTime: Int = 0, - val endTime: Timestamp = Timestamp(0, 0) + val endTime: Timestamp = Timestamp(0, 0), + val taskId: String ) \ No newline at end of file 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 1f4231a..cf5005f 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 @@ -2,6 +2,7 @@ package be.ugent.sel.studeez.data.local.models.timer_functional import be.ugent.sel.studeez.data.local.models.SessionReport import com.google.firebase.Timestamp +import com.google.firebase.firestore.DocumentReference abstract class FunctionalTimer(initialValue: Int) { var time: Time = Time(initialValue) @@ -17,10 +18,11 @@ abstract class FunctionalTimer(initialValue: Int) { abstract fun hasCurrentCountdownEnded(): Boolean - fun getSessionReport(): SessionReport { + fun getSessionReport(taskId: String): SessionReport { return SessionReport( studyTime = totalStudyTime, - endTime = Timestamp.now() + endTime = Timestamp.now(), + taskId = taskId ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt index 4b486fc..920d4e0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt @@ -30,7 +30,7 @@ class SessionViewModel @Inject constructor( } fun endSession(openAndPopUp: (String, String) -> Unit) { - sessionReportState.sessionReport = getTimer().getSessionReport() + sessionReportState.sessionReport = getTimer().getSessionReport(task.id) openAndPopUp(StudeezDestinations.SESSION_RECAP, StudeezDestinations.SESSION_SCREEN) } } \ No newline at end of file From 83fba0de70a520c7e0d7b25944b256f48aa73c25 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 13:55:44 +0200 Subject: [PATCH 32/87] #74 added a feedEntry dataclass --- .../ugent/sel/studeez/data/local/models/FeedEntry.kt | 10 ++++++++++ .../main/java/be/ugent/sel/studeez/domain/FeedDAO.kt | 4 ++++ .../studeez/domain/implementation/FirebaseFeedDAO.kt | 4 ++++ .../java/be/ugent/sel/studeez/screens/home/Feed.kt | 2 ++ .../be/ugent/sel/studeez/screens/home/FeedViewModel.kt | 4 ++++ 5 files changed, 24 insertions(+) create mode 100644 app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt create mode 100644 app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt create mode 100644 app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt new file mode 100644 index 0000000..336a252 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt @@ -0,0 +1,10 @@ +package be.ugent.sel.studeez.data.local.models + +data class FeedEntry( + val argb_color: Long = 0, + val subJectName: String = "", + val taskName: String = "", + val taskId: String = "", // Name of task is not unique + val subjectId: String = "", + val totalStudyTime: Int = 0 +) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt new file mode 100644 index 0000000..cc8ae0c --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt @@ -0,0 +1,4 @@ +package be.ugent.sel.studeez.domain + +interface FeedDAO { +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt new file mode 100644 index 0000000..df9ef8f --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -0,0 +1,4 @@ +package be.ugent.sel.studeez.domain.implementation + +class FirebaseFeedDAO { +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt new file mode 100644 index 0000000..af6014f --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -0,0 +1,2 @@ +package be.ugent.sel.studeez.screens.home + diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt new file mode 100644 index 0000000..52c0be2 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt @@ -0,0 +1,4 @@ +package be.ugent.sel.studeez.screens.home + +class FeedViewModel { +} \ No newline at end of file From 05d93246a68be8db05644e62c4cda560357068ea Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 13:56:08 +0200 Subject: [PATCH 33/87] sessionreport now also has a task and subject id --- .../be/ugent/sel/studeez/data/local/models/SessionReport.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt index 9ed8450..5835538 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/SessionReport.kt @@ -7,5 +7,6 @@ data class SessionReport( @DocumentId val id: String = "", val studyTime: Int = 0, val endTime: Timestamp = Timestamp(0, 0), - val taskId: String + val taskId: String = "", + val subjectId: String = "" ) \ No newline at end of file From a0ea97dc522b325237a768ceaf35516014a616dd Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 13:57:05 +0200 Subject: [PATCH 34/87] #74 added bind for feedDAO --- app/src/main/java/be/ugent/sel/studeez/di/DatabaseModule.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/di/DatabaseModule.kt b/app/src/main/java/be/ugent/sel/studeez/di/DatabaseModule.kt index 7ee4992..4c5fea1 100644 --- a/app/src/main/java/be/ugent/sel/studeez/di/DatabaseModule.kt +++ b/app/src/main/java/be/ugent/sel/studeez/di/DatabaseModule.kt @@ -33,4 +33,7 @@ abstract class DatabaseModule { @Binds abstract fun provideTaskDAO(impl: FireBaseTaskDAO): TaskDAO + + @Binds + abstract fun provideFeedDAO(impl: FirebaseFeedDAO): FeedDAO } \ No newline at end of file From bee7101befefbd2a8f70059a7088021152b73186 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 13:58:02 +0200 Subject: [PATCH 35/87] #74 added FeedDAO and firebase implementation --- .../be/ugent/sel/studeez/domain/FeedDAO.kt | 6 +++ .../domain/implementation/FirebaseFeedDAO.kt | 49 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt index cc8ae0c..05d4425 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt @@ -1,4 +1,10 @@ package be.ugent.sel.studeez.domain +import be.ugent.sel.studeez.data.local.models.FeedEntry +import kotlinx.coroutines.flow.Flow + interface FeedDAO { + + fun getFeedEntries(): Flow> + } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index df9ef8f..c406b45 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -1,4 +1,51 @@ package be.ugent.sel.studeez.domain.implementation -class FirebaseFeedDAO { +import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.data.local.models.SessionReport +import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.data.local.models.task.Task +import be.ugent.sel.studeez.domain.FeedDAO +import be.ugent.sel.studeez.domain.SessionDAO +import be.ugent.sel.studeez.domain.TaskDAO +import kotlinx.coroutines.flow.* +import javax.inject.Inject + +class FirebaseFeedDAO @Inject constructor( + private val sessionDAO: SessionDAO, + private val taskDAO: TaskDAO, + private val subjectDAO: FireBaseSubjectDAO +) : FeedDAO { + + override fun getFeedEntries(): Flow> { + return sessionDAO.getSessions().map {sessionReports -> + sessionReports + .map { sessionReport -> sessionToFeedEntry(sessionReport) } + .groupBy { it.taskId } + .map { fuseFeedEntries(it.component2()) } + } + } + + private fun fuseFeedEntries(entries: List): FeedEntry = + entries.fold(entries[0]) { accEntry, newEntry -> + val newStudyTime = accEntry.totalStudyTime + newEntry.totalStudyTime + accEntry.copy(totalStudyTime = newStudyTime) + } + + + private suspend fun sessionToFeedEntry(sessionReport: SessionReport): FeedEntry { + val subjectId: String = sessionReport.subjectId + val taskId: String = sessionReport.taskId + + val task: Task = taskDAO.getTask(subjectId, taskId) + val subject: Subject = subjectDAO.getSubject(subjectId)!! + + return FeedEntry( + argb_color = subject.argb_color, + subJectName = subject.name, + taskName = task.name, + taskId = task.id, + subjectId = subject.id, + totalStudyTime = sessionReport.studyTime + ) + } } \ No newline at end of file From dab4506a3451b55bcb1a012dd0bdfa7a46e3b512 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 13:59:29 +0200 Subject: [PATCH 36/87] #74 added single getSubject so feed kan fetch only one subject --- .../studeez/domain/implementation/FireBaseSubjectDAO.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt index 7d90fbf..e022863 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt @@ -1,13 +1,16 @@ package be.ugent.sel.studeez.domain.implementation import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.SubjectDAO import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.ktx.snapshots +import com.google.firebase.firestore.ktx.toObject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.tasks.await import javax.inject.Inject class FireBaseSubjectDAO @Inject constructor( @@ -20,6 +23,10 @@ class FireBaseSubjectDAO @Inject constructor( .map { it.toObjects(Subject::class.java) } } + override suspend fun getSubject(subjectId: String): Subject? { + return currentUserSubjectsCollection().document(subjectId).get().await().toObject() + } + override fun saveSubject(newSubject: Subject) { currentUserSubjectsCollection().add(newSubject) } From 2c7c96d73a1f4632ccdfb1feda717c881fa984dd Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 13:59:44 +0200 Subject: [PATCH 37/87] #74 added single getTask so feed kan fetch only one Task --- .../sel/studeez/domain/implementation/FireBaseTaskDAO.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt index b8855e6..963c93b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt @@ -8,8 +8,11 @@ import be.ugent.sel.studeez.domain.TaskDAO import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.ktx.snapshots +import com.google.firebase.firestore.ktx.toObject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.tasks.await import javax.inject.Inject class FireBaseTaskDAO @Inject constructor( @@ -22,6 +25,10 @@ class FireBaseTaskDAO @Inject constructor( .map { it.toObjects(Task::class.java) } } + override suspend fun getTask(subjectId: String, taskId: String): Task { + return selectedSubjectTasksCollection(subjectId).document(taskId).get().await().toObject()!! + } + override fun saveTask(newTask: Task) { selectedSubjectTasksCollection(newTask.subjectId).add(newTask) } From 1c224446a847f6c2e6f09f8e05956e84ad26a92f Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:00:42 +0200 Subject: [PATCH 38/87] added getSubject to interface --- app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt index 2749fac..da6abbe 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt @@ -12,4 +12,5 @@ interface SubjectDAO { fun deleteSubject(oldSubject: Subject) fun updateSubject(newSubject: Subject) + suspend fun getSubject(subjectId: String): Subject? } \ No newline at end of file From 07ff75476d0a309992c7b533dff1da03c64540c2 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:00:52 +0200 Subject: [PATCH 39/87] added getTask to interface --- app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt index 0f629ea..988a10d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt @@ -15,4 +15,6 @@ interface TaskDAO { fun deleteTask(oldTask: Task) fun toggleTaskCompleted(task: Task, completed: Boolean) + + suspend fun getTask(subjectId: String, taskId: String): Task } \ No newline at end of file From 2db431463db0cbb0372199e721e2431bb8e7c3bf Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:02:29 +0200 Subject: [PATCH 40/87] sessionreport needs if of subjectId and taskId --- .../data/local/models/timer_functional/FunctionalTimer.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 cf5005f..656f52f 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 @@ -18,11 +18,12 @@ abstract class FunctionalTimer(initialValue: Int) { abstract fun hasCurrentCountdownEnded(): Boolean - fun getSessionReport(taskId: String): SessionReport { + fun getSessionReport(subjectId: String, taskId: String): SessionReport { return SessionReport( studyTime = totalStudyTime, endTime = Timestamp.now(), - taskId = taskId + taskId = taskId, + subjectId = subjectId ) } From f7b5d5170d73412b4ebe22c3d312e3fb1f1334c7 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:02:56 +0200 Subject: [PATCH 41/87] #74 made a feed --- .../be/ugent/sel/studeez/screens/home/Feed.kt | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt index af6014f..0e93a96 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -1,2 +1,103 @@ package be.ugent.sel.studeez.screens.home +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Card +import androidx.compose.material.Divider +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.List +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import be.ugent.sel.studeez.R +import be.ugent.sel.studeez.common.composable.StealthButton +import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds + +@Composable +fun Feed( + open: (String) -> Unit, + viewModel: FeedViewModel = hiltViewModel() +) { + val feedEntries = viewModel.getFeedEntries().collectAsState(initial = emptyList()) + + LazyColumn { + items(feedEntries.value) {feedEntry -> + FeedEntryCard(feedEntry = feedEntry) { + viewModel.continueWithTask(open, feedEntry.subjectId, feedEntry.taskId) + } + } + } +} + +@Composable +fun FeedEntryCard( + feedEntry: FeedEntry, + onViewSubject: () -> Unit, +) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp, vertical = 5.dp), + ) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(start = 10.dp) + .weight(3f) + ) { + Box( + modifier = Modifier + .size(20.dp) + .clip(CircleShape) + .background(Color(feedEntry.argb_color)), + ) + Column( + verticalArrangement = Arrangement.spacedBy(0.dp) + ) { + Text( + text = feedEntry.subJectName, + fontWeight = FontWeight.Bold, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text(text = feedEntry.taskName) + Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString()) + } + } + } + StealthButton( + text = R.string.start, + modifier = Modifier + .padding(start = 10.dp, end = 5.dp) + .weight(1f) + ) { + onViewSubject() + } + } + } +} \ No newline at end of file From 190c3467ec78aaf30f535bf4554c2a4f525d8f18 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:03:46 +0200 Subject: [PATCH 42/87] #74 viewmodel of a feed --- .../sel/studeez/screens/home/FeedViewModel.kt | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt index 52c0be2..3b9fb0c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt @@ -1,4 +1,37 @@ package be.ugent.sel.studeez.screens.home -class FeedViewModel { +import androidx.lifecycle.viewModelScope +import be.ugent.sel.studeez.data.SelectedTask +import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.domain.FeedDAO +import be.ugent.sel.studeez.domain.LogService +import be.ugent.sel.studeez.domain.TaskDAO +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 kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class FeedViewModel @Inject constructor( + private val feedDAO: FeedDAO, + private val taskDAO: TaskDAO, + private val selectedTask: SelectedTask, + logService: LogService +) : StudeezViewModel(logService) { + + private val entries: Flow> = feedDAO.getFeedEntries() + + fun getFeedEntries(): Flow> { + return entries + } + + fun continueWithTask(open: (String) -> Unit, subjectId: String, taskId: String) { + viewModelScope.launch { + val task = taskDAO.getTask(subjectId, taskId) + selectedTask.set(task) + open(StudeezDestinations.TIMER_SELECTION_SCREEN) + } + } } \ No newline at end of file From 4728755c5e863b2132a27fce153c4258ffed74b7 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:04:20 +0200 Subject: [PATCH 43/87] #74 homescreen now contains a feed --- .../be/ugent/sel/studeez/screens/home/HomeScreen.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt index f02852e..b71ada1 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt @@ -25,6 +25,7 @@ fun HomeRoute( HomeScreen( onStartSessionClick = { viewModel.onStartSessionClick(open) }, drawerActions = drawerActions, + open = open, navigationBarActions = navigationBarActions, ) } @@ -32,6 +33,7 @@ fun HomeRoute( @Composable fun HomeScreen( onStartSessionClick: () -> Unit, + open: (String) -> Unit, drawerActions: DrawerActions, navigationBarActions: NavigationBarActions ) { @@ -41,9 +43,10 @@ fun HomeScreen( navigationBarActions = navigationBarActions, // TODO barAction = { FriendsAction() } ) { - BasicButton(R.string.start_session, Modifier.basicButton()) { - onStartSessionClick() - } + Feed(open) +// BasicButton(R.string.start_session, Modifier.basicButton()) { +// onStartSessionClick() +// } } } @@ -63,6 +66,7 @@ fun HomeScreenPreview() { HomeScreen( onStartSessionClick = {}, drawerActions = DrawerActions({}, {}, {}, {}, {}), - navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}) + navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), + open = {} ) } From 49835108f3976e27b0c93e0b6ecbd7dc213e47b7 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:05:43 +0200 Subject: [PATCH 44/87] subject id and taskid as parameters for getSessionReport --- .../be/ugent/sel/studeez/screens/session/SessionViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt index 920d4e0..cd4c93a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt @@ -30,7 +30,7 @@ class SessionViewModel @Inject constructor( } fun endSession(openAndPopUp: (String, String) -> Unit) { - sessionReportState.sessionReport = getTimer().getSessionReport(task.id) + sessionReportState.sessionReport = getTimer().getSessionReport(task.subjectId, task.id) openAndPopUp(StudeezDestinations.SESSION_RECAP, StudeezDestinations.SESSION_SCREEN) } } \ No newline at end of file From e1ddf41d09ef719983b723c2473dcf11c043d984 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:06:20 +0200 Subject: [PATCH 45/87] #74 added continue string for feed --- app/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d51259c..bc00963 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -29,6 +29,9 @@ Home Start session + + Continue + Tasks Task From 260171a972a1b858e66bd52bcfe9392cdb8c9577 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:25:18 +0200 Subject: [PATCH 46/87] #74 feedEntry now has an endTime --- .../java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt index 336a252..e24cd24 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt @@ -1,10 +1,13 @@ package be.ugent.sel.studeez.data.local.models +import com.google.firebase.Timestamp + data class FeedEntry( val argb_color: Long = 0, val subJectName: String = "", val taskName: String = "", val taskId: String = "", // Name of task is not unique val subjectId: String = "", - val totalStudyTime: Int = 0 + val totalStudyTime: Int = 0, + val endTime: Timestamp = Timestamp(0, 0) ) From 3f6d416f39446affee82ce284f0d3095b94257fc Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 14:26:07 +0200 Subject: [PATCH 47/87] #74 feed is now sorted on taskdates --- .../domain/implementation/FirebaseFeedDAO.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index c406b45..d742bf3 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -7,6 +7,7 @@ import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.domain.FeedDAO import be.ugent.sel.studeez.domain.SessionDAO import be.ugent.sel.studeez.domain.TaskDAO +import com.google.firebase.Timestamp import kotlinx.coroutines.flow.* import javax.inject.Inject @@ -22,15 +23,22 @@ class FirebaseFeedDAO @Inject constructor( .map { sessionReport -> sessionToFeedEntry(sessionReport) } .groupBy { it.taskId } .map { fuseFeedEntries(it.component2()) } + .sortedByDescending { it.endTime } } } private fun fuseFeedEntries(entries: List): FeedEntry = entries.fold(entries[0]) { accEntry, newEntry -> - val newStudyTime = accEntry.totalStudyTime + newEntry.totalStudyTime - accEntry.copy(totalStudyTime = newStudyTime) + accEntry.copy( + totalStudyTime = accEntry.totalStudyTime + newEntry.totalStudyTime, + endTime = getMostRecent(accEntry.endTime, newEntry.endTime) + ) } + private fun getMostRecent(t1: Timestamp, t2: Timestamp): Timestamp { + return if (t1 < t2) t2 else t1 + } + private suspend fun sessionToFeedEntry(sessionReport: SessionReport): FeedEntry { val subjectId: String = sessionReport.subjectId @@ -45,7 +53,8 @@ class FirebaseFeedDAO @Inject constructor( taskName = task.name, taskId = task.id, subjectId = subject.id, - totalStudyTime = sessionReport.studyTime + totalStudyTime = sessionReport.studyTime, + endTime = sessionReport.endTime ) } } \ No newline at end of file From f3a8c93a3e23969759de35dcfc2193b17cde376f Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 16:10:32 +0200 Subject: [PATCH 48/87] #74 getFeedentries now returns a map with date as key and as value the entries for that day --- app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt | 2 +- .../sel/studeez/domain/implementation/FirebaseFeedDAO.kt | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt index 05d4425..2d91781 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/FeedDAO.kt @@ -5,6 +5,6 @@ import kotlinx.coroutines.flow.Flow interface FeedDAO { - fun getFeedEntries(): Flow> + fun getFeedEntries(): Flow>> } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index d742bf3..600153a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -1,5 +1,6 @@ package be.ugent.sel.studeez.domain.implementation +import android.icu.text.DateFormat import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.SessionReport import be.ugent.sel.studeez.data.local.models.task.Subject @@ -17,16 +18,21 @@ class FirebaseFeedDAO @Inject constructor( private val subjectDAO: FireBaseSubjectDAO ) : FeedDAO { - override fun getFeedEntries(): Flow> { + override fun getFeedEntries(): Flow>> { return sessionDAO.getSessions().map {sessionReports -> sessionReports .map { sessionReport -> sessionToFeedEntry(sessionReport) } .groupBy { it.taskId } .map { fuseFeedEntries(it.component2()) } .sortedByDescending { it.endTime } + .groupBy { getFormattedTime(it) } } } + private fun getFormattedTime(entry: FeedEntry): String { + return DateFormat.getDateInstance().format(entry.endTime.toDate()) + } + private fun fuseFeedEntries(entries: List): FeedEntry = entries.fold(entries[0]) { accEntry, newEntry -> accEntry.copy( From ac1bfe4d49a33ee4cc7ffc049fb0e292017134ea Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 16:10:56 +0200 Subject: [PATCH 49/87] #74 feed now had dates --- .../be/ugent/sel/studeez/screens/home/Feed.kt | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt index 0e93a96..62f285a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -1,5 +1,7 @@ package be.ugent.sel.studeez.screens.home +import android.icu.text.DateFormat +import android.icu.text.SimpleDateFormat import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn @@ -21,24 +23,37 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.StealthButton import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import com.google.type.Date +import java.time.temporal.TemporalField +import java.util.* @Composable fun Feed( open: (String) -> Unit, viewModel: FeedViewModel = hiltViewModel() ) { - val feedEntries = viewModel.getFeedEntries().collectAsState(initial = emptyList()) + val feedEntries = viewModel.getFeedEntries().collectAsState(initial = emptyMap()) LazyColumn { - items(feedEntries.value) {feedEntry -> - FeedEntryCard(feedEntry = feedEntry) { - viewModel.continueWithTask(open, feedEntry.subjectId, feedEntry.taskId) + + items(feedEntries.value.toList()) {(date, feedEntries) -> + Text( + text = date, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + modifier = Modifier.padding(horizontal = 10.dp) + ) + feedEntries.forEach { feedEntry -> + FeedEntryCard(feedEntry = feedEntry) { + viewModel.continueWithTask(open, feedEntry.subjectId, feedEntry.taskId) + } } } } From 4e8fb28b0298cc99868c9e43ede74887fec9a16f Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 16:11:46 +0200 Subject: [PATCH 50/87] #74 dao returns map --- .../java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt index 3b9fb0c..aca17c8 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt @@ -21,9 +21,9 @@ class FeedViewModel @Inject constructor( logService: LogService ) : StudeezViewModel(logService) { - private val entries: Flow> = feedDAO.getFeedEntries() + private val entries: Flow>> = feedDAO.getFeedEntries() - fun getFeedEntries(): Flow> { + fun getFeedEntries(): Flow>> { return entries } From afe58572a6b97d4ca6b1aaff8d00c98d23900415 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 16:58:25 +0200 Subject: [PATCH 51/87] #74 fusing entries only on a daily basis --- .../sel/studeez/domain/implementation/FirebaseFeedDAO.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index 600153a..79e4e68 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -22,10 +22,14 @@ class FirebaseFeedDAO @Inject constructor( return sessionDAO.getSessions().map {sessionReports -> sessionReports .map { sessionReport -> sessionToFeedEntry(sessionReport) } - .groupBy { it.taskId } - .map { fuseFeedEntries(it.component2()) } .sortedByDescending { it.endTime } .groupBy { getFormattedTime(it) } + .mapValues { (_, entries) -> + entries + .groupBy { it.taskId } + .map { fuseFeedEntries(it.component2()) } + .sortedByDescending { it.endTime } + } } } From b5b32059718448a4c38a5e1596a9faca7fd5ebed Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 16:59:23 +0200 Subject: [PATCH 52/87] #74 UI Refactor --- .../be/ugent/sel/studeez/screens/home/Feed.kt | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt index 62f285a..4a254ac 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -1,7 +1,5 @@ package be.ugent.sel.studeez.screens.home -import android.icu.text.DateFormat -import android.icu.text.SimpleDateFormat import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn @@ -9,17 +7,13 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Card import androidx.compose.material.Divider -import androidx.compose.material.Icon import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.List import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -27,12 +21,9 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.StealthButton +import be.ugent.sel.studeez.common.ext.spacer import be.ugent.sel.studeez.data.local.models.FeedEntry -import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds -import com.google.type.Date -import java.time.temporal.TemporalField -import java.util.* @Composable fun Feed( @@ -44,21 +35,41 @@ fun Feed( LazyColumn { items(feedEntries.value.toList()) {(date, feedEntries) -> - Text( - text = date, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - modifier = Modifier.padding(horizontal = 10.dp) - ) + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } + DateText(date = date) + Text( + text = "${HoursMinutesSeconds(totalDayStudyTime)}", + fontSize = 15.sp, + fontWeight = FontWeight.Bold + ) + } feedEntries.forEach { feedEntry -> FeedEntryCard(feedEntry = feedEntry) { viewModel.continueWithTask(open, feedEntry.subjectId, feedEntry.taskId) } } + Spacer(modifier = Modifier.height(20.dp)) } } } +@Composable +fun DateText(date: String) { + Text( + text = date, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + modifier = Modifier.padding(horizontal = 10.dp) + ) +} + @Composable fun FeedEntryCard( feedEntry: FeedEntry, From d036afc319e20aec40f1ec5d681805d290366b14 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 17:10:57 +0200 Subject: [PATCH 53/87] Docs --- .../studeez/domain/implementation/FirebaseFeedDAO.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index 79e4e68..56d9000 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -18,6 +18,9 @@ class FirebaseFeedDAO @Inject constructor( private val subjectDAO: FireBaseSubjectDAO ) : FeedDAO { + /** + * Return a map as with key the day and value a list of feedentries for that day. + */ override fun getFeedEntries(): Flow>> { return sessionDAO.getSessions().map {sessionReports -> sessionReports @@ -28,7 +31,6 @@ class FirebaseFeedDAO @Inject constructor( entries .groupBy { it.taskId } .map { fuseFeedEntries(it.component2()) } - .sortedByDescending { it.endTime } } } } @@ -37,6 +39,10 @@ class FirebaseFeedDAO @Inject constructor( return DateFormat.getDateInstance().format(entry.endTime.toDate()) } + /** + * Givin a list of entries referencing the same task, in the same day, fuse them into one + * feed-entry by adding the studytime and keeping the most recent end-timestamp + */ private fun fuseFeedEntries(entries: List): FeedEntry = entries.fold(entries[0]) { accEntry, newEntry -> accEntry.copy( @@ -49,7 +55,9 @@ class FirebaseFeedDAO @Inject constructor( return if (t1 < t2) t2 else t1 } - + /** + * Convert a sessionReport to a feedEntry. Fetch Task and Subject to get names + */ private suspend fun sessionToFeedEntry(sessionReport: SessionReport): FeedEntry { val subjectId: String = sessionReport.subjectId val taskId: String = sessionReport.taskId From 9a214ce97cc7118396eb38f4b09496365c7b45ca Mon Sep 17 00:00:00 2001 From: lbarraga Date: Sun, 7 May 2023 17:23:43 +0200 Subject: [PATCH 54/87] change name of button function --- app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt index 4a254ac..7847ceb 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Card -import androidx.compose.material.Divider import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -21,7 +20,6 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.StealthButton -import be.ugent.sel.studeez.common.ext.spacer import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds @@ -73,7 +71,7 @@ fun DateText(date: String) { @Composable fun FeedEntryCard( feedEntry: FeedEntry, - onViewSubject: () -> Unit, + continueWithTask: () -> Unit, ) { Card( modifier = Modifier @@ -122,7 +120,7 @@ fun FeedEntryCard( .padding(start = 10.dp, end = 5.dp) .weight(1f) ) { - onViewSubject() + continueWithTask() } } } From c62d15ee99ca56608890885d10e599c24f2c1c7d Mon Sep 17 00:00:00 2001 From: lbarraga Date: Mon, 8 May 2023 17:10:44 +0200 Subject: [PATCH 55/87] comment in homescreen weg --- .../main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt index b71ada1..0911fd9 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt @@ -44,9 +44,6 @@ fun HomeScreen( // TODO barAction = { FriendsAction() } ) { Feed(open) -// BasicButton(R.string.start_session, Modifier.basicButton()) { -// onStartSessionClick() -// } } } From 9df80f4f935de6743143ce3b7079030715623288 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Mon, 8 May 2023 17:40:23 +0200 Subject: [PATCH 56/87] Fix: double counted entries --- .../ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index 56d9000..c116fbf 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -44,7 +44,7 @@ class FirebaseFeedDAO @Inject constructor( * feed-entry by adding the studytime and keeping the most recent end-timestamp */ private fun fuseFeedEntries(entries: List): FeedEntry = - entries.fold(entries[0]) { accEntry, newEntry -> + entries.drop(1).fold(entries[0]) { accEntry, newEntry -> accEntry.copy( totalStudyTime = accEntry.totalStudyTime + newEntry.totalStudyTime, endTime = getMostRecent(accEntry.endTime, newEntry.endTime) From 08c779030e3580f1084b990e8c094f3bcaf0c9f9 Mon Sep 17 00:00:00 2001 From: brreynie Date: Mon, 8 May 2023 21:05:54 +0200 Subject: [PATCH 57/87] refactor FeedEntry --- .../common/composable/TextComposable.kt | 13 +++ .../be/ugent/sel/studeez/screens/home/Feed.kt | 86 ++--------------- .../sel/studeez/screens/home/FeedEntry.kt | 96 +++++++++++++++++++ 3 files changed, 119 insertions(+), 76 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/TextComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/TextComposable.kt index 1b921a9..25fa3c4 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/TextComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/TextComposable.kt @@ -3,10 +3,13 @@ package be.ugent.sel.studeez.common.composable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable @@ -23,4 +26,14 @@ fun Headline( fontSize = 34.sp ) } +} + +@Composable +fun DateText(date: String) { + Text( + text = date, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + modifier = Modifier.padding(horizontal = 10.dp) + ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt index 7847ceb..af42203 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -1,26 +1,19 @@ package be.ugent.sel.studeez.screens.home -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.Card import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import be.ugent.sel.studeez.R -import be.ugent.sel.studeez.common.composable.StealthButton -import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.common.composable.DateText import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds @Composable @@ -29,10 +22,10 @@ fun Feed( viewModel: FeedViewModel = hiltViewModel() ) { val feedEntries = viewModel.getFeedEntries().collectAsState(initial = emptyMap()) - + LazyColumn { - items(feedEntries.value.toList()) {(date, feedEntries) -> + items(feedEntries.value.toList()) { (date, feedEntries) -> Row( horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier @@ -49,7 +42,7 @@ fun Feed( ) } feedEntries.forEach { feedEntry -> - FeedEntryCard(feedEntry = feedEntry) { + FeedEntry(feedEntry = feedEntry) { viewModel.continueWithTask(open, feedEntry.subjectId, feedEntry.taskId) } } @@ -58,70 +51,11 @@ fun Feed( } } +@Preview @Composable -fun DateText(date: String) { - Text( - text = date, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - modifier = Modifier.padding(horizontal = 10.dp) +fun FeedPreview() { + Feed( + open = {}, + viewModel = hiltViewModel(), ) -} - -@Composable -fun FeedEntryCard( - feedEntry: FeedEntry, - continueWithTask: () -> Unit, -) { - Card( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 10.dp, vertical = 5.dp), - ) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(start = 10.dp) - .weight(3f) - ) { - Box( - modifier = Modifier - .size(20.dp) - .clip(CircleShape) - .background(Color(feedEntry.argb_color)), - ) - Column( - verticalArrangement = Arrangement.spacedBy(0.dp) - ) { - Text( - text = feedEntry.subJectName, - fontWeight = FontWeight.Bold, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Text(text = feedEntry.taskName) - Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString()) - } - } - } - StealthButton( - text = R.string.start, - modifier = Modifier - .padding(start = 10.dp, end = 5.dp) - .weight(1f) - ) { - continueWithTask() - } - } - } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt new file mode 100644 index 0000000..a7d1fc1 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt @@ -0,0 +1,96 @@ +package be.ugent.sel.studeez.screens.home + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Card +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +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.StealthButton +import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds + +@Composable +fun FeedEntry( + feedEntry: FeedEntry, + continueWithTask: () -> Unit, +) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp, vertical = 5.dp), + ) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(start = 10.dp) + .weight(11f) + ) { + Box( + modifier = Modifier + .size(20.dp) + .clip(CircleShape) + .background(Color(feedEntry.argb_color)), + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Column( + verticalArrangement = Arrangement.spacedBy(0.dp) + ) { + Text( + text = feedEntry.subJectName, + fontWeight = FontWeight.Bold, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + Text( + text = feedEntry.taskName, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + } + Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString()) + } + } + StealthButton( + text = R.string.continue_task, + modifier = Modifier + .padding(start = 10.dp, end = 5.dp) + .weight(6f) + ) { + continueWithTask() + } + } + } +} + +@Preview +@Composable +fun FeedEntryPreview() { + FeedEntry( + continueWithTask = {}, + feedEntry = FeedEntry( + argb_color = 0xFFFFD200, + subJectName = "Test Subject", + taskName = "Test Taskkkkkkkkkkkkkkkkkkkkkkkkk", + totalStudyTime = 20, + ) + ) +} \ No newline at end of file From d31276ef815a7e055717ea43a30a1639ebd9c13a Mon Sep 17 00:00:00 2001 From: brreynie Date: Mon, 8 May 2023 21:21:14 +0200 Subject: [PATCH 58/87] refactor Feed --- .../sel/studeez/navigation/StudeezNavGraph.kt | 4 +- .../be/ugent/sel/studeez/screens/home/Feed.kt | 43 +++++++++++-------- .../sel/studeez/screens/home/FeedViewModel.kt | 2 +- .../sel/studeez/screens/home/HomeScreen.kt | 17 ++++---- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt index a09846a..bd12413 100644 --- a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt @@ -15,6 +15,7 @@ import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions import be.ugent.sel.studeez.screens.home.HomeRoute +import be.ugent.sel.studeez.screens.home.getFeedActions import be.ugent.sel.studeez.screens.log_in.LoginRoute import be.ugent.sel.studeez.screens.profile.EditProfileRoute import be.ugent.sel.studeez.screens.profile.ProfileRoute @@ -67,7 +68,8 @@ fun StudeezNavGraph( open, viewModel = hiltViewModel(), drawerActions = drawerActions, - navigationBarActions = navigationBarActions + navigationBarActions = navigationBarActions, + feedActions = getFeedActions(hiltViewModel(), open), ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt index af42203..96a9623 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt @@ -9,22 +9,40 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.common.composable.DateText +import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import kotlinx.coroutines.flow.Flow + +data class FeedActions( + val getFeedEntries: () -> Flow>>, + val continueTask: (String, String) -> Unit, +) + +fun getFeedActions( + viewmodel: FeedViewModel, + open: (String) -> Unit, +): FeedActions { + return FeedActions( + getFeedEntries = viewmodel::getFeedEntries, + continueTask = { subjectId, taskId -> + viewmodel.continueTask( + open, + subjectId, + taskId, + ) + }, + ) +} @Composable fun Feed( - open: (String) -> Unit, - viewModel: FeedViewModel = hiltViewModel() + feedActions: FeedActions, ) { - val feedEntries = viewModel.getFeedEntries().collectAsState(initial = emptyMap()) - + val feedEntries = feedActions.getFeedEntries().collectAsState(initial = emptyMap()) LazyColumn { - items(feedEntries.value.toList()) { (date, feedEntries) -> Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -43,19 +61,10 @@ fun Feed( } feedEntries.forEach { feedEntry -> FeedEntry(feedEntry = feedEntry) { - viewModel.continueWithTask(open, feedEntry.subjectId, feedEntry.taskId) + feedActions.continueTask(feedEntry.subjectId, feedEntry.taskId) } } Spacer(modifier = Modifier.height(20.dp)) } } -} - -@Preview -@Composable -fun FeedPreview() { - Feed( - open = {}, - viewModel = hiltViewModel(), - ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt index aca17c8..1f57175 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt @@ -27,7 +27,7 @@ class FeedViewModel @Inject constructor( return entries } - fun continueWithTask(open: (String) -> Unit, subjectId: String, taskId: String) { + fun continueTask(open: (String) -> Unit, subjectId: String, taskId: String) { viewModelScope.launch { val task = taskDAO.getTask(subjectId, taskId) selectedTask.set(task) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt index 0911fd9..79f03e3 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt @@ -5,15 +5,13 @@ import androidx.compose.material.IconButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Person import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import be.ugent.sel.studeez.R -import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate import be.ugent.sel.studeez.common.composable.drawer.DrawerActions import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions -import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.resources +import kotlinx.coroutines.flow.flowOf @Composable fun HomeRoute( @@ -21,21 +19,22 @@ fun HomeRoute( viewModel: HomeViewModel, drawerActions: DrawerActions, navigationBarActions: NavigationBarActions, + feedActions: FeedActions, ) { HomeScreen( - onStartSessionClick = { viewModel.onStartSessionClick(open) }, drawerActions = drawerActions, open = open, navigationBarActions = navigationBarActions, + feedActions = feedActions, ) } @Composable fun HomeScreen( - onStartSessionClick: () -> Unit, open: (String) -> Unit, drawerActions: DrawerActions, - navigationBarActions: NavigationBarActions + navigationBarActions: NavigationBarActions, + feedActions: FeedActions, ) { PrimaryScreenTemplate( title = resources().getString(R.string.home), @@ -43,7 +42,7 @@ fun HomeScreen( navigationBarActions = navigationBarActions, // TODO barAction = { FriendsAction() } ) { - Feed(open) + Feed(feedActions) } } @@ -61,9 +60,9 @@ fun FriendsAction() { @Composable fun HomeScreenPreview() { HomeScreen( - onStartSessionClick = {}, drawerActions = DrawerActions({}, {}, {}, {}, {}), navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), - open = {} + open = {}, + feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }) ) } From 6ba0018765a4d09bb048d13db64d112c234cacb0 Mon Sep 17 00:00:00 2001 From: brreynie Date: Mon, 8 May 2023 21:51:18 +0200 Subject: [PATCH 59/87] refactor feed to use UiState.Loading --- .../studeez/common/composable/feed/Feed.kt | 99 +++++++++++++++++++ .../composable/feed}/FeedEntry.kt | 2 +- .../common/composable/feed/FeedUiState.kt | 8 ++ .../composable/feed}/FeedViewModel.kt | 14 ++- .../sel/studeez/navigation/StudeezNavGraph.kt | 4 +- .../be/ugent/sel/studeez/screens/home/Feed.kt | 70 ------------- .../sel/studeez/screens/home/HomeScreen.kt | 16 ++- .../sel/studeez/screens/home/HomeViewModel.kt | 19 ---- 8 files changed, 131 insertions(+), 101 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt rename app/src/main/java/be/ugent/sel/studeez/{screens/home => common/composable/feed}/FeedEntry.kt (98%) create mode 100644 app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedUiState.kt rename app/src/main/java/be/ugent/sel/studeez/{screens/home => common/composable/feed}/FeedViewModel.kt (75%) delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt new file mode 100644 index 0000000..6c7c0c1 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt @@ -0,0 +1,99 @@ +package be.ugent.sel.studeez.common.composable.feed + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import be.ugent.sel.studeez.common.composable.DateText +import be.ugent.sel.studeez.data.local.models.FeedEntry +import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf + +data class FeedActions( + val getFeedEntries: () -> Flow>>, + val continueTask: (String, String) -> Unit, +) + +fun getFeedActions( + viewmodel: FeedViewModel, + open: (String) -> Unit, +): FeedActions { + return FeedActions( + getFeedEntries = viewmodel::getFeedEntries, + continueTask = { subjectId, taskId -> + viewmodel.continueTask( + open, + subjectId, + taskId, + ) + }, + ) +} + +@Composable +fun Feed( + feedActions: FeedActions, + uiState: FeedUiState, +) { + when (uiState) { + FeedUiState.Loading -> { + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator(color = MaterialTheme.colors.onBackground) + } + } + is FeedUiState.Succes -> { +// val feedEntries = feedActions.getFeedEntries().collectAsState(initial = emptyMap()) + val feedEntries = uiState.feedEntries + LazyColumn { + items(feedEntries.toList()) { (date, feedEntries) -> + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } + DateText(date = date) + Text( + text = "${HoursMinutesSeconds(totalDayStudyTime)}", + fontSize = 15.sp, + fontWeight = FontWeight.Bold + ) + } + feedEntries.forEach { feedEntry -> + FeedEntry(feedEntry = feedEntry) { + feedActions.continueTask(feedEntry.subjectId, feedEntry.taskId) + } + } + Spacer(modifier = Modifier.height(20.dp)) + } + } + } + } +} + +@Preview +@Composable +fun FeedPreview() { + Feed( + feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }), + uiState = FeedUiState.Loading, + ) +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt similarity index 98% rename from app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt rename to app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt index a7d1fc1..6dce710 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.home +package be.ugent.sel.studeez.common.composable.feed import androidx.compose.foundation.background import androidx.compose.foundation.layout.* diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedUiState.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedUiState.kt new file mode 100644 index 0000000..1b938ca --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedUiState.kt @@ -0,0 +1,8 @@ +package be.ugent.sel.studeez.common.composable.feed + +import be.ugent.sel.studeez.data.local.models.FeedEntry + +sealed interface FeedUiState { + object Loading : FeedUiState + data class Succes(val feedEntries: Map>) : FeedUiState +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt similarity index 75% rename from app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt index 1f57175..d31d83a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.home +package be.ugent.sel.studeez.common.composable.feed import androidx.lifecycle.viewModelScope import be.ugent.sel.studeez.data.SelectedTask @@ -9,13 +9,13 @@ import be.ugent.sel.studeez.domain.TaskDAO 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 kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class FeedViewModel @Inject constructor( - private val feedDAO: FeedDAO, + feedDAO: FeedDAO, private val taskDAO: TaskDAO, private val selectedTask: SelectedTask, logService: LogService @@ -23,6 +23,14 @@ class FeedViewModel @Inject constructor( private val entries: Flow>> = feedDAO.getFeedEntries() + val uiState: StateFlow = feedDAO.getFeedEntries() + .map { FeedUiState.Succes(it) } + .stateIn( + scope = viewModelScope, + initialValue = FeedUiState.Loading, + started = SharingStarted.Eagerly, + ) + fun getFeedEntries(): Flow>> { return entries } diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt index bd12413..5becc44 100644 --- a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt @@ -15,7 +15,6 @@ import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions import be.ugent.sel.studeez.screens.home.HomeRoute -import be.ugent.sel.studeez.screens.home.getFeedActions import be.ugent.sel.studeez.screens.log_in.LoginRoute import be.ugent.sel.studeez.screens.profile.EditProfileRoute import be.ugent.sel.studeez.screens.profile.ProfileRoute @@ -66,10 +65,9 @@ fun StudeezNavGraph( composable(StudeezDestinations.HOME_SCREEN) { HomeRoute( open, - viewModel = hiltViewModel(), drawerActions = drawerActions, navigationBarActions = navigationBarActions, - feedActions = getFeedActions(hiltViewModel(), open), + feedViewModel = hiltViewModel(), ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt deleted file mode 100644 index 96a9623..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/Feed.kt +++ /dev/null @@ -1,70 +0,0 @@ -package be.ugent.sel.studeez.screens.home - -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import be.ugent.sel.studeez.common.composable.DateText -import be.ugent.sel.studeez.data.local.models.FeedEntry -import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds -import kotlinx.coroutines.flow.Flow - -data class FeedActions( - val getFeedEntries: () -> Flow>>, - val continueTask: (String, String) -> Unit, -) - -fun getFeedActions( - viewmodel: FeedViewModel, - open: (String) -> Unit, -): FeedActions { - return FeedActions( - getFeedEntries = viewmodel::getFeedEntries, - continueTask = { subjectId, taskId -> - viewmodel.continueTask( - open, - subjectId, - taskId, - ) - }, - ) -} - -@Composable -fun Feed( - feedActions: FeedActions, -) { - val feedEntries = feedActions.getFeedEntries().collectAsState(initial = emptyMap()) - LazyColumn { - items(feedEntries.value.toList()) { (date, feedEntries) -> - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } - DateText(date = date) - Text( - text = "${HoursMinutesSeconds(totalDayStudyTime)}", - fontSize = 15.sp, - fontWeight = FontWeight.Bold - ) - } - feedEntries.forEach { feedEntry -> - FeedEntry(feedEntry = feedEntry) { - feedActions.continueTask(feedEntry.subjectId, feedEntry.taskId) - } - } - Spacer(modifier = Modifier.height(20.dp)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt index 79f03e3..78d5ddb 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt @@ -5,10 +5,13 @@ import androidx.compose.material.IconButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Person import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.tooling.preview.Preview import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate import be.ugent.sel.studeez.common.composable.drawer.DrawerActions +import be.ugent.sel.studeez.common.composable.feed.* import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions import be.ugent.sel.studeez.resources import kotlinx.coroutines.flow.flowOf @@ -16,16 +19,17 @@ import kotlinx.coroutines.flow.flowOf @Composable fun HomeRoute( open: (String) -> Unit, - viewModel: HomeViewModel, drawerActions: DrawerActions, navigationBarActions: NavigationBarActions, - feedActions: FeedActions, + feedViewModel: FeedViewModel, ) { + val feedUiState by feedViewModel.uiState.collectAsState() HomeScreen( drawerActions = drawerActions, open = open, navigationBarActions = navigationBarActions, - feedActions = feedActions, + feedActions = getFeedActions(feedViewModel, open), + feedUiState = feedUiState, ) } @@ -35,6 +39,7 @@ fun HomeScreen( drawerActions: DrawerActions, navigationBarActions: NavigationBarActions, feedActions: FeedActions, + feedUiState: FeedUiState, ) { PrimaryScreenTemplate( title = resources().getString(R.string.home), @@ -42,7 +47,7 @@ fun HomeScreen( navigationBarActions = navigationBarActions, // TODO barAction = { FriendsAction() } ) { - Feed(feedActions) + Feed(feedActions, feedUiState) } } @@ -63,6 +68,7 @@ fun HomeScreenPreview() { drawerActions = DrawerActions({}, {}, {}, {}, {}), navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), open = {}, - feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }) + feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }), + feedUiState = FeedUiState.Loading, ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt deleted file mode 100644 index b27f995..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt +++ /dev/null @@ -1,19 +0,0 @@ -package be.ugent.sel.studeez.screens.home - -import be.ugent.sel.studeez.domain.AccountDAO -import be.ugent.sel.studeez.domain.LogService -import be.ugent.sel.studeez.navigation.StudeezDestinations -import be.ugent.sel.studeez.screens.StudeezViewModel -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -@HiltViewModel -class HomeViewModel @Inject constructor( - private val accountDAO: AccountDAO, - logService: LogService -) : StudeezViewModel(logService) { - - fun onStartSessionClick(open: (String) -> Unit) { - open(StudeezDestinations.TIMER_SELECTION_SCREEN) - } -} \ No newline at end of file From 366f236f9865136ce36206a084e938f4c0c14951 Mon Sep 17 00:00:00 2001 From: brreynie Date: Mon, 8 May 2023 22:14:17 +0200 Subject: [PATCH 60/87] add previews for feed --- .../studeez/common/composable/feed/Feed.kt | 70 +++++++++++-------- .../common/composable/feed/FeedViewModel.kt | 6 -- .../sel/studeez/screens/home/HomeScreen.kt | 45 ++++++++++-- 3 files changed, 80 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt index 6c7c0c1..5dac1c0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt @@ -16,34 +16,11 @@ import androidx.compose.ui.unit.sp import be.ugent.sel.studeez.common.composable.DateText import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf - -data class FeedActions( - val getFeedEntries: () -> Flow>>, - val continueTask: (String, String) -> Unit, -) - -fun getFeedActions( - viewmodel: FeedViewModel, - open: (String) -> Unit, -): FeedActions { - return FeedActions( - getFeedEntries = viewmodel::getFeedEntries, - continueTask = { subjectId, taskId -> - viewmodel.continueTask( - open, - subjectId, - taskId, - ) - }, - ) -} @Composable fun Feed( - feedActions: FeedActions, uiState: FeedUiState, + continueTask: (String, String) -> Unit, ) { when (uiState) { FeedUiState.Loading -> { @@ -58,7 +35,6 @@ fun Feed( } } is FeedUiState.Succes -> { -// val feedEntries = feedActions.getFeedEntries().collectAsState(initial = emptyMap()) val feedEntries = uiState.feedEntries LazyColumn { items(feedEntries.toList()) { (date, feedEntries) -> @@ -79,7 +55,7 @@ fun Feed( } feedEntries.forEach { feedEntry -> FeedEntry(feedEntry = feedEntry) { - feedActions.continueTask(feedEntry.subjectId, feedEntry.taskId) + continueTask(feedEntry.subjectId, feedEntry.taskId) } } Spacer(modifier = Modifier.height(20.dp)) @@ -89,11 +65,49 @@ fun Feed( } } +@Preview +@Composable +fun FeedLoadingPreview() { + Feed( + uiState = FeedUiState.Loading, + continueTask = { _, _ -> run {} }, + ) +} + @Preview @Composable fun FeedPreview() { Feed( - feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }), - uiState = FeedUiState.Loading, + uiState = FeedUiState.Succes( + mapOf( + "08 May 2023" to listOf( + FeedEntry( + argb_color = 0xFFFFD200, + subJectName = "Test Subject", + taskName = "Test Task", + totalStudyTime = 600, + ), + FeedEntry( + argb_color = 0xFFFFD200, + subJectName = "Test Subject", + taskName = "Test Task", + totalStudyTime = 20, + ), + ), + "09 May 2023" to listOf( + FeedEntry( + argb_color = 0xFFFD1200, + subJectName = "Test Subject", + taskName = "Test Task", + ), + FeedEntry( + argb_color = 0xFFFFD200, + subJectName = "Test Subject", + taskName = "Test Task", + ), + ) + ) + ), + continueTask = { _, _ -> run {} }, ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt index d31d83a..443d0c9 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt @@ -21,8 +21,6 @@ class FeedViewModel @Inject constructor( logService: LogService ) : StudeezViewModel(logService) { - private val entries: Flow>> = feedDAO.getFeedEntries() - val uiState: StateFlow = feedDAO.getFeedEntries() .map { FeedUiState.Succes(it) } .stateIn( @@ -31,10 +29,6 @@ class FeedViewModel @Inject constructor( started = SharingStarted.Eagerly, ) - fun getFeedEntries(): Flow>> { - return entries - } - fun continueTask(open: (String) -> Unit, subjectId: String, taskId: String) { viewModelScope.launch { val task = taskDAO.getTask(subjectId, taskId) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt index 78d5ddb..dad3dd2 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt @@ -11,10 +11,12 @@ import androidx.compose.ui.tooling.preview.Preview import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate import be.ugent.sel.studeez.common.composable.drawer.DrawerActions -import be.ugent.sel.studeez.common.composable.feed.* +import be.ugent.sel.studeez.common.composable.feed.Feed +import be.ugent.sel.studeez.common.composable.feed.FeedUiState +import be.ugent.sel.studeez.common.composable.feed.FeedViewModel import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions +import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.resources -import kotlinx.coroutines.flow.flowOf @Composable fun HomeRoute( @@ -28,8 +30,8 @@ fun HomeRoute( drawerActions = drawerActions, open = open, navigationBarActions = navigationBarActions, - feedActions = getFeedActions(feedViewModel, open), feedUiState = feedUiState, + continueTask = { subjectId, taskId -> feedViewModel.continueTask(open, subjectId, taskId) }, ) } @@ -38,8 +40,8 @@ fun HomeScreen( open: (String) -> Unit, drawerActions: DrawerActions, navigationBarActions: NavigationBarActions, - feedActions: FeedActions, feedUiState: FeedUiState, + continueTask: (String, String) -> Unit, ) { PrimaryScreenTemplate( title = resources().getString(R.string.home), @@ -47,7 +49,7 @@ fun HomeScreen( navigationBarActions = navigationBarActions, // TODO barAction = { FriendsAction() } ) { - Feed(feedActions, feedUiState) + Feed(feedUiState, continueTask) } } @@ -68,7 +70,36 @@ fun HomeScreenPreview() { drawerActions = DrawerActions({}, {}, {}, {}, {}), navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), open = {}, - feedActions = FeedActions({ flowOf() }, { _, _ -> run {} }), - feedUiState = FeedUiState.Loading, + feedUiState = FeedUiState.Succes( + mapOf( + "08 May 2023" to listOf( + FeedEntry( + argb_color = 0xFFABD200, + subJectName = "Test Subject", + taskName = "Test Task", + totalStudyTime = 600, + ), + FeedEntry( + argb_color = 0xFFFFD200, + subJectName = "Test Subject", + taskName = "Test Task", + totalStudyTime = 20, + ), + ), + "09 May 2023" to listOf( + FeedEntry( + argb_color = 0xFFFD1200, + subJectName = "Test Subject", + taskName = "Test Task", + ), + FeedEntry( + argb_color = 0xFFFF5C89, + subJectName = "Test Subject", + taskName = "Test Task", + ), + ) + ) + ), + continueTask = { _, _ -> run {} }, ) } From 5f8b7d7a7b653ed2d56d842327261b001d8d7f1d Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 15:30:37 +0200 Subject: [PATCH 61/87] show #tasks and #completedTasks in subject entry --- .../common/composable/tasks/SubjectEntry.kt | 18 +++++++--------- .../studeez/data/local/models/task/Subject.kt | 7 ++++++- .../studeez/data/local/models/task/Task.kt | 2 ++ .../be/ugent/sel/studeez/domain/TaskDAO.kt | 4 ++++ .../implementation/FireBaseSubjectDAO.kt | 10 ++++++++- .../domain/implementation/FireBaseTaskDAO.kt | 21 ++++++++++++++++++- .../domain/implementation/FirebaseFeedDAO.kt | 14 +++++++------ .../studeez/screens/tasks/SubjectScreen.kt | 2 +- 8 files changed, 57 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt index 8655ba3..a6b89bf 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt @@ -1,13 +1,7 @@ package be.ugent.sel.studeez.common.composable.tasks import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Card import androidx.compose.material.Icon @@ -24,10 +18,10 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import be.ugent.sel.studeez.R.string as AppText import be.ugent.sel.studeez.common.composable.StealthButton import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import be.ugent.sel.studeez.R.string as AppText @Composable fun SubjectEntry( @@ -80,7 +74,7 @@ fun SubjectEntry( imageVector = Icons.Default.List, contentDescription = stringResource(id = AppText.tasks) ) - Text(text = "0/0") // TODO + Text(text = "${subject.taskCompletedCount}/${subject.taskCount}") // TODO } } } @@ -104,7 +98,9 @@ fun SubjectEntryPreview() { subject = Subject( name = "Test Subject", argb_color = 0xFFFFD200, - time = 60 + time = 60, + taskCount = 5, + taskCompletedCount = 2, ), ) {} } @@ -116,7 +112,7 @@ fun OverflowSubjectEntryPreview() { subject = Subject( name = "Testttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt", argb_color = 0xFFFFD200, - time = 60 + time = 60, ), ) {} } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt index e84c2bb..622ef3c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt @@ -1,10 +1,15 @@ package be.ugent.sel.studeez.data.local.models.task import com.google.firebase.firestore.DocumentId +import com.google.firebase.firestore.Exclude data class Subject( @DocumentId val id: String = "", val name: String = "", val time: Int = 0, val argb_color: Long = 0, -) \ No newline at end of file + @get:Exclude @set:Exclude + var taskCount: Int = 0, + @get:Exclude @set:Exclude + var taskCompletedCount: Int = 0, +) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt index f2618db..91242b0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt @@ -8,6 +8,7 @@ data class Task( val completed: Boolean = false, val time: Int = 0, val subjectId: String = "", + val archived: Boolean = false, ) object TaskDocument { @@ -16,4 +17,5 @@ object TaskDocument { const val completed = "completed" const val time = "time" const val subjectId = "subjectId" + const val archived = "archived" } diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt index 988a10d..4c7ee44 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt @@ -17,4 +17,8 @@ interface TaskDAO { fun toggleTaskCompleted(task: Task, completed: Boolean) suspend fun getTask(subjectId: String, taskId: String): Task + + suspend fun getTaskCount(subject: Subject): Int + + suspend fun getCompletedTaskCount(subject: Subject): Int } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt index e022863..9156771 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt @@ -1,9 +1,9 @@ package be.ugent.sel.studeez.domain.implementation import be.ugent.sel.studeez.data.local.models.task.Subject -import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.SubjectDAO +import be.ugent.sel.studeez.domain.TaskDAO import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.ktx.snapshots @@ -16,11 +16,19 @@ import javax.inject.Inject class FireBaseSubjectDAO @Inject constructor( private val firestore: FirebaseFirestore, private val auth: AccountDAO, + private val taskDAO: TaskDAO, ) : SubjectDAO { override fun getSubjects(): Flow> { return currentUserSubjectsCollection() .snapshots() .map { it.toObjects(Subject::class.java) } + .map { subjects -> + subjects.map { subject -> + subject.taskCount = taskDAO.getTaskCount(subject) + subject.taskCompletedCount = taskDAO.getCompletedTaskCount(subject) + subject + } + } } override suspend fun getSubject(subjectId: String): Subject? { diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt index 963c93b..bf32776 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt @@ -5,12 +5,12 @@ import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.data.local.models.task.TaskDocument import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.TaskDAO +import com.google.firebase.firestore.AggregateSource import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.ktx.snapshots import com.google.firebase.firestore.ktx.toObject import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.tasks.await import javax.inject.Inject @@ -21,6 +21,7 @@ class FireBaseTaskDAO @Inject constructor( ) : TaskDAO { override fun getTasks(subject: Subject): Flow> { return selectedSubjectTasksCollection(subject.id) + .whereEqualTo(TaskDocument.archived, false) .snapshots() .map { it.toObjects(Task::class.java) } } @@ -29,6 +30,24 @@ class FireBaseTaskDAO @Inject constructor( return selectedSubjectTasksCollection(subjectId).document(taskId).get().await().toObject()!! } + override suspend fun getTaskCount(subject: Subject): Int { + return selectedSubjectTasksCollection(subject.id) + .count() + .get(AggregateSource.SERVER) + .await() + .count.toInt() + } + + override suspend fun getCompletedTaskCount(subject: Subject): Int { + return selectedSubjectTasksCollection(subject.id) + .whereEqualTo(TaskDocument.completed, true) + .whereEqualTo(TaskDocument.archived, false) + .count() + .get(AggregateSource.SERVER) + .await() + .count.toInt() + } + override fun saveTask(newTask: Task) { selectedSubjectTasksCollection(newTask.subjectId).add(newTask) } diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index c116fbf..fa579bb 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -7,30 +7,32 @@ import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.domain.FeedDAO import be.ugent.sel.studeez.domain.SessionDAO +import be.ugent.sel.studeez.domain.SubjectDAO import be.ugent.sel.studeez.domain.TaskDAO import com.google.firebase.Timestamp -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map import javax.inject.Inject class FirebaseFeedDAO @Inject constructor( private val sessionDAO: SessionDAO, private val taskDAO: TaskDAO, - private val subjectDAO: FireBaseSubjectDAO + private val subjectDAO: SubjectDAO ) : FeedDAO { /** * Return a map as with key the day and value a list of feedentries for that day. */ override fun getFeedEntries(): Flow>> { - return sessionDAO.getSessions().map {sessionReports -> + return sessionDAO.getSessions().map { sessionReports -> sessionReports - .map { sessionReport -> sessionToFeedEntry(sessionReport) } + .map { sessionReport -> sessionToFeedEntry(sessionReport) } .sortedByDescending { it.endTime } .groupBy { getFormattedTime(it) } .mapValues { (_, entries) -> entries - .groupBy { it.taskId } - .map { fuseFeedEntries(it.component2()) } + .groupBy { it.taskId } + .map { fuseFeedEntries(it.component2()) } } } } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt index 15a3925..a3395ea 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt @@ -54,6 +54,7 @@ fun SubjectScreen( Column( modifier = Modifier.padding(top = 5.dp) ) { + NewTaskSubjectButton(onClick = addSubject, AppText.new_subject) LazyColumn { items(subjects.value) { SubjectEntry( @@ -62,7 +63,6 @@ fun SubjectScreen( ) } } - NewTaskSubjectButton(onClick = addSubject, AppText.new_subject) } } } From e35f1438547925c25067580fd1e5dc83c33dc59f Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 16:00:15 +0200 Subject: [PATCH 62/87] archive tasks --- .../common/composable/tasks/TaskEntry.kt | 18 ++++-------------- .../sel/studeez/data/local/models/task/Task.kt | 8 ++++++-- .../domain/implementation/FireBaseTaskDAO.kt | 6 ++++-- .../sel/studeez/screens/tasks/TaskScreen.kt | 11 +++++++---- .../sel/studeez/screens/tasks/TaskViewModel.kt | 6 ++++++ 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt index bf3a7cf..35e7a44 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/TaskEntry.kt @@ -1,17 +1,7 @@ package be.ugent.sel.studeez.common.composable.tasks -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Card -import androidx.compose.material.Checkbox -import androidx.compose.material.CheckboxDefaults -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.foundation.layout.* +import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Delete import androidx.compose.runtime.Composable @@ -31,7 +21,7 @@ import be.ugent.sel.studeez.resources fun TaskEntry( task: Task, onCheckTask: (Boolean) -> Unit, - onDeleteTask: () -> Unit, + onArchiveTask: () -> Unit, onStartTask: () -> Unit ) { Card( @@ -81,7 +71,7 @@ fun TaskEntry( Box(modifier = Modifier.weight(7f)) { if (task.completed) { IconButton( - onClick = onDeleteTask, + onClick = onArchiveTask, modifier = Modifier .padding(start = 20.dp) ) { diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt index 91242b0..44d6d01 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt @@ -8,8 +8,12 @@ data class Task( val completed: Boolean = false, val time: Int = 0, val subjectId: String = "", - val archived: Boolean = false, -) + var archived: Boolean = false, +) { + fun archive() { + this.archived = true + } +} object TaskDocument { const val id = "id" diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt index bf32776..4443b87 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt @@ -32,6 +32,7 @@ class FireBaseTaskDAO @Inject constructor( override suspend fun getTaskCount(subject: Subject): Int { return selectedSubjectTasksCollection(subject.id) + .whereEqualTo(TaskDocument.archived, false) .count() .get(AggregateSource.SERVER) .await() @@ -53,7 +54,7 @@ class FireBaseTaskDAO @Inject constructor( } override fun updateTask(newTask: Task) { - selectedSubjectTasksCollection(newTask.id).document(newTask.id).set(newTask) + selectedSubjectTasksCollection(newTask.subjectId).document(newTask.id).set(newTask) } override fun deleteTask(oldTask: Task) { @@ -63,7 +64,8 @@ class FireBaseTaskDAO @Inject constructor( override fun toggleTaskCompleted(task: Task, completed: Boolean) { selectedSubjectTasksCollection(task.subjectId) .document(task.id) - .update(TaskDocument.completed, completed) +// .update(TaskDocument.completed, completed) + .set(task.copy(completed = completed)) } private fun selectedSubjectTasksCollection(subjectId: String): CollectionReference = diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt index 8a35717..1b56bc6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt @@ -30,7 +30,8 @@ data class TaskActions( val deleteTask: (Task) -> Unit, val onCheckTask: (Task, Boolean) -> Unit, val editSubject: () -> Unit, - val startTask: (Task) -> Unit + val startTask: (Task) -> Unit, + val archiveTask: (Task) -> Unit, ) fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskActions { @@ -41,7 +42,8 @@ fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskAction deleteTask = viewModel::deleteTask, onCheckTask = { task, isChecked -> viewModel.toggleTaskCompleted(task, isChecked) }, editSubject = { viewModel.editSubject(open) }, - startTask = { task -> viewModel.startTask(task, open) } + startTask = { task -> viewModel.startTask(task, open) }, + archiveTask = viewModel::archiveTask ) } @@ -76,7 +78,7 @@ fun TaskScreen( TaskEntry( task = it, onCheckTask = { isChecked -> taskActions.onCheckTask(it, isChecked) }, - onDeleteTask = { taskActions.deleteTask(it) }, + onArchiveTask = { taskActions.archiveTask(it) }, onStartTask = { taskActions.startTask(it) } ) } @@ -111,7 +113,8 @@ fun TaskScreenPreview() { {}, { _, _ -> run {} }, {}, - {} + {}, + {}, ) ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt index 37f1c91..2361399 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt @@ -1,5 +1,6 @@ package be.ugent.sel.studeez.screens.tasks +import android.util.Log import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.SelectedTask import be.ugent.sel.studeez.data.local.models.task.Subject @@ -42,6 +43,11 @@ class TaskViewModel @Inject constructor( taskDAO.deleteTask(task) } + fun archiveTask(task: Task) { + task.archive() + taskDAO.updateTask(task) + } + fun toggleTaskCompleted(task: Task, completed: Boolean) { taskDAO.toggleTaskCompleted(task, completed) } From 1293ea31133ee40dde21a60e37b2ad9c39e377af Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:17:10 +0200 Subject: [PATCH 63/87] #74 refactor feed --- .../studeez/common/composable/feed/Feed.kt | 115 ++++++++++++------ 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt index 5dac1c0..54be2ea 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/Feed.kt @@ -9,58 +9,105 @@ 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.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import be.ugent.sel.studeez.common.composable.BasicTextButton import be.ugent.sel.studeez.common.composable.DateText +import be.ugent.sel.studeez.common.composable.Headline +import be.ugent.sel.studeez.common.ext.textButton import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import be.ugent.sel.studeez.R.string as AppText @Composable fun Feed( uiState: FeedUiState, continueTask: (String, String) -> Unit, + onEmptyFeedHelp: () -> Unit ) { when (uiState) { - FeedUiState.Loading -> { - Column( + FeedUiState.Loading -> LoadingFeed() + is FeedUiState.Succes -> LoadedFeed( + uiState = uiState, + continueTask = continueTask, + onEmptyFeedHelp = onEmptyFeedHelp + ) + } +} + +@Composable +fun LoadedFeed( + uiState: FeedUiState.Succes, + continueTask: (String, String) -> Unit, + onEmptyFeedHelp: () -> Unit, +) { + if (uiState.feedEntries.isEmpty()) EmptyFeed(onEmptyFeedHelp) + else FeedWithElements(uiState = uiState, continueTask = continueTask) +} + +@Composable +fun LoadingFeed() { + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator(color = MaterialTheme.colors.onBackground) + } +} + +@Composable +fun FeedWithElements( + uiState: FeedUiState.Succes, + continueTask: (String, String) -> Unit, +) { + val feedEntries = uiState.feedEntries + LazyColumn { + items(feedEntries.toList()) { (date, feedEntries) -> + Row( + horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier .fillMaxWidth() - .fillMaxHeight(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + .padding(10.dp), + verticalAlignment = Alignment.CenterVertically ) { - CircularProgressIndicator(color = MaterialTheme.colors.onBackground) + val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } + DateText(date = date) + Text( + text = "${HoursMinutesSeconds(totalDayStudyTime)}", + fontSize = 15.sp, + fontWeight = FontWeight.Bold + ) } - } - is FeedUiState.Succes -> { - val feedEntries = uiState.feedEntries - LazyColumn { - items(feedEntries.toList()) { (date, feedEntries) -> - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime } - DateText(date = date) - Text( - text = "${HoursMinutesSeconds(totalDayStudyTime)}", - fontSize = 15.sp, - fontWeight = FontWeight.Bold - ) - } - feedEntries.forEach { feedEntry -> - FeedEntry(feedEntry = feedEntry) { - continueTask(feedEntry.subjectId, feedEntry.taskId) - } - } - Spacer(modifier = Modifier.height(20.dp)) + feedEntries.forEach { feedEntry -> + FeedEntry(feedEntry = feedEntry) { + continueTask(feedEntry.subjectId, feedEntry.taskId) } } + Spacer(modifier = Modifier.height(20.dp)) + } + } +} + +@Composable +fun EmptyFeed(onEmptyFeedHelp: () -> Unit) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Headline(text = stringResource(id = AppText.your_feed)) + + BasicTextButton( + AppText.empty_feed_help_text, + Modifier.textButton(), + action = onEmptyFeedHelp, + ) } } } @@ -70,7 +117,7 @@ fun Feed( fun FeedLoadingPreview() { Feed( uiState = FeedUiState.Loading, - continueTask = { _, _ -> run {} }, + continueTask = { _, _ -> run {} }, {} ) } @@ -108,6 +155,6 @@ fun FeedPreview() { ) ) ), - continueTask = { _, _ -> run {} }, + continueTask = { _, _ -> run {} }, {} ) } \ No newline at end of file From 0fb3125f6a4ce5d33e8c42fbde874b0deb38dc05 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:17:46 +0200 Subject: [PATCH 64/87] #74 button to add subject when user has empty feed --- .../ugent/sel/studeez/common/composable/feed/FeedViewModel.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt index 443d0c9..fbd32f4 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt @@ -36,4 +36,8 @@ class FeedViewModel @Inject constructor( open(StudeezDestinations.TIMER_SELECTION_SCREEN) } } + + fun onEmptyFeedHelp(open: (String) -> Unit) { + open(StudeezDestinations.ADD_SUBJECT_FORM) + } } \ No newline at end of file From 9bf77b556c19c5a0bccd75d3ddfed396623e96a1 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:19:03 +0200 Subject: [PATCH 65/87] added function that opens subject add screen --- .../java/be/ugent/sel/studeez/screens/home/HomeScreen.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt index dad3dd2..c93527b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeScreen.kt @@ -32,6 +32,7 @@ fun HomeRoute( navigationBarActions = navigationBarActions, feedUiState = feedUiState, continueTask = { subjectId, taskId -> feedViewModel.continueTask(open, subjectId, taskId) }, + onEmptyFeedHelp = { feedViewModel.onEmptyFeedHelp(open) } ) } @@ -42,6 +43,7 @@ fun HomeScreen( navigationBarActions: NavigationBarActions, feedUiState: FeedUiState, continueTask: (String, String) -> Unit, + onEmptyFeedHelp: () -> Unit, ) { PrimaryScreenTemplate( title = resources().getString(R.string.home), @@ -49,7 +51,7 @@ fun HomeScreen( navigationBarActions = navigationBarActions, // TODO barAction = { FriendsAction() } ) { - Feed(feedUiState, continueTask) + Feed(feedUiState, continueTask, onEmptyFeedHelp) } } @@ -101,5 +103,6 @@ fun HomeScreenPreview() { ) ), continueTask = { _, _ -> run {} }, + onEmptyFeedHelp = {} ) } From 5be8432b18119ebf3b13465184cd0279fb478afe Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:19:38 +0200 Subject: [PATCH 66/87] edit button on the right --- .../screens/timer_overview/TimerOverviewScreen.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 a07dd67..3c25ddf 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 @@ -82,12 +82,13 @@ fun TimerOverviewScreen( items(timers.value) { timerInfo -> TimerEntry( timerInfo = timerInfo, - ) { - StealthButton( - text = R.string.edit, - onClick = { timerOverviewActions.onEditClick(timerInfo) } - ) - } + rightButton = { + StealthButton( + text = R.string.edit, + onClick = { timerOverviewActions.onEditClick(timerInfo) } + ) + } + ) } From 4fa7f97513d3cc00e79f3fc9d5643931b1bce4f6 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:20:39 +0200 Subject: [PATCH 67/87] added padding to custom timer time picker button --- .../screens/timer_selection/TimerSelectionScreen.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 2f17e65..d78b4bf 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,10 +1,13 @@ package be.ugent.sel.studeez.screens.timer_selection +import androidx.compose.foundation.layout.padding 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.Modifier 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.SecondaryScreenTemplate import be.ugent.sel.studeez.common.composable.StealthButton @@ -99,7 +102,10 @@ fun CustomTimerEntry( ) }, rightButton = { - TimePickerButton(initialSeconds = hms.getTotalSeconds()) { chosenTime -> + TimePickerButton( + initialSeconds = hms.getTotalSeconds(), + modifier = Modifier.padding(horizontal = 5.dp) + ) { chosenTime -> timerInfo.studyTime = chosenTime } } From 5992abf9c767ecbbec01b81888dcca4486366f7e Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:21:08 +0200 Subject: [PATCH 68/87] default of custom timer is 1 hour --- .../screens/timer_selection/TimerSelectionViewModel.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt index ab42973..a4f646d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import be.ugent.sel.studeez.data.SelectedTimerState +import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds 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 @@ -21,7 +22,9 @@ class TimerSelectionViewModel @Inject constructor( logService: LogService ) : StudeezViewModel(logService) { - var customTimerStudyTime: MutableState = mutableStateOf(0) + var customTimerStudyTime: MutableState = mutableStateOf( + HoursMinutesSeconds(1, 0, 0).getTotalSeconds() + ) fun getAllTimers() : Flow> { return timerDAO.getAllTimers() From 529adbcab322797c29ed0943cc6ba2b94a8bb1a9 Mon Sep 17 00:00:00 2001 From: Lukas Barragan Torres Date: Tue, 9 May 2023 16:21:37 +0200 Subject: [PATCH 69/87] added feed string --- app/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bc00963..d58be52 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,6 +31,8 @@ Continue + This is your feed + Create you first subject and tasks to get started Tasks From 8a395fbd4e71400e22785318650bae4f064b65de Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 20:30:15 +0200 Subject: [PATCH 70/87] implement TaskDAO as a very simple fluent interface --- .../domain/implementation/FireBaseTaskDAO.kt | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt index 4443b87..049bb54 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt @@ -8,6 +8,7 @@ import be.ugent.sel.studeez.domain.TaskDAO import com.google.firebase.firestore.AggregateSource import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.firestore.Query import com.google.firebase.firestore.ktx.snapshots import com.google.firebase.firestore.ktx.toObject import kotlinx.coroutines.flow.Flow @@ -21,7 +22,7 @@ class FireBaseTaskDAO @Inject constructor( ) : TaskDAO { override fun getTasks(subject: Subject): Flow> { return selectedSubjectTasksCollection(subject.id) - .whereEqualTo(TaskDocument.archived, false) + .nonArchived() .snapshots() .map { it.toObjects(Task::class.java) } } @@ -32,7 +33,7 @@ class FireBaseTaskDAO @Inject constructor( override suspend fun getTaskCount(subject: Subject): Int { return selectedSubjectTasksCollection(subject.id) - .whereEqualTo(TaskDocument.archived, false) + .nonArchived() .count() .get(AggregateSource.SERVER) .await() @@ -41,8 +42,8 @@ class FireBaseTaskDAO @Inject constructor( override suspend fun getCompletedTaskCount(subject: Subject): Int { return selectedSubjectTasksCollection(subject.id) - .whereEqualTo(TaskDocument.completed, true) - .whereEqualTo(TaskDocument.archived, false) + .completed() + .nonArchived() .count() .get(AggregateSource.SERVER) .await() @@ -74,4 +75,19 @@ class FireBaseTaskDAO @Inject constructor( .collection(FireBaseCollections.SUBJECT_COLLECTION) .document(subjectId) .collection(FireBaseCollections.TASK_COLLECTION) + + // Extend CollectionReference and Query with some filters + + private fun CollectionReference.nonArchived(): Query = + this.whereEqualTo(TaskDocument.archived, false) + + private fun Query.nonArchived(): Query = + this.whereEqualTo(TaskDocument.archived, false) + + private fun CollectionReference.completed(): Query = + this.whereEqualTo(TaskDocument.completed, true) + + private fun Query.completed(): Query = + this.whereEqualTo(TaskDocument.completed, true) + } \ No newline at end of file From a60422e00480496754e31e123f652bf1b9d237fd Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 21:01:19 +0200 Subject: [PATCH 71/87] refactor DAO's --- .../be/ugent/sel/studeez/domain/SubjectDAO.kt | 5 ++ .../be/ugent/sel/studeez/domain/TaskDAO.kt | 6 --- .../implementation/FireBaseSubjectDAO.kt | 36 ++++++++++++- .../domain/implementation/FireBaseTaskDAO.kt | 51 +++++-------------- 4 files changed, 52 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt index da6abbe..bad8106 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt @@ -12,5 +12,10 @@ interface SubjectDAO { fun deleteSubject(oldSubject: Subject) fun updateSubject(newSubject: Subject) + + suspend fun getTaskCount(subject: Subject): Int + suspend fun getCompletedTaskCount(subject: Subject): Int + fun getStudyTime(subject: Subject): Flow + suspend fun getSubject(subjectId: String): Subject? } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt index 4c7ee44..8a2dd41 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/TaskDAO.kt @@ -14,11 +14,5 @@ interface TaskDAO { fun deleteTask(oldTask: Task) - fun toggleTaskCompleted(task: Task, completed: Boolean) - suspend fun getTask(subjectId: String, taskId: String): Task - - suspend fun getTaskCount(subject: Subject): Int - - suspend fun getCompletedTaskCount(subject: Subject): Int } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt index 9156771..3e9ae13 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt @@ -4,6 +4,7 @@ import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.SubjectDAO import be.ugent.sel.studeez.domain.TaskDAO +import com.google.firebase.firestore.AggregateSource import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.ktx.snapshots @@ -24,8 +25,8 @@ class FireBaseSubjectDAO @Inject constructor( .map { it.toObjects(Subject::class.java) } .map { subjects -> subjects.map { subject -> - subject.taskCount = taskDAO.getTaskCount(subject) - subject.taskCompletedCount = taskDAO.getCompletedTaskCount(subject) + subject.taskCount = getTaskCount(subject) + subject.taskCompletedCount = getCompletedTaskCount(subject) subject } } @@ -47,8 +48,39 @@ class FireBaseSubjectDAO @Inject constructor( currentUserSubjectsCollection().document(newSubject.id).set(newSubject) } + override suspend fun getTaskCount(subject: Subject): Int { + return subjectTasksCollection(subject) + .nonArchived() + .count() + .get(AggregateSource.SERVER) + .await() + .count.toInt() + } + + override suspend fun getCompletedTaskCount(subject: Subject): Int { + return subjectTasksCollection(subject) + .nonArchived() + .completed() + .count() + .get(AggregateSource.SERVER) + .await() + .count.toInt() + } + + override fun getStudyTime(subject: Subject): Flow { + return taskDAO.getTasks(subject) + .map { tasks -> tasks.sumOf { it.time } } + } + private fun currentUserSubjectsCollection(): CollectionReference = firestore.collection(FireBaseCollections.USER_COLLECTION) .document(auth.currentUserId) .collection(FireBaseCollections.SUBJECT_COLLECTION) + + private fun subjectTasksCollection(subject: Subject): CollectionReference = + firestore.collection(FireBaseCollections.USER_COLLECTION) + .document(auth.currentUserId) + .collection(FireBaseCollections.SUBJECT_COLLECTION) + .document(subject.id) + .collection(FireBaseCollections.TASK_COLLECTION) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt index 049bb54..bde5c6f 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt @@ -5,7 +5,6 @@ import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.data.local.models.task.TaskDocument import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.TaskDAO -import com.google.firebase.firestore.AggregateSource import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.Query @@ -31,44 +30,20 @@ class FireBaseTaskDAO @Inject constructor( return selectedSubjectTasksCollection(subjectId).document(taskId).get().await().toObject()!! } - override suspend fun getTaskCount(subject: Subject): Int { - return selectedSubjectTasksCollection(subject.id) - .nonArchived() - .count() - .get(AggregateSource.SERVER) - .await() - .count.toInt() - } - - override suspend fun getCompletedTaskCount(subject: Subject): Int { - return selectedSubjectTasksCollection(subject.id) - .completed() - .nonArchived() - .count() - .get(AggregateSource.SERVER) - .await() - .count.toInt() - } - override fun saveTask(newTask: Task) { selectedSubjectTasksCollection(newTask.subjectId).add(newTask) } override fun updateTask(newTask: Task) { - selectedSubjectTasksCollection(newTask.subjectId).document(newTask.id).set(newTask) + selectedSubjectTasksCollection(newTask.subjectId) + .document(newTask.id) + .set(newTask) } override fun deleteTask(oldTask: Task) { selectedSubjectTasksCollection(oldTask.subjectId).document(oldTask.id).delete() } - override fun toggleTaskCompleted(task: Task, completed: Boolean) { - selectedSubjectTasksCollection(task.subjectId) - .document(task.id) -// .update(TaskDocument.completed, completed) - .set(task.copy(completed = completed)) - } - private fun selectedSubjectTasksCollection(subjectId: String): CollectionReference = firestore.collection(FireBaseCollections.USER_COLLECTION) .document(auth.currentUserId) @@ -76,18 +51,18 @@ class FireBaseTaskDAO @Inject constructor( .document(subjectId) .collection(FireBaseCollections.TASK_COLLECTION) - // Extend CollectionReference and Query with some filters +} - private fun CollectionReference.nonArchived(): Query = - this.whereEqualTo(TaskDocument.archived, false) +// Extend CollectionReference and Query with some filters - private fun Query.nonArchived(): Query = - this.whereEqualTo(TaskDocument.archived, false) +fun CollectionReference.nonArchived(): Query = + this.whereEqualTo(TaskDocument.archived, false) - private fun CollectionReference.completed(): Query = - this.whereEqualTo(TaskDocument.completed, true) +fun Query.nonArchived(): Query = + this.whereEqualTo(TaskDocument.archived, false) - private fun Query.completed(): Query = - this.whereEqualTo(TaskDocument.completed, true) +fun CollectionReference.completed(): Query = + this.whereEqualTo(TaskDocument.completed, true) -} \ No newline at end of file +fun Query.completed(): Query = + this.whereEqualTo(TaskDocument.completed, true) From ec31e116b4c3e0bf5bcded46a7ce9fa35c3770ee Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 21:29:52 +0200 Subject: [PATCH 72/87] refactor subjectscreen to use uiState --- .../common/composable/feed/FeedViewModel.kt | 6 +- .../studeez/data/local/models/task/Subject.kt | 3 +- .../studeez/data/local/models/task/Task.kt | 2 +- .../studeez/screens/tasks/SubjectScreen.kt | 76 ++++++++++++++----- .../studeez/screens/tasks/SubjectUiState.kt | 8 ++ .../studeez/screens/tasks/SubjectViewModel.kt | 18 +++-- .../studeez/screens/tasks/TaskViewModel.kt | 13 +--- 7 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt index 443d0c9..13d134b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedViewModel.kt @@ -2,14 +2,16 @@ package be.ugent.sel.studeez.common.composable.feed import androidx.lifecycle.viewModelScope import be.ugent.sel.studeez.data.SelectedTask -import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.domain.FeedDAO import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.TaskDAO import be.ugent.sel.studeez.navigation.StudeezDestinations import be.ugent.sel.studeez.screens.StudeezViewModel import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt index 622ef3c..6f29e22 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt @@ -6,10 +6,11 @@ import com.google.firebase.firestore.Exclude data class Subject( @DocumentId val id: String = "", val name: String = "", - val time: Int = 0, val argb_color: Long = 0, @get:Exclude @set:Exclude var taskCount: Int = 0, @get:Exclude @set:Exclude var taskCompletedCount: Int = 0, + @get:Exclude @set:Exclude + var time: Int = 0, ) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt index 44d6d01..e42ce5d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt @@ -5,7 +5,7 @@ import com.google.firebase.firestore.DocumentId data class Task( @DocumentId val id: String = "", val name: String = "", - val completed: Boolean = false, + var completed: Boolean = false, val time: Int = 0, val subjectId: String = "", var archived: Boolean = false, diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt index a3395ea..115c75e 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt @@ -1,11 +1,14 @@ package be.ugent.sel.studeez.screens.tasks -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -16,8 +19,6 @@ import be.ugent.sel.studeez.common.composable.drawer.DrawerActions import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions import be.ugent.sel.studeez.common.composable.tasks.SubjectEntry import be.ugent.sel.studeez.data.local.models.task.Subject -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf import be.ugent.sel.studeez.R.string as AppText @Composable @@ -27,12 +28,13 @@ fun SubjectRoute( drawerActions: DrawerActions, navigationBarActions: NavigationBarActions, ) { + val uiState by viewModel.uiState.collectAsState() SubjectScreen( drawerActions = drawerActions, navigationBarActions = navigationBarActions, - addSubject = { viewModel.addSubject(open) }, - getSubjects = viewModel::getSubjects, + onAddSubject = { viewModel.onAddSubject(open) }, onViewSubject = { viewModel.onViewSubject(it, open) }, + uiState, ) } @@ -40,9 +42,9 @@ fun SubjectRoute( fun SubjectScreen( drawerActions: DrawerActions, navigationBarActions: NavigationBarActions, - addSubject: () -> Unit, - getSubjects: () -> Flow>, + onAddSubject: () -> Unit, onViewSubject: (Subject) -> Unit, + uiState: SubjectUiState, ) { PrimaryScreenTemplate( title = stringResource(AppText.my_subjects), @@ -50,17 +52,29 @@ fun SubjectScreen( navigationBarActions = navigationBarActions, barAction = {}, ) { - val subjects = getSubjects().collectAsState(initial = emptyList()) - Column( - modifier = Modifier.padding(top = 5.dp) - ) { - NewTaskSubjectButton(onClick = addSubject, AppText.new_subject) - LazyColumn { - items(subjects.value) { - SubjectEntry( - subject = it, - onViewSubject = { onViewSubject(it) }, - ) + when (uiState) { + SubjectUiState.Loading -> Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator(color = MaterialTheme.colors.onBackground) + } + is SubjectUiState.Succes -> { + Column( + modifier = Modifier.padding(top = 5.dp) + ) { + NewTaskSubjectButton(onClick = onAddSubject, AppText.new_subject) + LazyColumn { + items(uiState.subjects) { + SubjectEntry( + subject = it, + onViewSubject = { onViewSubject(it) }, + ) + } + } } } } @@ -73,8 +87,28 @@ fun SubjectScreenPreview() { SubjectScreen( drawerActions = DrawerActions({}, {}, {}, {}, {}), navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), - addSubject = {}, - getSubjects = { flowOf() }, + onAddSubject = {}, onViewSubject = {}, + uiState = SubjectUiState.Succes( + listOf( + Subject( + name = "Test Subject", + argb_color = 0xFFFFD200, + taskCount = 5, taskCompletedCount = 2, + ) + ) + ) + ) +} + +@Preview +@Composable +fun SubjectScreenLoadingPreview() { + SubjectScreen( + drawerActions = DrawerActions({}, {}, {}, {}, {}), + navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), + onAddSubject = {}, + onViewSubject = {}, + uiState = SubjectUiState.Loading ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt new file mode 100644 index 0000000..38adae4 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt @@ -0,0 +1,8 @@ +package be.ugent.sel.studeez.screens.tasks + +import be.ugent.sel.studeez.data.local.models.task.Subject + +sealed interface SubjectUiState { + object Loading : SubjectUiState + data class Succes(val subjects: List) : SubjectUiState +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt index f1d6071..8587327 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt @@ -1,5 +1,6 @@ package be.ugent.sel.studeez.screens.tasks +import androidx.lifecycle.viewModelScope import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.domain.LogService @@ -7,7 +8,7 @@ import be.ugent.sel.studeez.domain.SubjectDAO 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 kotlinx.coroutines.flow.* import javax.inject.Inject @HiltViewModel @@ -16,12 +17,17 @@ class SubjectViewModel @Inject constructor( private val selectedSubject: SelectedSubject, logService: LogService, ) : StudeezViewModel(logService) { - fun addSubject(open: (String) -> Unit) { - open(StudeezDestinations.ADD_SUBJECT_FORM) - } - fun getSubjects(): Flow> { - return subjectDAO.getSubjects() + val uiState: StateFlow = subjectDAO.getSubjects() + .map { SubjectUiState.Succes(it) } + .stateIn( + scope = viewModelScope, + initialValue = SubjectUiState.Loading, + started = SharingStarted.Eagerly, + ) + + fun onAddSubject(open: (String) -> Unit) { + open(StudeezDestinations.ADD_SUBJECT_FORM) } fun onViewSubject(subject: Subject, open: (String) -> Unit) { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt index 2361399..e2adbc1 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskViewModel.kt @@ -1,12 +1,10 @@ package be.ugent.sel.studeez.screens.tasks -import android.util.Log import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.SelectedTask import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.domain.LogService -import be.ugent.sel.studeez.domain.SubjectDAO import be.ugent.sel.studeez.domain.TaskDAO import be.ugent.sel.studeez.navigation.StudeezDestinations import be.ugent.sel.studeez.screens.StudeezViewModel @@ -17,7 +15,6 @@ import javax.inject.Inject @HiltViewModel class TaskViewModel @Inject constructor( private val taskDAO: TaskDAO, - private val subjectDAO: SubjectDAO, private val selectedSubject: SelectedSubject, private val selectedTask: SelectedTask, logService: LogService, @@ -30,11 +27,6 @@ class TaskViewModel @Inject constructor( return taskDAO.getTasks(selectedSubject()) } - fun deleteSubject(open: (String) -> Unit) { - subjectDAO.deleteSubject(selectedSubject()) - open(StudeezDestinations.SUBJECT_SCREEN) - } - fun getSelectedSubject(): Subject { return selectedSubject() } @@ -44,12 +36,11 @@ class TaskViewModel @Inject constructor( } fun archiveTask(task: Task) { - task.archive() - taskDAO.updateTask(task) + taskDAO.updateTask(task.copy(archived = true)) } fun toggleTaskCompleted(task: Task, completed: Boolean) { - taskDAO.toggleTaskCompleted(task, completed) + taskDAO.updateTask(task.copy(completed = completed)) } fun editSubject(open: (String) -> Unit) { From e9cc4f4a0c9eaae4b6375176ae8a967be6e25284 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 21:37:26 +0200 Subject: [PATCH 73/87] show studytime --- .../common/composable/tasks/SubjectEntry.kt | 20 +++++++++++++------ .../studeez/screens/tasks/SubjectScreen.kt | 7 +++++++ .../studeez/screens/tasks/SubjectViewModel.kt | 4 ++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt index a6b89bf..5db2af3 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/tasks/SubjectEntry.kt @@ -9,6 +9,8 @@ import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.List import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -21,13 +23,17 @@ import androidx.compose.ui.unit.dp import be.ugent.sel.studeez.common.composable.StealthButton import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf import be.ugent.sel.studeez.R.string as AppText @Composable fun SubjectEntry( subject: Subject, onViewSubject: () -> Unit, + getStudyTime: () -> Flow, ) { + val studytime by getStudyTime().collectAsState(initial = 0) Card( modifier = Modifier .fillMaxWidth() @@ -64,7 +70,7 @@ fun SubjectEntry( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = HoursMinutesSeconds(subject.time).toString(), + text = HoursMinutesSeconds(studytime).toString(), ) Row( verticalAlignment = Alignment.CenterVertically, @@ -74,7 +80,7 @@ fun SubjectEntry( imageVector = Icons.Default.List, contentDescription = stringResource(id = AppText.tasks) ) - Text(text = "${subject.taskCompletedCount}/${subject.taskCount}") // TODO + Text(text = "${subject.taskCompletedCount}/${subject.taskCount}") } } } @@ -98,11 +104,12 @@ fun SubjectEntryPreview() { subject = Subject( name = "Test Subject", argb_color = 0xFFFFD200, - time = 60, taskCount = 5, taskCompletedCount = 2, ), - ) {} + onViewSubject = {}, + getStudyTime = { flowOf() } + ) } @Preview @@ -112,7 +119,8 @@ fun OverflowSubjectEntryPreview() { subject = Subject( name = "Testttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt", argb_color = 0xFFFFD200, - time = 60, ), - ) {} + onViewSubject = {}, + getStudyTime = { flowOf() } + ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt index 115c75e..7ff5636 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt @@ -19,6 +19,8 @@ import be.ugent.sel.studeez.common.composable.drawer.DrawerActions import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions import be.ugent.sel.studeez.common.composable.tasks.SubjectEntry import be.ugent.sel.studeez.data.local.models.task.Subject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf import be.ugent.sel.studeez.R.string as AppText @Composable @@ -34,6 +36,7 @@ fun SubjectRoute( navigationBarActions = navigationBarActions, onAddSubject = { viewModel.onAddSubject(open) }, onViewSubject = { viewModel.onViewSubject(it, open) }, + getStudyTime = viewModel::getStudyTime, uiState, ) } @@ -44,6 +47,7 @@ fun SubjectScreen( navigationBarActions: NavigationBarActions, onAddSubject: () -> Unit, onViewSubject: (Subject) -> Unit, + getStudyTime: (Subject) -> Flow, uiState: SubjectUiState, ) { PrimaryScreenTemplate( @@ -72,6 +76,7 @@ fun SubjectScreen( SubjectEntry( subject = it, onViewSubject = { onViewSubject(it) }, + getStudyTime = { getStudyTime(it) }, ) } } @@ -89,6 +94,7 @@ fun SubjectScreenPreview() { navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), onAddSubject = {}, onViewSubject = {}, + getStudyTime = { flowOf() }, uiState = SubjectUiState.Succes( listOf( Subject( @@ -109,6 +115,7 @@ fun SubjectScreenLoadingPreview() { navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), onAddSubject = {}, onViewSubject = {}, + getStudyTime = { flowOf() }, uiState = SubjectUiState.Loading ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt index 8587327..f384489 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt @@ -30,6 +30,10 @@ class SubjectViewModel @Inject constructor( open(StudeezDestinations.ADD_SUBJECT_FORM) } + fun getStudyTime(subject: Subject): Flow { + return subjectDAO.getStudyTime(subject) + } + fun onViewSubject(subject: Subject, open: (String) -> Unit) { selectedSubject.set(subject) open(StudeezDestinations.TASKS_SCREEN) From 0e4200057b5fdb2df45c31bdb7b227b44e451fb8 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 21:56:25 +0200 Subject: [PATCH 74/87] fix selectedSubject --- .../sel/studeez/navigation/StudeezNavGraph.kt | 12 ++--- .../{tasks => subjects}/SubjectScreen.kt | 2 +- .../{tasks => subjects}/SubjectUiState.kt | 2 +- .../{tasks => subjects}/SubjectViewModel.kt | 2 +- .../form}/SubjectFormScreen.kt | 8 +-- .../form}/SubjectFormUiState.kt | 2 +- .../form}/SubjectFormViewModel.kt | 54 ++++++++++++------- .../tasks/{forms => form}/TaskFormScreen.kt | 2 +- .../tasks/{forms => form}/TaskFormUiState.kt | 2 +- .../{forms => form}/TaskFormViewModel.kt | 5 +- 10 files changed, 53 insertions(+), 38 deletions(-) rename app/src/main/java/be/ugent/sel/studeez/screens/{tasks => subjects}/SubjectScreen.kt (98%) rename app/src/main/java/be/ugent/sel/studeez/screens/{tasks => subjects}/SubjectUiState.kt (81%) rename app/src/main/java/be/ugent/sel/studeez/screens/{tasks => subjects}/SubjectViewModel.kt (96%) rename app/src/main/java/be/ugent/sel/studeez/screens/{tasks/forms => subjects/form}/SubjectFormScreen.kt (95%) rename app/src/main/java/be/ugent/sel/studeez/screens/{tasks/forms => subjects/form}/SubjectFormUiState.kt (64%) rename app/src/main/java/be/ugent/sel/studeez/screens/{tasks/forms => subjects/form}/SubjectFormViewModel.kt (67%) rename app/src/main/java/be/ugent/sel/studeez/screens/tasks/{forms => form}/TaskFormScreen.kt (98%) rename app/src/main/java/be/ugent/sel/studeez/screens/tasks/{forms => form}/TaskFormUiState.kt (53%) rename app/src/main/java/be/ugent/sel/studeez/screens/tasks/{forms => form}/TaskFormViewModel.kt (93%) diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt index 5becc44..6ef1606 100644 --- a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt @@ -24,12 +24,12 @@ 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.tasks.SubjectRoute +import be.ugent.sel.studeez.screens.subjects.SubjectRoute import be.ugent.sel.studeez.screens.tasks.TaskRoute -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.subjects.form.SubjectCreateRoute +import be.ugent.sel.studeez.screens.subjects.form.SubjectEditRoute +import be.ugent.sel.studeez.screens.tasks.form.TaskAddRoute +import be.ugent.sel.studeez.screens.tasks.form.TaskEditRoute 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_form.timer_type_select.TimerTypeSelectScreen @@ -81,7 +81,7 @@ fun StudeezNavGraph( } composable(StudeezDestinations.ADD_SUBJECT_FORM) { - SubjectAddRoute( + SubjectCreateRoute( goBack = goBack, openAndPopUp = openAndPopUp, viewModel = hiltViewModel(), diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt similarity index 98% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt index 7ff5636..ab2cff4 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks +package be.ugent.sel.studeez.screens.subjects import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectUiState.kt similarity index 81% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectUiState.kt index 38adae4..2e44e27 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectUiState.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectUiState.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks +package be.ugent.sel.studeez.screens.subjects import be.ugent.sel.studeez.data.local.models.task.Subject diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt similarity index 96% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt index f384489..c158529 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/SubjectViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks +package be.ugent.sel.studeez.screens.subjects import androidx.lifecycle.viewModelScope import be.ugent.sel.studeez.data.SelectedSubject diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt similarity index 95% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index 74bc7d2..19e6816 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks.forms +package be.ugent.sel.studeez.screens.subjects.form import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column @@ -19,10 +19,10 @@ import be.ugent.sel.studeez.resources import be.ugent.sel.studeez.R.string as AppText @Composable -fun SubjectAddRoute( +fun SubjectCreateRoute( goBack: () -> Unit, openAndPopUp: (String, String) -> Unit, - viewModel: SubjectFormViewModel, + viewModel: SubjectCreateFormViewModel, ) { val uiState by viewModel.uiState SubjectForm( @@ -39,7 +39,7 @@ fun SubjectAddRoute( fun SubjectEditRoute( goBack: () -> Unit, openAndPopUp: (String, String) -> Unit, - viewModel: SubjectFormViewModel, + viewModel: SubjectEditFormViewModel, ) { val uiState by viewModel.uiState SubjectForm( diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt similarity index 64% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormUiState.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt index 5418b74..9fdba01 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormUiState.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks.forms +package be.ugent.sel.studeez.screens.subjects.form data class SubjectFormUiState( val name: String = "", diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt similarity index 67% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt index 68ebd3e..37a9e5b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/SubjectFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt @@ -1,5 +1,6 @@ -package be.ugent.sel.studeez.screens.tasks.forms +package be.ugent.sel.studeez.screens.subjects.form +import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.local.models.task.Subject @@ -10,25 +11,17 @@ import be.ugent.sel.studeez.screens.StudeezViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject -@HiltViewModel -class SubjectFormViewModel @Inject constructor( - private val subjectDAO: SubjectDAO, - private val selectedSubject: SelectedSubject, +abstract class SubjectFormViewModel( + protected val subjectDAO: SubjectDAO, + protected val selectedSubject: SelectedSubject, logService: LogService, ) : StudeezViewModel(logService) { - var uiState = mutableStateOf( - if (selectedSubject.isSet()) SubjectFormUiState( - name = selectedSubject().name, - color = selectedSubject().argb_color - ) - else SubjectFormUiState() - ) - private set + abstract val uiState: MutableState - private val name: String + protected val name: String get() = uiState.value.name - private val color: Long + protected val color: Long get() = uiState.value.color fun onNameChange(newValue: String) { @@ -38,11 +31,15 @@ class SubjectFormViewModel @Inject constructor( fun onColorChange(newValue: Long) { uiState.value = uiState.value.copy(color = newValue) } +} - fun onDelete(openAndPopUp: (String, String) -> Unit) { - subjectDAO.deleteSubject(selectedSubject()) - openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM) - } +@HiltViewModel +class SubjectCreateFormViewModel @Inject constructor( + subjectDAO: SubjectDAO, + selectedSubject: SelectedSubject, + logService: LogService, +) : SubjectFormViewModel(subjectDAO, selectedSubject, logService) { + override val uiState = mutableStateOf(SubjectFormUiState()) fun onCreate(openAndPopUp: (String, String) -> Unit) { val newSubject = Subject( @@ -57,6 +54,25 @@ class SubjectFormViewModel @Inject constructor( // open(StudeezDestinations.TASKS_SCREEN) openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.ADD_SUBJECT_FORM) } +} + +@HiltViewModel +class SubjectEditFormViewModel @Inject constructor( + subjectDAO: SubjectDAO, + selectedSubject: SelectedSubject, + logService: LogService, +) : SubjectFormViewModel(subjectDAO, selectedSubject, logService) { + override val uiState = mutableStateOf( + SubjectFormUiState( + name = selectedSubject().name, + color = selectedSubject().argb_color + ) + ) + + fun onDelete(openAndPopUp: (String, String) -> Unit) { + subjectDAO.deleteSubject(selectedSubject()) + openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM) + } fun onEdit(openAndPopUp: (String, String) -> Unit) { val newSubject = selectedSubject().copy( diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt similarity index 98% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormScreen.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt index 62b6c6c..b09dc66 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks.forms +package be.ugent.sel.studeez.screens.tasks.form import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormUiState.kt similarity index 53% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormUiState.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormUiState.kt index d967d59..6156fb7 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormUiState.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormUiState.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks.forms +package be.ugent.sel.studeez.screens.tasks.form data class TaskFormUiState( val name: String = "", diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt similarity index 93% rename from app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormViewModel.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt index 03ad32b..8ae91ae 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/forms/TaskFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt @@ -1,4 +1,4 @@ -package be.ugent.sel.studeez.screens.tasks.forms +package be.ugent.sel.studeez.screens.tasks.form import androidx.compose.runtime.mutableStateOf import be.ugent.sel.studeez.data.SelectedSubject @@ -11,8 +11,7 @@ import be.ugent.sel.studeez.screens.StudeezViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject -@HiltViewModel -class TaskFormViewModel @Inject constructor( +abstract class TaskFormViewModel( private val taskDAO: TaskDAO, private val selectedSubject: SelectedSubject, private val selectedTask: SelectedTask, From e333a0f6266982e372203f716eb3d59b146786e1 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 22:03:38 +0200 Subject: [PATCH 75/87] fix selectedTask --- .../sel/studeez/navigation/StudeezNavGraph.kt | 4 +- .../screens/tasks/form/TaskFormScreen.kt | 6 +-- .../screens/tasks/form/TaskFormViewModel.kt | 46 +++++++++++++------ 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt index 6ef1606..37085f1 100644 --- a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezNavGraph.kt @@ -28,7 +28,7 @@ import be.ugent.sel.studeez.screens.subjects.SubjectRoute import be.ugent.sel.studeez.screens.tasks.TaskRoute import be.ugent.sel.studeez.screens.subjects.form.SubjectCreateRoute import be.ugent.sel.studeez.screens.subjects.form.SubjectEditRoute -import be.ugent.sel.studeez.screens.tasks.form.TaskAddRoute +import be.ugent.sel.studeez.screens.tasks.form.TaskCreateRoute import be.ugent.sel.studeez.screens.tasks.form.TaskEditRoute import be.ugent.sel.studeez.screens.timer_form.TimerAddRoute import be.ugent.sel.studeez.screens.timer_form.TimerEditRoute @@ -105,7 +105,7 @@ fun StudeezNavGraph( } composable(StudeezDestinations.ADD_TASK_FORM) { - TaskAddRoute( + TaskCreateRoute( goBack = goBack, openAndPopUp = openAndPopUp, viewModel = hiltViewModel(), diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt index b09dc66..92302ea 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormScreen.kt @@ -18,10 +18,10 @@ import be.ugent.sel.studeez.resources import be.ugent.sel.studeez.R.string as AppText @Composable -fun TaskAddRoute( +fun TaskCreateRoute( goBack: () -> Unit, openAndPopUp: (String, String) -> Unit, - viewModel: TaskFormViewModel, + viewModel: TaskCreateFormViewModel, ) { val uiState by viewModel.uiState TaskForm( @@ -37,7 +37,7 @@ fun TaskAddRoute( fun TaskEditRoute( goBack: () -> Unit, openAndPopUp: (String, String) -> Unit, - viewModel: TaskFormViewModel, + viewModel: TaskEditFormViewModel, ) { val uiState by viewModel.uiState TaskForm( diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt index 8ae91ae..07cba5d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/form/TaskFormViewModel.kt @@ -1,5 +1,6 @@ package be.ugent.sel.studeez.screens.tasks.form +import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.SelectedTask @@ -12,37 +13,54 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject abstract class TaskFormViewModel( - private val taskDAO: TaskDAO, - private val selectedSubject: SelectedSubject, - private val selectedTask: SelectedTask, + protected val taskDAO: TaskDAO, + protected val selectedSubject: SelectedSubject, + protected val selectedTask: SelectedTask, logService: LogService, ) : StudeezViewModel(logService) { - var uiState = mutableStateOf( - if (selectedTask.isSet()) TaskFormUiState(selectedTask().name) else TaskFormUiState() - ) - private set + abstract val uiState: MutableState - private val name: String + protected val name: String get() = uiState.value.name fun onNameChange(newValue: String) { uiState.value = uiState.value.copy(name = newValue) } +} - fun onDelete(openAndPopUp: (String, String) -> Unit) { - taskDAO.deleteTask(selectedTask()) - openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_TASK_FORM) - } +@HiltViewModel +class TaskCreateFormViewModel @Inject constructor( + taskDAO: TaskDAO, + selectedSubject: SelectedSubject, + selectedTask: SelectedTask, + logService: LogService, +) : TaskFormViewModel(taskDAO, selectedSubject, selectedTask, logService) { + override val uiState = mutableStateOf(TaskFormUiState()) fun onCreate(openAndPopUp: (String, String) -> Unit) { val newTask = Task(name = name, subjectId = selectedSubject().id) taskDAO.saveTask(newTask) openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.ADD_TASK_FORM) } +} + +@HiltViewModel +class TaskEditFormViewModel @Inject constructor( + taskDAO: TaskDAO, + selectedSubject: SelectedSubject, + selectedTask: SelectedTask, + logService: LogService, +) : TaskFormViewModel(taskDAO, selectedSubject, selectedTask, logService) { + override val uiState = mutableStateOf(TaskFormUiState()) + + fun onDelete(openAndPopUp: (String, String) -> Unit) { + taskDAO.deleteTask(selectedTask()) + openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_TASK_FORM) + } fun onEdit(openAndPopUp: (String, String) -> Unit) { - val newTask = Task(name = name) + val newTask = selectedTask().copy(name = name) taskDAO.updateTask(newTask) openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_TASK_FORM) } -} \ No newline at end of file +} From d4c017ef1b7780d803748e3d9c64d6ea894b7ca3 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 22:11:52 +0200 Subject: [PATCH 76/87] add time to task when saving session report --- .../studeez/screens/session_recap/SessionRecapViewModel.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt index 5fb4943..5fdd95c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt @@ -1,9 +1,11 @@ package be.ugent.sel.studeez.screens.session_recap +import be.ugent.sel.studeez.data.SelectedTask import be.ugent.sel.studeez.data.SessionReportState import be.ugent.sel.studeez.data.local.models.SessionReport import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.SessionDAO +import be.ugent.sel.studeez.domain.TaskDAO import be.ugent.sel.studeez.navigation.StudeezDestinations import be.ugent.sel.studeez.screens.StudeezViewModel import dagger.hilt.android.lifecycle.HiltViewModel @@ -13,6 +15,8 @@ import javax.inject.Inject class SessionRecapViewModel @Inject constructor( sessionReportState: SessionReportState, private val sessionDAO: SessionDAO, + private val taskDAO: TaskDAO, + private val selectedTask: SelectedTask, logService: LogService ) : StudeezViewModel(logService) { @@ -24,6 +28,8 @@ class SessionRecapViewModel @Inject constructor( fun saveSession(open: (String, String) -> Unit) { sessionDAO.saveSession(getSessionReport()) + val newTask = selectedTask().copy(time = selectedTask().time + report.studyTime) + taskDAO.updateTask(newTask) open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP) } From c3424b99964615b0477995761f1b751e81d0ce3b Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 22:26:11 +0200 Subject: [PATCH 77/87] archive subjects --- .../sel/studeez/data/local/models/task/Subject.kt | 10 ++++++++-- .../domain/implementation/FireBaseSubjectDAO.kt | 15 ++++++++++++--- .../domain/implementation/FireBaseTaskDAO.kt | 10 +++++----- .../screens/subjects/form/SubjectFormViewModel.kt | 2 +- .../ugent/sel/studeez/screens/tasks/TaskScreen.kt | 3 --- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt index 6f29e22..74ebe9f 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Subject.kt @@ -7,10 +7,16 @@ data class Subject( @DocumentId val id: String = "", val name: String = "", val argb_color: Long = 0, + var archived: Boolean = false, @get:Exclude @set:Exclude var taskCount: Int = 0, @get:Exclude @set:Exclude var taskCompletedCount: Int = 0, - @get:Exclude @set:Exclude - var time: Int = 0, ) + +object SubjectDocument { + const val id = "id" + const val name = "name" + const val archived = "archived" + const val argb_color = "argb_color" +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt index 3e9ae13..b023986 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseSubjectDAO.kt @@ -1,12 +1,14 @@ package be.ugent.sel.studeez.domain.implementation import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.data.local.models.task.SubjectDocument import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.SubjectDAO import be.ugent.sel.studeez.domain.TaskDAO import com.google.firebase.firestore.AggregateSource import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.firestore.Query import com.google.firebase.firestore.ktx.snapshots import com.google.firebase.firestore.ktx.toObject import kotlinx.coroutines.flow.Flow @@ -21,6 +23,7 @@ class FireBaseSubjectDAO @Inject constructor( ) : SubjectDAO { override fun getSubjects(): Flow> { return currentUserSubjectsCollection() + .subjectNotArchived() .snapshots() .map { it.toObjects(Subject::class.java) } .map { subjects -> @@ -50,7 +53,7 @@ class FireBaseSubjectDAO @Inject constructor( override suspend fun getTaskCount(subject: Subject): Int { return subjectTasksCollection(subject) - .nonArchived() + .taskNotArchived() .count() .get(AggregateSource.SERVER) .await() @@ -59,8 +62,8 @@ class FireBaseSubjectDAO @Inject constructor( override suspend fun getCompletedTaskCount(subject: Subject): Int { return subjectTasksCollection(subject) - .nonArchived() - .completed() + .taskNotArchived() + .taskNotCompleted() .count() .get(AggregateSource.SERVER) .await() @@ -83,4 +86,10 @@ class FireBaseSubjectDAO @Inject constructor( .collection(FireBaseCollections.SUBJECT_COLLECTION) .document(subject.id) .collection(FireBaseCollections.TASK_COLLECTION) + + fun CollectionReference.subjectNotArchived(): Query = + this.whereEqualTo(SubjectDocument.archived, false) + + fun Query.subjectNotArchived(): Query = + this.whereEqualTo(SubjectDocument.archived, false) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt index bde5c6f..685b237 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FireBaseTaskDAO.kt @@ -21,7 +21,7 @@ class FireBaseTaskDAO @Inject constructor( ) : TaskDAO { override fun getTasks(subject: Subject): Flow> { return selectedSubjectTasksCollection(subject.id) - .nonArchived() + .taskNotArchived() .snapshots() .map { it.toObjects(Task::class.java) } } @@ -55,14 +55,14 @@ class FireBaseTaskDAO @Inject constructor( // Extend CollectionReference and Query with some filters -fun CollectionReference.nonArchived(): Query = +fun CollectionReference.taskNotArchived(): Query = this.whereEqualTo(TaskDocument.archived, false) -fun Query.nonArchived(): Query = +fun Query.taskNotArchived(): Query = this.whereEqualTo(TaskDocument.archived, false) -fun CollectionReference.completed(): Query = +fun CollectionReference.taskNotCompleted(): Query = this.whereEqualTo(TaskDocument.completed, true) -fun Query.completed(): Query = +fun Query.taskNotCompleted(): Query = this.whereEqualTo(TaskDocument.completed, true) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt index 37a9e5b..533123b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormViewModel.kt @@ -70,7 +70,7 @@ class SubjectEditFormViewModel @Inject constructor( ) fun onDelete(openAndPopUp: (String, String) -> Unit) { - subjectDAO.deleteSubject(selectedSubject()) + subjectDAO.updateSubject(selectedSubject().copy(archived = true)) openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt index 1b56bc6..7760d84 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt @@ -27,7 +27,6 @@ data class TaskActions( val addTask: () -> Unit, val getSubject: () -> Subject, val getTasks: () -> Flow>, - val deleteTask: (Task) -> Unit, val onCheckTask: (Task, Boolean) -> Unit, val editSubject: () -> Unit, val startTask: (Task) -> Unit, @@ -39,7 +38,6 @@ fun getTaskActions(viewModel: TaskViewModel, open: (String) -> Unit): TaskAction addTask = { viewModel.addTask(open) }, getTasks = viewModel::getTasks, getSubject = viewModel::getSelectedSubject, - deleteTask = viewModel::deleteTask, onCheckTask = { task, isChecked -> viewModel.toggleTaskCompleted(task, isChecked) }, editSubject = { viewModel.editSubject(open) }, startTask = { task -> viewModel.startTask(task, open) }, @@ -110,7 +108,6 @@ fun TaskScreenPreview() { {}, { Subject(name = "Test Subject") }, { flowOf() }, - {}, { _, _ -> run {} }, {}, {}, From 6a560fee795e95cf7d726454849f91e7dda31d61 Mon Sep 17 00:00:00 2001 From: lbarraga Date: Tue, 9 May 2023 22:29:07 +0200 Subject: [PATCH 78/87] button on feed not visible when task is checked --- .../common/composable/ButtonComposable.kt | 3 ++- .../common/composable/feed/FeedEntry.kt | 25 +++++++++++++------ .../studeez/data/local/models/FeedEntry.kt | 3 ++- .../domain/implementation/FirebaseFeedDAO.kt | 3 ++- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt index 73ae1b5..0ba2ffe 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt @@ -20,6 +20,7 @@ import androidx.compose.material.icons.filled.Add import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -84,7 +85,7 @@ fun StealthButton( backgroundColor = MaterialTheme.colors.surface, contentColor = MaterialTheme.colors.onSurface.copy(alpha = 0.4f) ), - border = BorderStroke(3.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.4f)) + border = BorderStroke(2.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.4f)) ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt index 6dce710..76c9075 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt @@ -4,7 +4,10 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Card +import androidx.compose.material.Icon import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Info import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -16,6 +19,7 @@ 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.StealthButton +import be.ugent.sel.studeez.common.ext.fieldModifier import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds @@ -69,13 +73,20 @@ fun FeedEntry( Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString()) } } - StealthButton( - text = R.string.continue_task, - modifier = Modifier - .padding(start = 10.dp, end = 5.dp) - .weight(6f) - ) { - continueWithTask() + if (!feedEntry.isArchived) { + StealthButton( + text = R.string.continue_task, + modifier = Modifier + .padding(start = 10.dp, end = 5.dp) + .weight(6f) + ) { + continueWithTask() + } + } else { + Row { + Icon(imageVector = Icons.Default.Info, contentDescription = null) + Text(text = "Deleted", modifier = Modifier.padding(horizontal = 5.dp)) + } } } } diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt index e24cd24..8733c48 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/FeedEntry.kt @@ -9,5 +9,6 @@ data class FeedEntry( val taskId: String = "", // Name of task is not unique val subjectId: String = "", val totalStudyTime: Int = 0, - val endTime: Timestamp = Timestamp(0, 0) + val endTime: Timestamp = Timestamp(0, 0), + val isArchived: Boolean = false ) diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index c116fbf..88142fb 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -72,7 +72,8 @@ class FirebaseFeedDAO @Inject constructor( taskId = task.id, subjectId = subject.id, totalStudyTime = sessionReport.studyTime, - endTime = sessionReport.endTime + endTime = sessionReport.endTime, + isArchived = task.completed ) } } \ No newline at end of file From a5b98d6bf824110efe31f7d59348da733bcda76b Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 22:38:23 +0200 Subject: [PATCH 79/87] move new-task button to top --- .../be/ugent/sel/studeez/data/local/models/task/Task.kt | 6 +----- .../java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt index e42ce5d..ff2748d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/task/Task.kt @@ -9,11 +9,7 @@ data class Task( val time: Int = 0, val subjectId: String = "", var archived: Boolean = false, -) { - fun archive() { - this.archived = true - } -} +) object TaskDocument { const val id = "id" diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt index 7760d84..acdb64b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt @@ -71,6 +71,7 @@ fun TaskScreen( Column( modifier = Modifier.padding(top = 5.dp) ) { + NewTaskSubjectButton(onClick = taskActions.addTask, AppText.new_task) LazyColumn { items(tasks.value) { TaskEntry( @@ -81,7 +82,6 @@ fun TaskScreen( ) } } - NewTaskSubjectButton(onClick = taskActions.addTask, AppText.new_task) } } } From 7706c2d070af9a9a8e7f24fc29fa0c9afaf2f5d0 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 22:44:08 +0200 Subject: [PATCH 80/87] #22 sort tasks by completed --- .../be/ugent/sel/studeez/screens/tasks/TaskScreen.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt index acdb64b..516b836 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/tasks/TaskScreen.kt @@ -73,7 +73,15 @@ fun TaskScreen( ) { NewTaskSubjectButton(onClick = taskActions.addTask, AppText.new_task) LazyColumn { - items(tasks.value) { + items(tasks.value.filter { !it.completed }) { + TaskEntry( + task = it, + onCheckTask = { isChecked -> taskActions.onCheckTask(it, isChecked) }, + onArchiveTask = { taskActions.archiveTask(it) }, + onStartTask = { taskActions.startTask(it) } + ) + } + items(tasks.value.filter { it.completed }) { TaskEntry( task = it, onCheckTask = { isChecked -> taskActions.onCheckTask(it, isChecked) }, From 875732fd2dd0604917742e496720c4619f9f888f Mon Sep 17 00:00:00 2001 From: lbarraga Date: Tue, 9 May 2023 23:12:52 +0200 Subject: [PATCH 81/87] changed stealthbutton to blue + disbale feed continue when task or subject is archived --- .../common/composable/ButtonComposable.kt | 12 +++++++-- .../common/composable/feed/FeedEntry.kt | 27 ++++++++----------- .../sel/studeez/common/ext/ModifierExt.kt | 11 ++++++++ .../domain/implementation/FirebaseFeedDAO.kt | 2 +- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt index 0ba2ffe..c96994d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/ButtonComposable.kt @@ -2,6 +2,7 @@ package be.ugent.sel.studeez.common.composable import androidx.annotation.StringRes import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -49,6 +50,7 @@ fun BasicButton( modifier: Modifier = Modifier, colors: ButtonColors = ButtonDefaults.buttonColors(), border: BorderStroke? = null, + enabled: Boolean = true, onClick: () -> Unit, ) { Button( @@ -57,6 +59,7 @@ fun BasicButton( shape = defaultButtonShape(), colors = colors, border = border, + enabled = enabled, ) { Text( text = stringResource(text), @@ -75,17 +78,22 @@ fun BasicButtonPreview() { fun StealthButton( @StringRes text: Int, modifier: Modifier = Modifier.card(), + enabled: Boolean = true, onClick: () -> Unit, ) { + //val clickablemodifier = if (disabled) Modifier.clickable(indication = null) else modifier + val borderColor = if (enabled) MaterialTheme.colors.primary + else MaterialTheme.colors.onSurface.copy(alpha = 0.3f) BasicButton( text = text, onClick = onClick, modifier = modifier, + enabled = enabled, colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.surface, - contentColor = MaterialTheme.colors.onSurface.copy(alpha = 0.4f) + contentColor = borderColor ), - border = BorderStroke(2.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.4f)) + border = BorderStroke(2.dp, borderColor) ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt index 76c9075..179a9c0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt @@ -4,10 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Card -import androidx.compose.material.Icon import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Info import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -19,9 +16,9 @@ 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.StealthButton -import be.ugent.sel.studeez.common.ext.fieldModifier import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import be.ugent.sel.studeez.R.string as AppText @Composable fun FeedEntry( @@ -73,21 +70,19 @@ fun FeedEntry( Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString()) } } - if (!feedEntry.isArchived) { - StealthButton( - text = R.string.continue_task, - modifier = Modifier - .padding(start = 10.dp, end = 5.dp) - .weight(6f) - ) { + val buttonText: Int = if (feedEntry.isArchived) AppText.deleted else AppText.continue_task + StealthButton( + text = buttonText, + enabled = !feedEntry.isArchived, + modifier = Modifier + .padding(start = 10.dp, end = 5.dp) + .weight(6f) + ) { + if (!feedEntry.isArchived) { continueWithTask() } - } else { - Row { - Icon(imageVector = Icons.Default.Info, contentDescription = null) - Text(text = "Deleted", modifier = Modifier.padding(horizontal = 5.dp)) - } } + } } } diff --git a/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt b/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt index 7280ab3..8c96232 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt @@ -1,14 +1,25 @@ package be.ugent.sel.studeez.common.ext +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.composed import androidx.compose.ui.unit.dp fun Modifier.textButton(): Modifier { return this.fillMaxWidth().padding(16.dp, 8.dp, 16.dp, 0.dp) } +fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier = composed { + clickable(indication = null, + interactionSource = remember { MutableInteractionSource() }) { + onClick() + } +} + fun Modifier.basicButton(): Modifier { return this.fillMaxWidth().padding(16.dp, 8.dp) } diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt index b46b9d0..6c445bf 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseFeedDAO.kt @@ -75,7 +75,7 @@ class FirebaseFeedDAO @Inject constructor( subjectId = subject.id, totalStudyTime = sessionReport.studyTime, endTime = sessionReport.endTime, - isArchived = task.completed + isArchived = task.archived || subject.archived ) } } \ No newline at end of file From 43ccab6d083812a674fe3898dc372aad6212812b Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 23:20:24 +0200 Subject: [PATCH 82/87] fix missing rescource string --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d58be52..e5ed407 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,6 +31,7 @@ Continue + Deleted This is your feed Create you first subject and tasks to get started From 08b86c15dd12861a8dfa602daa863c8c10ae85e5 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 23:23:11 +0200 Subject: [PATCH 83/87] fix hint not very clear --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e5ed407..70c4558 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -33,7 +33,7 @@ Continue Deleted This is your feed - Create you first subject and tasks to get started + Click here to create you first subject and tasks to get started Tasks From 25ed3dfdd22a783f39463db3820cde5cb7c5a1d0 Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 23:25:39 +0200 Subject: [PATCH 84/87] add feedentry overflow preview -> needs fixing --- .../common/composable/feed/FeedEntry.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt index 179a9c0..ff950d6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/feed/FeedEntry.kt @@ -14,7 +14,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow 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.StealthButton import be.ugent.sel.studeez.data.local.models.FeedEntry import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds @@ -70,7 +69,8 @@ fun FeedEntry( Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString()) } } - val buttonText: Int = if (feedEntry.isArchived) AppText.deleted else AppText.continue_task + val buttonText: Int = + if (feedEntry.isArchived) AppText.deleted else AppText.continue_task StealthButton( text = buttonText, enabled = !feedEntry.isArchived, @@ -90,6 +90,20 @@ fun FeedEntry( @Preview @Composable fun FeedEntryPreview() { + FeedEntry( + continueWithTask = {}, + feedEntry = FeedEntry( + argb_color = 0xFFFFD200, + subJectName = "Test Subject", + taskName = "Test Task", + totalStudyTime = 20, + ) + ) +} + +@Preview +@Composable +fun FeedEntryOverflowPreview() { FeedEntry( continueWithTask = {}, feedEntry = FeedEntry( From 3c1bc9bb1b6024b770636a7c573e826f3261fc1b Mon Sep 17 00:00:00 2001 From: brreynie Date: Tue, 9 May 2023 23:51:05 +0200 Subject: [PATCH 85/87] refactored all states to communicate between viewmodels --- .../ugent/sel/studeez/data/EditTimerState.kt | 11 ----- .../ugent/sel/studeez/data/SelectedState.kt | 45 +++++++++++++++++++ .../ugent/sel/studeez/data/SelectedSubject.kt | 20 --------- .../be/ugent/sel/studeez/data/SelectedTask.kt | 21 --------- .../sel/studeez/data/SelectedTimerState.kt | 14 ------ .../sel/studeez/data/SessionReportState.kt | 14 ------ .../screens/session/SessionViewModel.kt | 20 ++++----- .../session_recap/SessionRecapViewModel.kt | 11 +++-- .../screens/timer_form/TimerFormViewModel.kt | 9 ++-- .../TimerTypeSelectViewModel.kt | 6 +-- .../timer_overview/TimerOverviewViewModel.kt | 12 ++--- .../TimerSelectionViewModel.kt | 10 ++--- .../InvisibleSessionManagerTest.kt | 10 ++--- 13 files changed, 78 insertions(+), 125 deletions(-) delete mode 100644 app/src/main/java/be/ugent/sel/studeez/data/EditTimerState.kt create mode 100644 app/src/main/java/be/ugent/sel/studeez/data/SelectedState.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/data/SelectedSubject.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/data/SelectedTask.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt delete mode 100644 app/src/main/java/be/ugent/sel/studeez/data/SessionReportState.kt 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 deleted file mode 100644 index dceec8c..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/data/EditTimerState.kt +++ /dev/null @@ -1,11 +0,0 @@ -package be.ugent.sel.studeez.data - -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/SelectedState.kt b/app/src/main/java/be/ugent/sel/studeez/data/SelectedState.kt new file mode 100644 index 0000000..c52939f --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/data/SelectedState.kt @@ -0,0 +1,45 @@ +package be.ugent.sel.studeez.data + +import be.ugent.sel.studeez.data.local.models.SessionReport +import be.ugent.sel.studeez.data.local.models.task.Subject +import be.ugent.sel.studeez.data.local.models.task.Task +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 + +/** + * Used to cummunicate between viewmodels. + */ +abstract class SelectedState { + abstract var value: T + operator fun invoke() = value + fun set(newValue: T) { + this.value = newValue + } +} + +@Singleton +class SelectedSessionReport @Inject constructor() : SelectedState() { + override lateinit var value: SessionReport +} + +@Singleton +class SelectedTask @Inject constructor() : SelectedState() { + override lateinit var value: Task +} + +@Singleton +class SelectedTimer @Inject constructor() : SelectedState() { + override lateinit var value: FunctionalTimer +} + +@Singleton +class SelectedSubject @Inject constructor() : SelectedState() { + override lateinit var value: Subject +} + +@Singleton +class SelectedTimerInfo @Inject constructor() : SelectedState() { + override lateinit var value: TimerInfo +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/SelectedSubject.kt b/app/src/main/java/be/ugent/sel/studeez/data/SelectedSubject.kt deleted file mode 100644 index fbc7e48..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/data/SelectedSubject.kt +++ /dev/null @@ -1,20 +0,0 @@ -package be.ugent.sel.studeez.data - -import be.ugent.sel.studeez.data.local.models.task.Subject -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Used to communicate the selected subject from the subject overview other screens. - * Because this is a singleton-class the view-models of both screens observe the same data. - */ -@Singleton -class SelectedSubject @Inject constructor() { - private lateinit var subject: Subject - operator fun invoke() = subject - fun set(subject: Subject) { - this.subject = subject - } - - fun isSet() = this::subject.isInitialized -} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/SelectedTask.kt b/app/src/main/java/be/ugent/sel/studeez/data/SelectedTask.kt deleted file mode 100644 index 9c3f042..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/data/SelectedTask.kt +++ /dev/null @@ -1,21 +0,0 @@ -package be.ugent.sel.studeez.data - -import be.ugent.sel.studeez.data.local.models.task.Task -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Used to communicate the selected task from the task overview other screens. - * Because this is a singleton-class the view-models of both screens observe the same data. - */ -@Singleton -class SelectedTask @Inject constructor() { - private lateinit var task: Task - - operator fun invoke() = task - fun set(task: Task) { - this.task = task - } - - fun isSet() = this::task.isInitialized -} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt b/app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt deleted file mode 100644 index f8fcebd..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt +++ /dev/null @@ -1,14 +0,0 @@ -package be.ugent.sel.studeez.data - -import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Used to communicate the SelectedTimer from the selection screen to the session screen. - * Because this is a singleton-class the view-models of both screens observe the same data. - */ -@Singleton -class SelectedTimerState @Inject constructor(){ - var selectedTimer: FunctionalTimer? = null -} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/SessionReportState.kt b/app/src/main/java/be/ugent/sel/studeez/data/SessionReportState.kt deleted file mode 100644 index 47770d0..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/data/SessionReportState.kt +++ /dev/null @@ -1,14 +0,0 @@ -package be.ugent.sel.studeez.data - -import be.ugent.sel.studeez.data.local.models.SessionReport -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Used to communicate the SelectedTimer from the selection screen to the session screen. - * Because this is a singleton-class the view-models of both screens observe the same data. - */ -@Singleton -class SessionReportState @Inject constructor(){ - var sessionReport: SessionReport? = null -} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt index cd4c93a..0be4147 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt @@ -1,9 +1,8 @@ package be.ugent.sel.studeez.screens.session +import be.ugent.sel.studeez.data.SelectedSessionReport import be.ugent.sel.studeez.data.SelectedTask -import be.ugent.sel.studeez.data.SelectedTimerState -import be.ugent.sel.studeez.data.SessionReportState -import be.ugent.sel.studeez.data.local.models.task.Task +import be.ugent.sel.studeez.data.SelectedTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.navigation.StudeezDestinations @@ -13,24 +12,21 @@ import javax.inject.Inject @HiltViewModel class SessionViewModel @Inject constructor( - private val selectedTimerState: SelectedTimerState, - private val sessionReportState: SessionReportState, + private val selectedTimer: SelectedTimer, + private val sessionReport: SelectedSessionReport, private val selectedTask: SelectedTask, logService: LogService ) : StudeezViewModel(logService) { - - private val task : Task = selectedTask() - - fun getTimer() : FunctionalTimer { - return selectedTimerState.selectedTimer!! + fun getTimer(): FunctionalTimer { + return selectedTimer() } fun getTask(): String { - return task.name + return selectedTask().name } fun endSession(openAndPopUp: (String, String) -> Unit) { - sessionReportState.sessionReport = getTimer().getSessionReport(task.subjectId, task.id) + sessionReport.set(getTimer().getSessionReport(selectedTask().subjectId, selectedTask().id)) openAndPopUp(StudeezDestinations.SESSION_RECAP, StudeezDestinations.SESSION_SCREEN) } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt index 5fdd95c..c11e28f 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapViewModel.kt @@ -1,7 +1,7 @@ package be.ugent.sel.studeez.screens.session_recap +import be.ugent.sel.studeez.data.SelectedSessionReport import be.ugent.sel.studeez.data.SelectedTask -import be.ugent.sel.studeez.data.SessionReportState import be.ugent.sel.studeez.data.local.models.SessionReport import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.SessionDAO @@ -13,22 +13,21 @@ import javax.inject.Inject @HiltViewModel class SessionRecapViewModel @Inject constructor( - sessionReportState: SessionReportState, + private val selectedSessionReport: SelectedSessionReport, private val sessionDAO: SessionDAO, private val taskDAO: TaskDAO, private val selectedTask: SelectedTask, logService: LogService ) : StudeezViewModel(logService) { - private val report: SessionReport = sessionReportState.sessionReport!! - fun getSessionReport(): SessionReport { - return report + return selectedSessionReport() } fun saveSession(open: (String, String) -> Unit) { sessionDAO.saveSession(getSessionReport()) - val newTask = selectedTask().copy(time = selectedTask().time + report.studyTime) + val newTask = + selectedTask().copy(time = selectedTask().time + selectedSessionReport().studyTime) taskDAO.updateTask(newTask) open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt index 4c2079c..8a0a4d4 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormViewModel.kt @@ -1,6 +1,6 @@ package be.ugent.sel.studeez.screens.timer_form -import be.ugent.sel.studeez.data.EditTimerState +import be.ugent.sel.studeez.data.SelectedTimerInfo 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 @@ -10,15 +10,12 @@ import javax.inject.Inject @HiltViewModel class TimerFormViewModel @Inject constructor( - private val editTimerState: EditTimerState, + private val selectedTimerInfo: SelectedTimerInfo, private val timerDAO: TimerDAO, logService: LogService ) : StudeezViewModel(logService) { - - private val timerInfo: TimerInfo = editTimerState.timerInfo - fun getTimerInfo(): TimerInfo { - return timerInfo + return selectedTimerInfo() } fun editTimer(timerInfo: TimerInfo, goBack: () -> Unit) { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt index 569a36c..c3ed2c4 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/timer_type_select/TimerTypeSelectViewModel.kt @@ -1,6 +1,6 @@ package be.ugent.sel.studeez.screens.timer_form.timer_type_select -import be.ugent.sel.studeez.data.EditTimerState +import be.ugent.sel.studeez.data.SelectedTimerInfo import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.navigation.StudeezDestinations @@ -10,13 +10,13 @@ import javax.inject.Inject @HiltViewModel class TimerTypeSelectViewModel @Inject constructor( - private val editTimerState: EditTimerState, + private val selectedTimerInfo: SelectedTimerInfo, logService: LogService ) : StudeezViewModel(logService) { fun onTimerTypeChosen(timerInfo: TimerInfo, open: (String) -> Unit) { - editTimerState.timerInfo = timerInfo + selectedTimerInfo.set(timerInfo) open(StudeezDestinations.ADD_TIMER_SCREEN) } } \ No newline at end of file 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 3e10053..395a155 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,6 +1,6 @@ package be.ugent.sel.studeez.screens.timer_overview -import be.ugent.sel.studeez.data.EditTimerState +import be.ugent.sel.studeez.data.SelectedTimerInfo 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 @@ -15,11 +15,11 @@ import javax.inject.Inject class TimerOverviewViewModel @Inject constructor( private val configurationService: ConfigurationService, private val timerDAO: TimerDAO, - private val editTimerState: EditTimerState, + private val selectedTimerInfo: SelectedTimerInfo, logService: LogService ) : StudeezViewModel(logService) { - fun getUserTimers() : Flow> { + fun getUserTimers(): Flow> { return timerDAO.getUserTimers() } @@ -27,8 +27,8 @@ class TimerOverviewViewModel @Inject constructor( return configurationService.getDefaultTimers() } - fun update(timerInfo: TimerInfo, open: (String) -> Unit) { - editTimerState.timerInfo = timerInfo + fun update(timerInfo: TimerInfo, open: (String) -> Unit) { + selectedTimerInfo.set(timerInfo) open(StudeezDestinations.TIMER_EDIT_SCREEN) } @@ -36,7 +36,7 @@ class TimerOverviewViewModel @Inject constructor( open(StudeezDestinations.TIMER_TYPE_CHOOSING_SCREEN) } - fun delete(timerInfo: TimerInfo) =timerDAO.deleteTimer(timerInfo) + fun delete(timerInfo: TimerInfo) = timerDAO.deleteTimer(timerInfo) fun save(timerInfo: TimerInfo) = timerDAO.saveTimer(timerInfo) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt index a4f646d..c6c6793 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt @@ -1,10 +1,8 @@ package be.ugent.sel.studeez.screens.timer_selection import androidx.compose.runtime.MutableState -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import be.ugent.sel.studeez.data.SelectedTimerState +import be.ugent.sel.studeez.data.SelectedTimer import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo import be.ugent.sel.studeez.domain.LogService @@ -18,7 +16,7 @@ import javax.inject.Inject @HiltViewModel class TimerSelectionViewModel @Inject constructor( private val timerDAO: TimerDAO, - private val selectedTimerState: SelectedTimerState, + private val selectedTimer: SelectedTimer, logService: LogService ) : StudeezViewModel(logService) { @@ -26,12 +24,12 @@ class TimerSelectionViewModel @Inject constructor( HoursMinutesSeconds(1, 0, 0).getTotalSeconds() ) - fun getAllTimers() : Flow> { + fun getAllTimers(): Flow> { return timerDAO.getAllTimers() } fun startSession(open: (String) -> Unit, timerInfo: TimerInfo) { - selectedTimerState.selectedTimer = timerInfo.getFunctionalTimer() + selectedTimer.set(timerInfo.getFunctionalTimer()) open(StudeezDestinations.SESSION_SCREEN) } } \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt index f9e34c3..12b6799 100644 --- a/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt @@ -1,8 +1,6 @@ package be.ugent.sel.studeez.timer_functional import android.media.MediaPlayer -import be.ugent.sel.studeez.data.SelectedTimerState -import be.ugent.sel.studeez.data.SessionReportState import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalCustomTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer @@ -18,14 +16,14 @@ import org.mockito.kotlin.mock @ExperimentalCoroutinesApi class InvisibleSessionManagerTest { - private var timerState: SelectedTimerState = SelectedTimerState() + private var timerState: SelectedTimer = SelectedTimer() private lateinit var viewModel: SessionViewModel private var mediaPlayer: MediaPlayer = mock() @Test fun InvisibleEndlessTimerTest() = runTest { timerState.selectedTimer = FunctionalEndlessTimer() - viewModel = SessionViewModel(timerState, SessionReportState(), mock()) + viewModel = SessionViewModel(timerState, SessionReport(), mock()) InvisibleSessionManager.setParameters(viewModel, mediaPlayer) val test = launch { @@ -47,7 +45,7 @@ class InvisibleSessionManagerTest { val breakTime = 5 val repeats = 1 timerState.selectedTimer = FunctionalPomodoroTimer(studyTime, breakTime, repeats) - viewModel = SessionViewModel(timerState, SessionReportState(), mock()) + viewModel = SessionViewModel(timerState, SessionReport(), mock()) InvisibleSessionManager.setParameters(viewModel, mediaPlayer) val test = launch { @@ -80,7 +78,7 @@ class InvisibleSessionManagerTest { @Test fun InvisibleCustomTimerTest() = runTest { timerState.selectedTimer = FunctionalCustomTimer(5) - viewModel = SessionViewModel(timerState, SessionReportState(), mock()) + viewModel = SessionViewModel(timerState, SessionReport(), mock()) InvisibleSessionManager.setParameters(viewModel, mediaPlayer) val test = launch { From efd92ce832d23d7bd18eb7fcf3119758a9f8a039 Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 09:59:17 +0200 Subject: [PATCH 86/87] fix tests unable to compile --- .../InvisibleSessionManagerTest.kt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt index 12b6799..54f673d 100644 --- a/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/InvisibleSessionManagerTest.kt @@ -1,9 +1,13 @@ package be.ugent.sel.studeez.timer_functional import android.media.MediaPlayer +import be.ugent.sel.studeez.data.SelectedSessionReport +import be.ugent.sel.studeez.data.SelectedTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalCustomTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer +import be.ugent.sel.studeez.domain.LogService +import be.ugent.sel.studeez.domain.implementation.LogServiceImpl import be.ugent.sel.studeez.screens.session.InvisibleSessionManager import be.ugent.sel.studeez.screens.session.SessionViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -16,14 +20,14 @@ import org.mockito.kotlin.mock @ExperimentalCoroutinesApi class InvisibleSessionManagerTest { - private var timerState: SelectedTimer = SelectedTimer() + private var selectedTimer: SelectedTimer = SelectedTimer() private lateinit var viewModel: SessionViewModel private var mediaPlayer: MediaPlayer = mock() @Test fun InvisibleEndlessTimerTest() = runTest { - timerState.selectedTimer = FunctionalEndlessTimer() - viewModel = SessionViewModel(timerState, SessionReport(), mock()) + selectedTimer.set(FunctionalEndlessTimer()) + viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) InvisibleSessionManager.setParameters(viewModel, mediaPlayer) val test = launch { @@ -44,8 +48,8 @@ class InvisibleSessionManagerTest { val studyTime = 10 val breakTime = 5 val repeats = 1 - timerState.selectedTimer = FunctionalPomodoroTimer(studyTime, breakTime, repeats) - viewModel = SessionViewModel(timerState, SessionReport(), mock()) + selectedTimer.set(FunctionalPomodoroTimer(studyTime, breakTime, repeats)) + viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) InvisibleSessionManager.setParameters(viewModel, mediaPlayer) val test = launch { @@ -77,8 +81,8 @@ class InvisibleSessionManagerTest { @Test fun InvisibleCustomTimerTest() = runTest { - timerState.selectedTimer = FunctionalCustomTimer(5) - viewModel = SessionViewModel(timerState, SessionReport(), mock()) + selectedTimer.set(FunctionalCustomTimer(5)) + viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) InvisibleSessionManager.setParameters(viewModel, mediaPlayer) val test = launch { From 59044658e6e3b3a60c4c9ed71732bd9875760d68 Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 10:27:08 +0200 Subject: [PATCH 87/87] Update app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt Co-authored-by: lbarraga --- .../java/be/ugent/sel/studeez/common/ext/ModifierExt.kt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt b/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt index 8c96232..66ade69 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/ext/ModifierExt.kt @@ -13,13 +13,6 @@ fun Modifier.textButton(): Modifier { return this.fillMaxWidth().padding(16.dp, 8.dp, 16.dp, 0.dp) } -fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier = composed { - clickable(indication = null, - interactionSource = remember { MutableInteractionSource() }) { - onClick() - } -} - fun Modifier.basicButton(): Modifier { return this.fillMaxWidth().padding(16.dp, 8.dp) }