commit
1d53752a30
14 changed files with 160 additions and 8 deletions
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
@ -37,6 +37,7 @@ 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.sign_up.SignUpRoute
|
||||
import be.ugent.sel.studeez.screens.splash.SplashRoute
|
||||
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
|
||||
|
@ -166,6 +167,7 @@ fun StudeezNavGraph(
|
|||
composable(StudeezDestinations.SESSION_SCREEN) {
|
||||
SessionRoute(
|
||||
open,
|
||||
openAndPopUp,
|
||||
viewModel = hiltViewModel()
|
||||
)
|
||||
}
|
||||
|
@ -189,5 +191,12 @@ fun StudeezNavGraph(
|
|||
viewModel = hiltViewModel(),
|
||||
)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SESSION_RECAP) {
|
||||
SessionRecapRoute(
|
||||
openAndPopUp = openAndPopUp,
|
||||
viewModel = hiltViewModel()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
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
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package be.ugent.sel.studeez.data.local.models.timer_functional
|
||||
|
||||
import be.ugent.sel.studeez.data.local.models.SessionReport
|
||||
import be.ugent.sel.studeez.screens.session.sessionScreens.CustomSessionScreen
|
||||
import be.ugent.sel.studeez.screens.session.sessionScreens.AbstractSessionScreen
|
||||
|
||||
|
@ -8,6 +9,7 @@ class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) {
|
|||
override fun tick() {
|
||||
if (!hasEnded()) {
|
||||
time.minOne()
|
||||
totalStudyTime++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ class FunctionalEndlessTimer : FunctionalTimer(0) {
|
|||
|
||||
override fun tick() {
|
||||
time.plusOne()
|
||||
totalStudyTime++
|
||||
}
|
||||
|
||||
override fun <T> accept(visitor: FunctionalTimerVisitor<T>): T {
|
||||
|
|
|
@ -26,6 +26,10 @@ class FunctionalPomodoroTimer(
|
|||
isInBreak = !isInBreak
|
||||
}
|
||||
time.minOne()
|
||||
|
||||
if (!isInBreak) {
|
||||
totalStudyTime++
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasEnded(): Boolean {
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
package be.ugent.sel.studeez.data.local.models.timer_functional
|
||||
|
||||
import be.ugent.sel.studeez.data.local.models.SessionReport
|
||||
import be.ugent.sel.studeez.screens.session.sessionScreens.AbstractSessionScreen
|
||||
import com.google.firebase.Timestamp
|
||||
|
||||
abstract class FunctionalTimer(initialValue: Int) {
|
||||
val time: Time = Time(initialValue)
|
||||
var totalStudyTime: Int = 0
|
||||
|
||||
fun getHoursMinutesSeconds(): HoursMinutesSeconds {
|
||||
return time.getAsHMS()
|
||||
|
@ -13,5 +18,12 @@ abstract class FunctionalTimer(initialValue: Int) {
|
|||
|
||||
abstract fun hasCurrentCountdownEnded(): Boolean
|
||||
|
||||
fun getSessionReport(): SessionReport {
|
||||
return SessionReport(
|
||||
studyTime = totalStudyTime,
|
||||
endTime = Timestamp.now()
|
||||
)
|
||||
}
|
||||
|
||||
abstract fun <T> accept(visitor: FunctionalTimerVisitor<T>): T
|
||||
}
|
|
@ -9,6 +9,7 @@ object StudeezDestinations {
|
|||
const val TIMER_OVERVIEW_SCREEN = "timer_overview"
|
||||
const val TIMER_SELECTION_SCREEN = "timer_selection"
|
||||
const val SESSION_SCREEN = "session"
|
||||
const val SESSION_RECAP = "session_recap"
|
||||
// const val TASKS_SCREEN = "tasks"
|
||||
// const val SESSIONS_SCREEN = "sessions"
|
||||
const val PROFILE_SCREEN = "profile"
|
||||
|
|
|
@ -14,23 +14,27 @@ data class SessionActions(
|
|||
val getTask: () -> String,
|
||||
val prepareMediaPlayer: () -> Unit,
|
||||
val releaseMediaPlayer: () -> Unit,
|
||||
val endSession: () -> Unit
|
||||
)
|
||||
|
||||
private fun getSessionActions(
|
||||
viewModel: SessionViewModel,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
mediaplayer: MediaPlayer,
|
||||
): SessionActions {
|
||||
return SessionActions(
|
||||
getTimer = viewModel::getTimer,
|
||||
getTask = viewModel::getTask,
|
||||
endSession = { viewModel.endSession(openAndPopUp) },
|
||||
prepareMediaPlayer = mediaplayer::prepareAsync,
|
||||
releaseMediaPlayer = mediaplayer::release,
|
||||
releaseMediaPlayer = mediaplayer::release
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SessionRoute(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: SessionViewModel,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
@ -58,6 +62,6 @@ fun SessionRoute(
|
|||
|
||||
sessionScreen(
|
||||
open = open,
|
||||
sessionActions = getSessionActions(viewModel, mediaplayer)
|
||||
sessionActions = getSessionActions(viewModel, openAndPopUp, mediaplayer)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
package be.ugent.sel.studeez.screens.session
|
||||
|
||||
import be.ugent.sel.studeez.data.SelectedTimerState
|
||||
import be.ugent.sel.studeez.data.SessionReportState
|
||||
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
|
||||
import be.ugent.sel.studeez.screens.StudeezViewModel
|
||||
import be.ugent.sel.studeez.data.SelectedTimerState
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SessionViewModel @Inject constructor(
|
||||
private val selectedTimerState: SelectedTimerState,
|
||||
private val sessionReportState: SessionReportState,
|
||||
logService: LogService
|
||||
) : StudeezViewModel(logService) {
|
||||
|
||||
private val timer: FunctionalTimer = FunctionalPomodoroTimer(15, 5, 3)
|
||||
private val task : String = "No task selected" // placeholder for tasks implementation
|
||||
|
||||
fun getTimer() : FunctionalTimer {
|
||||
|
@ -24,4 +25,9 @@ class SessionViewModel @Inject constructor(
|
|||
fun getTask(): String {
|
||||
return task
|
||||
}
|
||||
|
||||
fun endSession(openAndPopUp: (String, String) -> Unit) {
|
||||
sessionReportState.sessionReport = getTimer().getSessionReport()
|
||||
openAndPopUp(StudeezDestinations.SESSION_RECAP, StudeezDestinations.SESSION_SCREEN)
|
||||
}
|
||||
}
|
|
@ -47,8 +47,7 @@ abstract class AbstractSessionScreen {
|
|||
TextButton(
|
||||
onClick = {
|
||||
sessionActions.releaseMediaPlayer
|
||||
open(StudeezDestinations.HOME_SCREEN)
|
||||
// Vanaf hier ook naar report gaan als "end session" knop word ingedrukt
|
||||
sessionActions.endSession()
|
||||
},
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 20.dp)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package be.ugent.sel.studeez.screens.session_recap
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import be.ugent.sel.studeez.R
|
||||
import be.ugent.sel.studeez.common.composable.BasicButton
|
||||
import be.ugent.sel.studeez.common.ext.basicButton
|
||||
import be.ugent.sel.studeez.data.local.models.SessionReport
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.Time
|
||||
|
||||
data class SessionRecapActions(
|
||||
val getSessionReport: () -> SessionReport,
|
||||
val saveSession: () -> Unit,
|
||||
val discardSession: () -> Unit
|
||||
)
|
||||
|
||||
fun getSessionRecapActions(
|
||||
viewModel: SessionRecapViewModel,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
): SessionRecapActions {
|
||||
return SessionRecapActions(
|
||||
viewModel::getSessionReport,
|
||||
{viewModel.saveSession(openAndPopUp)},
|
||||
{viewModel.saveSession(openAndPopUp)}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SessionRecapRoute(
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: SessionRecapViewModel,
|
||||
) {
|
||||
SessionRecapScreen(
|
||||
modifier = modifier,
|
||||
getSessionRecapActions(viewModel, openAndPopUp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActions) {
|
||||
val sessionReport: SessionReport = sessionRecapActions.getSessionReport()
|
||||
val studyTime: Int = sessionReport.studyTime
|
||||
val hms: HoursMinutesSeconds = Time(studyTime).getAsHMS()
|
||||
Column {
|
||||
Text(text = "You studied: ${hms.hours} : ${hms.minutes} : ${hms.seconds}")
|
||||
|
||||
BasicButton(
|
||||
R.string.save, Modifier.basicButton()
|
||||
) {
|
||||
sessionRecapActions.saveSession()
|
||||
}
|
||||
BasicButton(
|
||||
R.string.discard, Modifier.basicButton(),
|
||||
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red)
|
||||
) {
|
||||
sessionRecapActions.discardSession()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package be.ugent.sel.studeez.screens.session_recap
|
||||
|
||||
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.navigation.StudeezDestinations
|
||||
import be.ugent.sel.studeez.screens.StudeezViewModel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SessionRecapViewModel @Inject constructor(
|
||||
private val sessionReportState: SessionReportState,
|
||||
private val sessionDAO: SessionDAO,
|
||||
logService: LogService
|
||||
) : StudeezViewModel(logService) {
|
||||
|
||||
private val report: SessionReport = sessionReportState.sessionReport!!
|
||||
|
||||
fun getSessionReport(): SessionReport {
|
||||
return report
|
||||
}
|
||||
|
||||
fun saveSession(open: (String, String) -> Unit) {
|
||||
sessionDAO.saveSession(getSessionReport())
|
||||
open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP)
|
||||
}
|
||||
|
||||
fun discardSession(open: (String, String) -> Unit) {
|
||||
open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP)
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
<!-- Actions -->
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="discard">Discard</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="go_back">Go back</string>
|
||||
<string name="next">Next</string>
|
||||
|
|
Reference in a new issue