From 79ed70bb175bd8fdbc037a83c7c537922fcd7d60 Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 11:49:18 +0200 Subject: [PATCH 01/18] generate random color --- .../studeez/screens/subjects/form/SubjectFormViewModel.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 533123b..e927a13 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 @@ -10,6 +10,7 @@ import be.ugent.sel.studeez.navigation.StudeezDestinations import be.ugent.sel.studeez.screens.StudeezViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject +import kotlin.random.Random abstract class SubjectFormViewModel( protected val subjectDAO: SubjectDAO, @@ -42,9 +43,12 @@ class SubjectCreateFormViewModel @Inject constructor( override val uiState = mutableStateOf(SubjectFormUiState()) fun onCreate(openAndPopUp: (String, String) -> Unit) { + val random = Random + val mask: Long = (0x000000FFL shl random.nextInt(0, 3)).inv() + val randomColor = random.nextLong(0xFF000000L, 0xFFFFFFFFL) and mask val newSubject = Subject( name = name, - argb_color = color, + argb_color = randomColor, ) subjectDAO.saveSubject( newSubject From 00751aaf51f6fd3706fd8cb79790bcd918736607 Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 11:59:28 +0200 Subject: [PATCH 02/18] colorgenerator as extension of Color --- .../java/be/ugent/sel/studeez/common/ext/ColorExt.kt | 10 ++++++++++ .../screens/subjects/form/SubjectFormViewModel.kt | 8 +++----- 2 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/common/ext/ColorExt.kt diff --git a/app/src/main/java/be/ugent/sel/studeez/common/ext/ColorExt.kt b/app/src/main/java/be/ugent/sel/studeez/common/ext/ColorExt.kt new file mode 100644 index 0000000..87ce226 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/common/ext/ColorExt.kt @@ -0,0 +1,10 @@ +package be.ugent.sel.studeez.common.ext + +import androidx.compose.ui.graphics.Color +import kotlin.random.Random + +fun Color.Companion.generateRandomArgb(): Long { + val random = Random + val mask: Long = (0x000000FFL shl random.nextInt(0, 3)).inv() + return random.nextLong(0xFF000000L, 0xFFFFFFFFL) and mask +} \ No newline at end of file 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 e927a13..eb7ee6f 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 @@ -2,6 +2,8 @@ package be.ugent.sel.studeez.screens.subjects.form import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.graphics.Color +import be.ugent.sel.studeez.common.ext.generateRandomArgb import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.domain.LogService @@ -10,7 +12,6 @@ import be.ugent.sel.studeez.navigation.StudeezDestinations import be.ugent.sel.studeez.screens.StudeezViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject -import kotlin.random.Random abstract class SubjectFormViewModel( protected val subjectDAO: SubjectDAO, @@ -43,12 +44,9 @@ class SubjectCreateFormViewModel @Inject constructor( override val uiState = mutableStateOf(SubjectFormUiState()) fun onCreate(openAndPopUp: (String, String) -> Unit) { - val random = Random - val mask: Long = (0x000000FFL shl random.nextInt(0, 3)).inv() - val randomColor = random.nextLong(0xFF000000L, 0xFFFFFFFFL) and mask val newSubject = Subject( name = name, - argb_color = randomColor, + argb_color = Color.generateRandomArgb(), ) subjectDAO.saveSubject( newSubject From d9f4170fbd24c173ee217d90bcbe858dd0c31c98 Mon Sep 17 00:00:00 2001 From: Rune Dyselinck Date: Wed, 10 May 2023 15:10:01 +0200 Subject: [PATCH 03/18] emojis in sessionrecap --- .idea/misc.xml | 1 - .../FloatingActionButtonComposable.kt | 1 - .../common/composable/ImageComposable.kt | 39 +++++++++++ .../session_recap/SessionRecapScreen.kt | 67 ++++++++++++++++++- app/src/main/res/drawable/mood_1.xml | 5 ++ app/src/main/res/drawable/mood_2.xml | 5 ++ app/src/main/res/values/strings.xml | 7 ++ 7 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/common/composable/ImageComposable.kt create mode 100644 app/src/main/res/drawable/mood_1.xml create mode 100644 app/src/main/res/drawable/mood_2.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ad17cb..8978d23 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/FloatingActionButtonComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/FloatingActionButtonComposable.kt index bc40ead..ea2b52d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/common/composable/FloatingActionButtonComposable.kt +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/FloatingActionButtonComposable.kt @@ -2,7 +2,6 @@ package be.ugent.sel.studeez.common.composable import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.border import androidx.compose.foundation.layout.* import androidx.compose.material.FloatingActionButton import androidx.compose.material.Icon diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/ImageComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/ImageComposable.kt new file mode 100644 index 0000000..39e7272 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/ImageComposable.kt @@ -0,0 +1,39 @@ +package be.ugent.sel.studeez.common.composable + +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.unit.dp + +@Composable +fun ImageBackgroundButton( + paint: Painter, + str: String, + background2: Color, + setBackground1: (Color) -> Unit, + setBackground2: (Color) -> Unit +) { + Image( + painter = paint, + str, + modifier = Modifier + .clickable { + if (background2 == Color.Transparent) { + setBackground1(Color.LightGray) + setBackground2(Color.Transparent) + } else { + setBackground2(Color.Transparent) + } + } + .border( + width = 2.dp, + color = background2, + shape = RoundedCornerShape(16.dp) + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index 2d06e0b..1e02ad9 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -1,13 +1,30 @@ package be.ugent.sel.studeez.screens.session_recap +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.material.ButtonDefaults import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +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 androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.BasicButton +import be.ugent.sel.studeez.common.composable.ImageBackgroundButton import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.data.local.models.SessionReport import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds @@ -47,10 +64,49 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi val sessionReport: SessionReport = sessionRecapActions.getSessionReport() val studyTime: Int = sessionReport.studyTime val hms: HoursMinutesSeconds = Time(studyTime).getAsHMS() + val (background1, setBackground1) = remember { mutableStateOf(Color.Transparent) } + val (background2, setBackground2) = remember { mutableStateOf(Color.Transparent) } Column( modifier = modifier + .fillMaxWidth() + .fillMaxHeight() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center ) { - Text(text = "You studied: $hms") + Text( + text = stringResource(R.string.congrats) + hms, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + fontWeight = FontWeight.Light, + fontSize = 30.sp + ) + + Text( + text = stringResource(R.string.how_did_it_go), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + fontWeight = FontWeight.Light, + fontSize = 30.sp + ) + + Row { + ImageBackgroundButton( + paint = painterResource(id = R.drawable.mood_1), + str = stringResource(id = R.string.good), + background2 = background2, + setBackground1 = setBackground2, + setBackground2 = setBackground1 + ) + + ImageBackgroundButton( + paint = painterResource(id = R.drawable.mood_2), + str = stringResource(id = R.string.bad), + background2 = background1, + setBackground1 = setBackground1, + setBackground2 = setBackground2 + ) + } BasicButton( R.string.save, Modifier.basicButton() @@ -65,3 +121,12 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi } } } + +@Preview +@Composable +fun SessionRecapScreenPreview() { + SessionRecapScreen( + modifier = Modifier, + sessionRecapActions = SessionRecapActions(hiltViewModel(), {}, {}) + ) +} \ No newline at end of file diff --git a/app/src/main/res/drawable/mood_1.xml b/app/src/main/res/drawable/mood_1.xml new file mode 100644 index 0000000..bf009f2 --- /dev/null +++ b/app/src/main/res/drawable/mood_1.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/mood_2.xml b/app/src/main/res/drawable/mood_2.xml new file mode 100644 index 0000000..0fd3daa --- /dev/null +++ b/app/src/main/res/drawable/mood_2.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0ec0e9d..9ebb196 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -138,4 +138,11 @@ Break Time Number of Repeats + + "Congratulations! You studied: " + How did it go? + Good + Bad + + From 6bef378fc043d8566fd56301a8477bdbc34d040a Mon Sep 17 00:00:00 2001 From: Rune Dyselinck Date: Wed, 10 May 2023 15:32:39 +0200 Subject: [PATCH 04/18] correct aligment --- .../session_recap/SessionRecapScreen.kt | 83 +++++++++++-------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index 1e02ad9..06a15e1 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -72,52 +72,65 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi .fillMaxHeight() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + verticalArrangement = Arrangement.SpaceBetween ) { Text( text = stringResource(R.string.congrats) + hms, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth(), textAlign = TextAlign.Center, fontWeight = FontWeight.Light, - fontSize = 30.sp + fontSize = 30.sp, + ) - Text( - text = stringResource(R.string.how_did_it_go), - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - fontWeight = FontWeight.Light, - fontSize = 30.sp - ) - - Row { - ImageBackgroundButton( - paint = painterResource(id = R.drawable.mood_1), - str = stringResource(id = R.string.good), - background2 = background2, - setBackground1 = setBackground2, - setBackground2 = setBackground1 + Column( + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = stringResource(R.string.how_did_it_go), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + fontWeight = FontWeight.Light, + fontSize = 30.sp ) - ImageBackgroundButton( - paint = painterResource(id = R.drawable.mood_2), - str = stringResource(id = R.string.bad), - background2 = background1, - setBackground1 = setBackground1, - setBackground2 = setBackground2 - ) + Row( + horizontalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + .align(Alignment.CenterHorizontally) + ) { + ImageBackgroundButton( + paint = painterResource(id = R.drawable.mood_1), + str = stringResource(id = R.string.good), + background2 = background2, + setBackground1 = setBackground2, + setBackground2 = setBackground1 + ) + + ImageBackgroundButton( + paint = painterResource(id = R.drawable.mood_2), + str = stringResource(id = R.string.bad), + background2 = background1, + setBackground1 = setBackground1, + setBackground2 = setBackground2 + ) + } } - BasicButton( - R.string.save, Modifier.basicButton() - ) { - sessionRecapActions.saveSession() - } - BasicButton( - R.string.discard, Modifier.basicButton(), - colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red) - ) { - sessionRecapActions.discardSession() + Column { + BasicButton( + R.string.save, Modifier.basicButton() + ) { + sessionRecapActions.saveSession() + } + BasicButton( + R.string.discard, Modifier.basicButton(), + colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red) + ) { + sessionRecapActions.discardSession() + } } } } From 45efd5cb3f82d7abeb68edbaef14b28501c3737a Mon Sep 17 00:00:00 2001 From: Rune Dyselinck Date: Wed, 10 May 2023 15:37:34 +0200 Subject: [PATCH 05/18] small fix --- .../sel/studeez/screens/session_recap/SessionRecapScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index 06a15e1..72082c8 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -142,4 +142,4 @@ fun SessionRecapScreenPreview() { modifier = Modifier, sessionRecapActions = SessionRecapActions(hiltViewModel(), {}, {}) ) -} \ No newline at end of file +} From de25ed85b53746ae704d87c1a3729afacbe1554a Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 15:50:54 +0200 Subject: [PATCH 06/18] #99 fix subjectentry to use flows for computed values --- .../common/composable/tasks/SubjectEntry.kt | 16 +++++++--- .../studeez/data/local/models/task/Subject.kt | 4 --- .../be/ugent/sel/studeez/domain/SubjectDAO.kt | 4 +-- .../implementation/FireBaseSubjectDAO.kt | 31 +++++-------------- .../studeez/screens/subjects/SubjectScreen.kt | 13 ++++++-- .../screens/subjects/SubjectViewModel.kt | 8 +++++ 6 files changed, 40 insertions(+), 36 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 5db2af3..c6631ce 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 @@ -31,9 +31,13 @@ import be.ugent.sel.studeez.R.string as AppText fun SubjectEntry( subject: Subject, onViewSubject: () -> Unit, + getTaskCount: () -> Flow, + getCompletedTaskCount: () -> Flow, getStudyTime: () -> Flow, ) { val studytime by getStudyTime().collectAsState(initial = 0) + val taskCount by getTaskCount().collectAsState(initial = 0) + val completedTaskCount by getCompletedTaskCount().collectAsState(initial = 0) Card( modifier = Modifier .fillMaxWidth() @@ -80,7 +84,7 @@ fun SubjectEntry( imageVector = Icons.Default.List, contentDescription = stringResource(id = AppText.tasks) ) - Text(text = "${subject.taskCompletedCount}/${subject.taskCount}") + Text(text = "${completedTaskCount}/${taskCount}") } } } @@ -104,11 +108,11 @@ fun SubjectEntryPreview() { subject = Subject( name = "Test Subject", argb_color = 0xFFFFD200, - taskCount = 5, - taskCompletedCount = 2, ), onViewSubject = {}, - getStudyTime = { flowOf() } + getTaskCount = { flowOf() }, + getCompletedTaskCount = { flowOf() }, + getStudyTime = { flowOf() }, ) } @@ -121,6 +125,8 @@ fun OverflowSubjectEntryPreview() { argb_color = 0xFFFFD200, ), onViewSubject = {}, - getStudyTime = { flowOf() } + getTaskCount = { flowOf() }, + getCompletedTaskCount = { flowOf() }, + getStudyTime = { flowOf() }, ) } \ 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 74ebe9f..261f3e0 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 @@ -8,10 +8,6 @@ data class Subject( 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, ) object SubjectDocument { 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 bad8106..c9f6a8a 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 @@ -13,8 +13,8 @@ interface SubjectDAO { fun updateSubject(newSubject: Subject) - suspend fun getTaskCount(subject: Subject): Int - suspend fun getCompletedTaskCount(subject: Subject): Int + fun getTaskCount(subject: Subject): Flow + fun getCompletedTaskCount(subject: Subject): Flow fun getStudyTime(subject: Subject): Flow suspend fun getSubject(subjectId: String): Subject? 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 b023986..e8931ed 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 @@ -2,10 +2,10 @@ 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.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.AggregateSource import com.google.firebase.firestore.CollectionReference import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.Query @@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.tasks.await import javax.inject.Inject +import kotlin.collections.count class FireBaseSubjectDAO @Inject constructor( private val firestore: FirebaseFirestore, @@ -26,13 +27,6 @@ class FireBaseSubjectDAO @Inject constructor( .subjectNotArchived() .snapshots() .map { it.toObjects(Subject::class.java) } - .map { subjects -> - subjects.map { subject -> - subject.taskCount = getTaskCount(subject) - subject.taskCompletedCount = getCompletedTaskCount(subject) - subject - } - } } override suspend fun getSubject(subjectId: String): Subject? { @@ -51,23 +45,14 @@ class FireBaseSubjectDAO @Inject constructor( currentUserSubjectsCollection().document(newSubject.id).set(newSubject) } - override suspend fun getTaskCount(subject: Subject): Int { - return subjectTasksCollection(subject) - .taskNotArchived() - .count() - .get(AggregateSource.SERVER) - .await() - .count.toInt() + override fun getTaskCount(subject: Subject): Flow { + return taskDAO.getTasks(subject) + .map(List::count) } - override suspend fun getCompletedTaskCount(subject: Subject): Int { - return subjectTasksCollection(subject) - .taskNotArchived() - .taskNotCompleted() - .count() - .get(AggregateSource.SERVER) - .await() - .count.toInt() + override fun getCompletedTaskCount(subject: Subject): Flow { + return taskDAO.getTasks(subject) + .map { tasks -> tasks.count { it.completed && !it.archived } } } override fun getStudyTime(subject: Subject): Flow { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt index ab2cff4..852c0e5 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectScreen.kt @@ -36,6 +36,8 @@ fun SubjectRoute( navigationBarActions = navigationBarActions, onAddSubject = { viewModel.onAddSubject(open) }, onViewSubject = { viewModel.onViewSubject(it, open) }, + getTaskCount = viewModel::getTaskCount, + getCompletedTaskCount = viewModel::getCompletedTaskCount, getStudyTime = viewModel::getStudyTime, uiState, ) @@ -47,6 +49,8 @@ fun SubjectScreen( navigationBarActions: NavigationBarActions, onAddSubject: () -> Unit, onViewSubject: (Subject) -> Unit, + getTaskCount: (Subject) -> Flow, + getCompletedTaskCount: (Subject) -> Flow, getStudyTime: (Subject) -> Flow, uiState: SubjectUiState, ) { @@ -76,6 +80,8 @@ fun SubjectScreen( SubjectEntry( subject = it, onViewSubject = { onViewSubject(it) }, + getTaskCount = { getTaskCount(it) }, + getCompletedTaskCount = { getCompletedTaskCount(it) }, getStudyTime = { getStudyTime(it) }, ) } @@ -94,13 +100,14 @@ fun SubjectScreenPreview() { navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), onAddSubject = {}, onViewSubject = {}, + getTaskCount = { flowOf() }, + getCompletedTaskCount = { flowOf() }, getStudyTime = { flowOf() }, uiState = SubjectUiState.Succes( listOf( Subject( name = "Test Subject", argb_color = 0xFFFFD200, - taskCount = 5, taskCompletedCount = 2, ) ) ) @@ -115,7 +122,9 @@ fun SubjectScreenLoadingPreview() { navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}), onAddSubject = {}, onViewSubject = {}, + getTaskCount = { flowOf() }, + getCompletedTaskCount = { flowOf() }, getStudyTime = { flowOf() }, - uiState = SubjectUiState.Loading + uiState = SubjectUiState.Loading, ) } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt index c158529..19ba396 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/SubjectViewModel.kt @@ -30,6 +30,14 @@ class SubjectViewModel @Inject constructor( open(StudeezDestinations.ADD_SUBJECT_FORM) } + fun getTaskCount(subject: Subject): Flow { + return subjectDAO.getTaskCount(subject) + } + + fun getCompletedTaskCount(subject: Subject): Flow { + return subjectDAO.getCompletedTaskCount(subject) + } + fun getStudyTime(subject: Subject): Flow { return subjectDAO.getStudyTime(subject) } From a7752e5706128163c8210dec9e906f358c2ad1ad Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 16:43:14 +0200 Subject: [PATCH 07/18] #99 fix update subject name after edit --- .../screens/subjects/form/SubjectFormViewModel.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 533123b..7c2f601 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 @@ -75,11 +75,13 @@ class SubjectEditFormViewModel @Inject constructor( } fun onEdit(openAndPopUp: (String, String) -> Unit) { - val newSubject = selectedSubject().copy( - name = name, - argb_color = color, + selectedSubject.set( + selectedSubject().copy( + name = name, + argb_color = color, + ) ) - subjectDAO.updateSubject(newSubject) + subjectDAO.updateSubject(selectedSubject()) openAndPopUp(StudeezDestinations.TASKS_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM) } } \ No newline at end of file From 61de50ea557bcf2f736b718a326210f7db7fe806 Mon Sep 17 00:00:00 2001 From: brreynie Date: Wed, 10 May 2023 16:52:41 +0200 Subject: [PATCH 08/18] reformat and optimize imports --- .../screens/session_recap/SessionRecapScreen.kt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index 72082c8..f3a5739 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -1,11 +1,6 @@ package be.ugent.sel.studeez.screens.session_recap -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.material.ButtonDefaults import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -42,8 +37,8 @@ fun getSessionRecapActions( ): SessionRecapActions { return SessionRecapActions( viewModel::getSessionReport, - {viewModel.saveSession(openAndPopUp)}, - {viewModel.discardSession(openAndPopUp)} + { viewModel.saveSession(openAndPopUp) }, + { viewModel.discardSession(openAndPopUp) } ) } @@ -82,7 +77,7 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi fontWeight = FontWeight.Light, fontSize = 30.sp, - ) + ) Column( modifier = Modifier.fillMaxWidth() From 93aae20f85bc9390082e95e84b019dcaf5880693 Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 13:22:12 +0200 Subject: [PATCH 09/18] #109 archiving subject archives all tasks of subject --- .../java/be/ugent/sel/studeez/domain/SubjectDAO.kt | 2 ++ .../domain/implementation/FireBaseSubjectDAO.kt | 14 ++++++++++++++ .../screens/subjects/form/SubjectFormScreen.kt | 7 ++++++- .../screens/subjects/form/SubjectFormViewModel.kt | 6 ++++-- 4 files changed, 26 insertions(+), 3 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 c9f6a8a..d887ef5 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 @@ -13,6 +13,8 @@ interface SubjectDAO { fun updateSubject(newSubject: Subject) + suspend fun archiveSubject(subject: Subject) + fun getTaskCount(subject: Subject): Flow fun getCompletedTaskCount(subject: Subject): Flow fun getStudyTime(subject: Subject): Flow 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 e8931ed..66815dc 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,8 +1,10 @@ package be.ugent.sel.studeez.domain.implementation +import android.util.Log 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.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.SubjectDAO import be.ugent.sel.studeez.domain.TaskDAO @@ -45,6 +47,18 @@ class FireBaseSubjectDAO @Inject constructor( currentUserSubjectsCollection().document(newSubject.id).set(newSubject) } + override suspend fun archiveSubject(subject: Subject) { + currentUserSubjectsCollection().document(subject.id).update(SubjectDocument.archived, true) + currentUserSubjectsCollection().document(subject.id) + .collection(FireBaseCollections.TASK_COLLECTION) + .taskNotArchived() + .get().await() + .documents + .forEach { + it.reference.update(TaskDocument.archived, true) + } + } + override fun getTaskCount(subject: Subject): Flow { return taskDAO.getTasks(subject) .map(List::count) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index 19e6816..bd81c8c 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.material.OutlinedTextField import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource @@ -16,6 +17,7 @@ import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.common.ext.fieldModifier import be.ugent.sel.studeez.resources +import kotlinx.coroutines.launch import be.ugent.sel.studeez.R.string as AppText @Composable @@ -42,6 +44,7 @@ fun SubjectEditRoute( viewModel: SubjectEditFormViewModel, ) { val uiState by viewModel.uiState + val coroutineScope = rememberCoroutineScope() SubjectForm( title = AppText.edit_subject, goBack = goBack, @@ -51,7 +54,9 @@ fun SubjectEditRoute( onColorChange = {}, ) { DeleteButton(text = AppText.delete_subject) { - viewModel.onDelete(openAndPopUp) + coroutineScope.launch { + viewModel.onDelete(openAndPopUp) + } } } } 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 7c2f601..84162d0 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 @@ -6,6 +6,7 @@ import be.ugent.sel.studeez.data.SelectedSubject import be.ugent.sel.studeez.data.local.models.task.Subject 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 import dagger.hilt.android.lifecycle.HiltViewModel @@ -59,6 +60,7 @@ class SubjectCreateFormViewModel @Inject constructor( @HiltViewModel class SubjectEditFormViewModel @Inject constructor( subjectDAO: SubjectDAO, + private val taskDAO: TaskDAO, selectedSubject: SelectedSubject, logService: LogService, ) : SubjectFormViewModel(subjectDAO, selectedSubject, logService) { @@ -69,8 +71,8 @@ class SubjectEditFormViewModel @Inject constructor( ) ) - fun onDelete(openAndPopUp: (String, String) -> Unit) { - subjectDAO.updateSubject(selectedSubject().copy(archived = true)) + suspend fun onDelete(openAndPopUp: (String, String) -> Unit) { + subjectDAO.archiveSubject(selectedSubject()) openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.EDIT_SUBJECT_FORM) } From d666733abea05e26000b1145ae1039ea6b3878ae Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 15:51:50 +0200 Subject: [PATCH 10/18] #109 fix pomodorotimer doing too many cycles --- .../local/models/timer_functional/FunctionalPomodoroTimer.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 765fbcd..f5237d6 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 @@ -6,14 +6,13 @@ class FunctionalPomodoroTimer( val repeats: Int ) : FunctionalTimer(studyTime) { - var breaksRemaining = repeats + var breaksRemaining = repeats - 1 var isInBreak = false override fun tick() { if (hasEnded()) { return } - if (hasCurrentCountdownEnded()) { if (isInBreak) { breaksRemaining-- From ad0780416db5b6a1464342cf8a1343ab2042a6b1 Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 15:54:59 +0200 Subject: [PATCH 11/18] fix dots not showing up correctly --- .../screens/session/sessionScreens/BreakSessionScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 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 9c59b46..f49a60b 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.repeats - funPomoDoroTimer.breaksRemaining) { + repeat(funPomoDoroTimer.repeats - funPomoDoroTimer.breaksRemaining - 1) { Dot(color = Color.DarkGray) } if (!funPomoDoroTimer.isInBreak) Dot(Color.Green) else Dot(Color.DarkGray) - repeat(funPomoDoroTimer.breaksRemaining - 1) { + repeat(funPomoDoroTimer.breaksRemaining) { Dot(color = Color.Gray) } } From 5f0bdc948fc35e9b916f97dc5f3aaf367a7c2a4d Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 15:57:20 +0200 Subject: [PATCH 12/18] all dots green when ended --- .../sessionScreens/BreakSessionScreen.kt | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 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 f49a60b..f328c5f 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 @@ -4,18 +4,13 @@ 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 import be.ugent.sel.studeez.R.string as AppText @@ -23,7 +18,7 @@ import be.ugent.sel.studeez.R.string as AppText class BreakSessionScreen( private val funPomoDoroTimer: FunctionalPomodoroTimer, private var mediaplayer: MediaPlayer? -): AbstractSessionScreen() { +) : AbstractSessionScreen() { @Composable override fun MidSection() { @@ -37,23 +32,31 @@ class BreakSessionScreen( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { - repeat(funPomoDoroTimer.repeats - funPomoDoroTimer.breaksRemaining - 1) { - Dot(color = Color.DarkGray) - } - if (!funPomoDoroTimer.isInBreak) Dot(Color.Green) else Dot(Color.DarkGray) - repeat(funPomoDoroTimer.breaksRemaining) { - Dot(color = Color.Gray) + if (funPomoDoroTimer.hasEnded()) { + repeat(funPomoDoroTimer.repeats) { + Dot(Color.Green) + } + } else { + repeat(funPomoDoroTimer.repeats - funPomoDoroTimer.breaksRemaining - 1) { + Dot(color = Color.DarkGray) + } + if (!funPomoDoroTimer.isInBreak) Dot(Color.Green) else Dot(Color.DarkGray) + repeat(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)) + Box( + modifier = Modifier + .padding(5.dp) + .size(10.dp) + .clip(CircleShape) + .background(color) + ) } @Composable From 0341fcf137c66987f713c4bde5298f0fdadea866 Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 16:31:03 +0200 Subject: [PATCH 13/18] clear navStack when ending session --- .../be/ugent/sel/studeez/navigation/StudeezNavGraph.kt | 5 +++-- .../screens/session_recap/SessionRecapScreen.kt | 10 +++++----- .../screens/session_recap/SessionRecapViewModel.kt | 8 ++++---- 3 files changed, 12 insertions(+), 11 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 37085f1..0a0e8b4 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 @@ -25,9 +25,9 @@ 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.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.TaskRoute 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 @@ -51,6 +51,7 @@ fun StudeezNavGraph( val open: (String) -> Unit = { appState.navigate(it) } val openAndPopUp: (String, String) -> Unit = { route, popUp -> appState.navigateAndPopUp(route, popUp) } + val clearAndNavigate: (route: String) -> Unit = { route -> appState.clearAndNavigate(route) } val drawerActions: DrawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp) val navigationBarActions: NavigationBarActions = @@ -200,7 +201,7 @@ fun StudeezNavGraph( composable(StudeezDestinations.SESSION_RECAP) { SessionRecapRoute( - openAndPopUp = openAndPopUp, + clearAndNavigate = clearAndNavigate, viewModel = hiltViewModel() ) } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index 2d06e0b..e49c8d6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -21,24 +21,24 @@ data class SessionRecapActions( fun getSessionRecapActions( viewModel: SessionRecapViewModel, - openAndPopUp: (String, String) -> Unit, + clearAndNavigate: (String) -> Unit, ): SessionRecapActions { return SessionRecapActions( viewModel::getSessionReport, - {viewModel.saveSession(openAndPopUp)}, - {viewModel.discardSession(openAndPopUp)} + { viewModel.saveSession(clearAndNavigate) }, + { viewModel.discardSession(clearAndNavigate) } ) } @Composable fun SessionRecapRoute( - openAndPopUp: (String, String) -> Unit, + clearAndNavigate: (String) -> Unit, modifier: Modifier = Modifier, viewModel: SessionRecapViewModel, ) { SessionRecapScreen( modifier = modifier, - getSessionRecapActions(viewModel, openAndPopUp) + getSessionRecapActions(viewModel, clearAndNavigate) ) } 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 c11e28f..bf11b93 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 @@ -24,15 +24,15 @@ class SessionRecapViewModel @Inject constructor( return selectedSessionReport() } - fun saveSession(open: (String, String) -> Unit) { + fun saveSession(open: (String) -> Unit) { sessionDAO.saveSession(getSessionReport()) val newTask = selectedTask().copy(time = selectedTask().time + selectedSessionReport().studyTime) taskDAO.updateTask(newTask) - open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP) + open(StudeezDestinations.HOME_SCREEN) } - fun discardSession(open: (String, String) -> Unit) { - open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP) + fun discardSession(open: (String) -> Unit) { + open(StudeezDestinations.HOME_SCREEN) } } \ No newline at end of file From 05e8951edff72431c8e78493ad3de3258f17ca3a Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 16:48:53 +0200 Subject: [PATCH 14/18] #109 refactor forms to be more consistent --- .../common/composable/FormComposable.kt | 22 +++++++++ .../subjects/form/SubjectFormScreen.kt | 4 +- .../screens/tasks/form/TaskFormScreen.kt | 4 +- .../{TimerFormRoute.kt => TimerFormScreen.kt} | 7 ++- .../form_screens/AbstractTimerFormScreen.kt | 48 ++++++------------- 5 files changed, 46 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/be/ugent/sel/studeez/common/composable/FormComposable.kt rename app/src/main/java/be/ugent/sel/studeez/screens/timer_form/{TimerFormRoute.kt => TimerFormScreen.kt} (87%) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/FormComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/FormComposable.kt new file mode 100644 index 0000000..1fbcfb2 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/FormComposable.kt @@ -0,0 +1,22 @@ +package be.ugent.sel.studeez.common.composable + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun FormComposable( + title: String, + popUp: () -> Unit, + content: @Composable () -> Unit, +) { + SecondaryScreenTemplate(title = title, popUp = popUp) { + Box( + modifier = Modifier.verticalScroll(rememberScrollState()), + ) { + content() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index bd81c8c..26097ce 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.DeleteButton -import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate +import be.ugent.sel.studeez.common.composable.FormComposable import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.common.ext.fieldModifier import be.ugent.sel.studeez.resources @@ -71,7 +71,7 @@ fun SubjectForm( onColorChange: (Color) -> Unit, extraButton: @Composable () -> Unit = {}, ) { - SecondaryScreenTemplate( + FormComposable( title = resources().getString(title), popUp = goBack, ) { 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 92302ea..79c744d 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 @@ -11,7 +11,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.DeleteButton -import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate +import be.ugent.sel.studeez.common.composable.FormComposable import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.common.ext.fieldModifier import be.ugent.sel.studeez.resources @@ -62,7 +62,7 @@ fun TaskForm( onNameChange: (String) -> Unit, extraButton: @Composable () -> Unit = {} ) { - SecondaryScreenTemplate( + FormComposable( title = resources().getString(title), popUp = goBack, ) { 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/TimerFormScreen.kt similarity index 87% rename from app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormRoute.kt rename to app/src/main/java/be/ugent/sel/studeez/screens/timer_form/TimerFormScreen.kt index 0323dc2..542a7f0 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/TimerFormScreen.kt @@ -3,7 +3,7 @@ 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.common.composable.FormComposable import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo import be.ugent.sel.studeez.R.string as AppText @@ -36,7 +36,10 @@ fun TimerFormScreen( ) { val timerFormScreen = getTimerInfo().accept(GetTimerFormScreen()) - SecondaryScreenTemplate(title = stringResource(id = label), popUp = popUp) { + FormComposable( + title = stringResource(id = label), + popUp = popUp + ) { timerFormScreen(onConfirmClick) } } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/AbstractTimerFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/AbstractTimerFormScreen.kt index 5f4a17b..69d02ef 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/AbstractTimerFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_form/form_screens/AbstractTimerFormScreen.kt @@ -1,17 +1,7 @@ package be.ugent.sel.studeez.screens.timer_form.form_screens -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment +import androidx.compose.runtime.* import androidx.compose.ui.Modifier import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.BasicButton @@ -32,32 +22,24 @@ abstract class AbstractTimerFormScreen(private val timerInfo: TimerInfo) { timerInfo.name = name timerInfo.description = description - Column( - verticalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxHeight().verticalScroll(rememberScrollState()), - ) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { + Column { - // Fields that every timer shares (ommited id) - LabelledInputField( - value = name, - onNewValue = { name = it }, - label = R.string.name - ) + // Fields that every timer shares (ommited id) + LabelledInputField( + value = name, + onNewValue = { name = it }, + label = R.string.name + ) - LabelledInputField( - value = description, - onNewValue = { description = it }, - label = AppText.description, - singleLine = false - ) + LabelledInputField( + value = description, + onNewValue = { description = it }, + label = AppText.description, + singleLine = false + ) - ExtraFields() + ExtraFields() - } BasicButton(R.string.save, Modifier.basicButton()) { onSaveClick(timerInfo) } From 4b09a8011c5aeb48cd83f0f40afb141305225297 Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 17:22:40 +0200 Subject: [PATCH 15/18] button to regenerate color --- app/build.gradle | 3 -- .../subjects/form/SubjectFormScreen.kt | 45 +++++++++++++++---- .../subjects/form/SubjectFormUiState.kt | 5 ++- .../subjects/form/SubjectFormViewModel.kt | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a19cbd7..68d4e47 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -123,9 +123,6 @@ dependencies { implementation 'com.google.firebase:firebase-firestore-ktx' implementation 'com.google.firebase:firebase-perf-ktx' implementation 'com.google.firebase:firebase-config-ktx' - - // Colorpicker - implementation 'com.github.skydoves:colorpicker-compose:1.0.2' } // Allow references to generate code diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index 19e6816..da59eda 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -1,20 +1,26 @@ package be.ugent.sel.studeez.screens.subjects.form import androidx.annotation.StringRes +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.Column -import androidx.compose.material.OutlinedTextField +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.DeleteButton +import be.ugent.sel.studeez.common.composable.LabelledInputField import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate import be.ugent.sel.studeez.common.ext.basicButton import be.ugent.sel.studeez.common.ext.fieldModifier +import be.ugent.sel.studeez.common.ext.generateRandomArgb import be.ugent.sel.studeez.resources import be.ugent.sel.studeez.R.string as AppText @@ -31,7 +37,7 @@ fun SubjectCreateRoute( uiState = uiState, onConfirm = { viewModel.onCreate(openAndPopUp) }, onNameChange = viewModel::onNameChange, - onColorChange = {}, + onColorChange = viewModel::onColorChange, ) } @@ -48,7 +54,7 @@ fun SubjectEditRoute( uiState = uiState, onConfirm = { viewModel.onEdit(openAndPopUp) }, onNameChange = viewModel::onNameChange, - onColorChange = {}, + onColorChange = viewModel::onColorChange, ) { DeleteButton(text = AppText.delete_subject) { viewModel.onDelete(openAndPopUp) @@ -63,7 +69,7 @@ fun SubjectForm( uiState: SubjectFormUiState, onConfirm: () -> Unit, onNameChange: (String) -> Unit, - onColorChange: (Color) -> Unit, + onColorChange: (Long) -> Unit, extraButton: @Composable () -> Unit = {}, ) { SecondaryScreenTemplate( @@ -71,13 +77,13 @@ fun SubjectForm( popUp = goBack, ) { Column { - OutlinedTextField( + LabelledInputField( singleLine = true, value = uiState.name, - onValueChange = onNameChange, - placeholder = { Text(stringResource(id = AppText.name)) }, - modifier = Modifier.fieldModifier(), + onNewValue = onNameChange, + label = AppText.name, ) + ColorPicker(onColorChange, uiState) BasicButton( text = AppText.confirm, modifier = Modifier.basicButton(), @@ -88,6 +94,27 @@ fun SubjectForm( } } +@Composable +fun ColorPicker( + onColorChange: (Long) -> Unit, + uiState: SubjectFormUiState, +) { + Button( + onClick = { onColorChange(Color.generateRandomArgb()) }, + modifier = Modifier + .fieldModifier(), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color(uiState.color), +// contentColor = MaterialTheme.colors.onSurface.copy(alpha = 0.4f), + ), + shape = RoundedCornerShape(4.dp), +// border = BorderStroke(1.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.4f)), + elevation = null, + ) { + Text(text = "Regenerate color") + } +} + @Preview @Composable fun AddSubjectFormPreview() { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt index 9fdba01..10a18e8 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormUiState.kt @@ -1,6 +1,9 @@ package be.ugent.sel.studeez.screens.subjects.form +import androidx.compose.ui.graphics.Color +import be.ugent.sel.studeez.common.ext.generateRandomArgb + data class SubjectFormUiState( val name: String = "", - val color: Long = 0xFFFFD200, + val color: Long = Color.generateRandomArgb(), ) \ No newline at end of file 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 eb7ee6f..7847a63 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 @@ -46,7 +46,7 @@ class SubjectCreateFormViewModel @Inject constructor( fun onCreate(openAndPopUp: (String, String) -> Unit) { val newSubject = Subject( name = name, - argb_color = Color.generateRandomArgb(), + argb_color = color, ) subjectDAO.saveSubject( newSubject From 360fb122f73bce5f7bdc6442aed131a7de8c7437 Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 17:24:46 +0200 Subject: [PATCH 16/18] some code polishing --- .../sel/studeez/screens/subjects/form/SubjectFormScreen.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index da59eda..d01061b 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -101,15 +101,11 @@ fun ColorPicker( ) { Button( onClick = { onColorChange(Color.generateRandomArgb()) }, - modifier = Modifier - .fieldModifier(), + modifier = Modifier.fieldModifier(), colors = ButtonDefaults.buttonColors( backgroundColor = Color(uiState.color), -// contentColor = MaterialTheme.colors.onSurface.copy(alpha = 0.4f), ), shape = RoundedCornerShape(4.dp), -// border = BorderStroke(1.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.4f)), - elevation = null, ) { Text(text = "Regenerate color") } From df0325074d04bbf042383d0653eb7e2125ca420a Mon Sep 17 00:00:00 2001 From: brreynie Date: Sat, 13 May 2023 17:29:25 +0200 Subject: [PATCH 17/18] i18n for regenerate button --- .../sel/studeez/screens/subjects/form/SubjectFormScreen.kt | 6 +++--- app/src/main/res/values/strings.xml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt index d01061b..b89a851 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/subjects/form/SubjectFormScreen.kt @@ -1,17 +1,16 @@ package be.ugent.sel.studeez.screens.subjects.form import androidx.annotation.StringRes -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.Column import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults -import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import be.ugent.sel.studeez.common.composable.BasicButton @@ -104,10 +103,11 @@ fun ColorPicker( modifier = Modifier.fieldModifier(), colors = ButtonDefaults.buttonColors( backgroundColor = Color(uiState.color), + contentColor = Color.White, ), shape = RoundedCornerShape(4.dp), ) { - Text(text = "Regenerate color") + Text(text = stringResource(id = AppText.regenerate_color)) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 70c4558..fa27f51 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,6 +46,7 @@ Delete Subject Delete Task View + Regenerate Color Looks like you found the sessions screen! In here, your upcoming studying sessions with friends will be listed. You can accept invites or edit your own. From 9ea4f73187835fe465f9c1db5d409e192d7aa65e Mon Sep 17 00:00:00 2001 From: brreynie Date: Mon, 15 May 2023 20:54:47 +0200 Subject: [PATCH 18/18] i18n improvement --- .../screens/session_recap/SessionRecapScreen.kt | 11 ++++++++--- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt index f3a5739..73f4100 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session_recap/SessionRecapScreen.kt @@ -16,7 +16,6 @@ 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 androidx.hilt.navigation.compose.hiltViewModel import be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.ImageBackgroundButton @@ -70,7 +69,7 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi verticalArrangement = Arrangement.SpaceBetween ) { Text( - text = stringResource(R.string.congrats) + hms, + text = stringResource(R.string.congrats, hms), modifier = Modifier .fillMaxWidth(), textAlign = TextAlign.Center, @@ -135,6 +134,12 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi fun SessionRecapScreenPreview() { SessionRecapScreen( modifier = Modifier, - sessionRecapActions = SessionRecapActions(hiltViewModel(), {}, {}) + sessionRecapActions = SessionRecapActions( + { SessionReport( + studyTime = 100, + ) }, + {}, + {}, + ) ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index be6b7ef..58e952d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -150,7 +150,7 @@ Number of Repeats - "Congratulations! You studied: " + "Congratulations! You studied: %s" How did it go? Good Bad