mediaplayer out of view
This commit is contained in:
		
						commit
						46d60e100b
					
				
					 16 changed files with 326 additions and 271 deletions
				
			
		|  | @ -3,19 +3,27 @@ package be.ugent.sel.studeez.data.local.models.timer_functional | |||
| class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) { | ||||
| 
 | ||||
|     override fun tick() { | ||||
|         if (time.time == 0) { | ||||
|             view = StudyState.DONE | ||||
|         } else { | ||||
|         if (!hasEnded()) { | ||||
|             time.minOne() | ||||
|         } else { | ||||
|             mediaPlayer?.setOnCompletionListener { | ||||
|                 mediaPlayer!!.release() | ||||
|                 mediaPlayer = null | ||||
|             } | ||||
|             mediaPlayer?.start() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun hasEnded(): Boolean { | ||||
|         return view == StudyState.DONE | ||||
|     } | ||||
| 
 | ||||
|     override fun hasCurrentCountdownEnded(): Boolean { | ||||
|         return time.time == 0 | ||||
|     } | ||||
| 
 | ||||
|     override fun hasCurrentCountdownEnded(): Boolean { | ||||
|         return hasEnded() | ||||
|     } | ||||
| 
 | ||||
|     override fun <T> accept(visitor: FunctionalTimerVisitor<T>): T { | ||||
|         return visitor.visitFunctionalCustomTimer(this) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,6 +1,6 @@ | |||
| package be.ugent.sel.studeez.data.local.models.timer_functional | ||||
| 
 | ||||
| class FunctionalEndlessTimer() : FunctionalTimer(0) { | ||||
| class FunctionalEndlessTimer : FunctionalTimer(0) { | ||||
| 
 | ||||
|     override fun hasEnded(): Boolean { | ||||
|         return false | ||||
|  | @ -13,4 +13,8 @@ class FunctionalEndlessTimer() : FunctionalTimer(0) { | |||
|     override fun tick() { | ||||
|         time.plusOne() | ||||
|     } | ||||
| 
 | ||||
|     override fun <T> accept(visitor: FunctionalTimerVisitor<T>): T { | ||||
|         return visitor.visitFunctionalEndlessTimer(this) | ||||
|     } | ||||
| } | ||||
|  | @ -9,18 +9,19 @@ class FunctionalPomodoroTimer( | |||
|     var isInBreak = false | ||||
| 
 | ||||
|     override fun tick() { | ||||
|         if (time.time == 0 && breaksRemaining == 0) { | ||||
|             view = StudyState.DONE | ||||
|         if (hasEnded()) { | ||||
|             mediaPlayer?.setOnCompletionListener { | ||||
|                 mediaPlayer!!.release() | ||||
|                 mediaPlayer = null | ||||
|             } | ||||
|             mediaPlayer?.start() | ||||
|             return | ||||
|         } | ||||
| 
 | ||||
|         if (time.time == 0) { | ||||
|         } else if (hasCurrentCountdownEnded()) { | ||||
|             mediaPlayer?.start() | ||||
|             if (isInBreak) { | ||||
|                 breaksRemaining-- | ||||
|                 view = StudyState.FOCUS_REMAINING | ||||
|                 time.time = studyTime | ||||
|             } else { | ||||
|                 view = StudyState.BREAK | ||||
|                 time.time = breakTime | ||||
|             } | ||||
|             isInBreak = !isInBreak | ||||
|  | @ -29,10 +30,18 @@ class FunctionalPomodoroTimer( | |||
|     } | ||||
| 
 | ||||
|     override fun hasEnded(): Boolean { | ||||
|         return breaksRemaining == 0 && time.time == 0 | ||||
|         return !hasBreaksRemaining() && hasCurrentCountdownEnded() | ||||
|     } | ||||
| 
 | ||||
|     private fun hasBreaksRemaining(): Boolean { | ||||
|         return breaksRemaining > 0 | ||||
|     } | ||||
| 
 | ||||
|     override fun hasCurrentCountdownEnded(): Boolean { | ||||
|         return time.time == 0 | ||||
|     } | ||||
| 
 | ||||
|     override fun <T> accept(visitor: FunctionalTimerVisitor<T>): T { | ||||
|         return visitor.visitFunctionalBreakTimer(this) | ||||
|     } | ||||
| } | ||||
|  | @ -1,8 +1,10 @@ | |||
| package be.ugent.sel.studeez.data.local.models.timer_functional | ||||
| 
 | ||||
| import android.media.MediaPlayer | ||||
| 
 | ||||
| abstract class FunctionalTimer(initialValue: Int) { | ||||
|     var time: Time = Time(initialValue) | ||||
|     var view: StudyState = StudyState.FOCUS | ||||
|     val time: Time = Time(initialValue) | ||||
|     var mediaPlayer: MediaPlayer? = null | ||||
| 
 | ||||
|     fun getHoursMinutesSeconds(): HoursMinutesSeconds { | ||||
|         return time.getAsHMS() | ||||
|  | @ -14,8 +16,5 @@ abstract class FunctionalTimer(initialValue: Int) { | |||
| 
 | ||||
|     abstract fun hasCurrentCountdownEnded(): Boolean | ||||
| 
 | ||||
|     enum class StudyState { | ||||
|         FOCUS, DONE, BREAK, FOCUS_REMAINING | ||||
|     } | ||||
| 
 | ||||
|     abstract fun <T> accept(visitor: FunctionalTimerVisitor<T>): T | ||||
| } | ||||
|  | @ -0,0 +1,11 @@ | |||
| package be.ugent.sel.studeez.data.local.models.timer_functional | ||||
| 
 | ||||
| interface FunctionalTimerVisitor<T> { | ||||
| 
 | ||||
|     fun visitFunctionalCustomTimer(functionalCustomTimer: FunctionalCustomTimer): T | ||||
| 
 | ||||
|     fun visitFunctionalEndlessTimer(functionalEndlessTimer: FunctionalEndlessTimer): T | ||||
| 
 | ||||
|     fun visitFunctionalBreakTimer(functionalPomodoroTimer: FunctionalPomodoroTimer): T | ||||
| 
 | ||||
| } | ||||
|  | @ -1,6 +1,5 @@ | |||
| package be.ugent.sel.studeez.screens.session | ||||
| 
 | ||||
| import android.media.MediaPlayer | ||||
| import kotlinx.coroutines.delay | ||||
| import javax.inject.Singleton | ||||
| import kotlin.time.Duration.Companion.seconds | ||||
|  | @ -8,11 +7,9 @@ import kotlin.time.Duration.Companion.seconds | |||
| @Singleton | ||||
| object InvisibleSessionManager { | ||||
|     private var viewModel: SessionViewModel? = null | ||||
|     private var mediaplayer: MediaPlayer? = null | ||||
| 
 | ||||
|     fun setParameters(viewModel: SessionViewModel, mediaplayer: MediaPlayer) { | ||||
|     fun setParameters(viewModel: SessionViewModel) { | ||||
|         this.viewModel = viewModel | ||||
|         this.mediaplayer = mediaplayer | ||||
|     } | ||||
| 
 | ||||
|     suspend fun updateTimer() { | ||||
|  | @ -20,15 +17,7 @@ object InvisibleSessionManager { | |||
|             while (true) { | ||||
|                 delay(1.seconds) | ||||
|                 viewModel!!.getTimer().tick() | ||||
|                 if (viewModel!!.getTimer().hasCurrentCountdownEnded() && !viewModel!!.getTimer().hasEnded()) { | ||||
|                     mediaplayer?.start() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun removeParameters() { | ||||
|         viewModel = null | ||||
|         mediaplayer = null | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,53 @@ | |||
| package be.ugent.sel.studeez.screens.session | ||||
| 
 | ||||
| import android.media.MediaPlayer | ||||
| import android.media.RingtoneManager | ||||
| import android.net.Uri | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer | ||||
| import be.ugent.sel.studeez.screens.session.sessionScreens.AbstractSessionScreen | ||||
| import be.ugent.sel.studeez.screens.session.sessionScreens.GetSessionScreen | ||||
| 
 | ||||
| data class SessionActions( | ||||
|     val getTimer: () -> FunctionalTimer, | ||||
|     val getTask: () -> String, | ||||
|     val startMediaPlayer: () -> Unit, | ||||
|     val releaseMediaPlayer: () -> Unit, | ||||
| ) | ||||
| 
 | ||||
| private fun getSessionActions( | ||||
|     viewModel: SessionViewModel, | ||||
|     mediaplayer: MediaPlayer, | ||||
| ): SessionActions { | ||||
|     return SessionActions( | ||||
|         getTimer = viewModel::getTimer, | ||||
|         getTask = viewModel::getTask, | ||||
|         startMediaPlayer = mediaplayer::start, | ||||
|         releaseMediaPlayer = mediaplayer::release, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun SessionRoute( | ||||
|     open: (String) -> Unit, | ||||
|     viewModel: SessionViewModel, | ||||
| ) { | ||||
|     val context = LocalContext.current | ||||
|     val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) | ||||
|     val mediaplayer = MediaPlayer.create(context, uri) | ||||
|     mediaplayer.isLooping = false | ||||
| 
 | ||||
|     viewModel.getTimer().mediaPlayer = mediaplayer | ||||
| 
 | ||||
|     InvisibleSessionManager.setParameters( | ||||
|         viewModel = viewModel | ||||
|     ) | ||||
| 
 | ||||
|     val sessionScreen: AbstractSessionScreen = viewModel.getTimer().accept(GetSessionScreen()) | ||||
| 
 | ||||
|     sessionScreen( | ||||
|         open = open, | ||||
|         sessionActions = getSessionActions(viewModel, mediaplayer) | ||||
|     ) | ||||
| } | ||||
|  | @ -1,206 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.session | ||||
| 
 | ||||
| import android.media.MediaPlayer | ||||
| import android.media.RingtoneManager | ||||
| import android.net.Uri | ||||
| import androidx.compose.foundation.background | ||||
| import androidx.compose.foundation.border | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material.TextButton | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.LaunchedEffect | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.runtime.remember | ||||
| import androidx.compose.runtime.setValue | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.Color | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
| 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 be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import androidx.compose.ui.unit.sp | ||||
| import be.ugent.sel.studeez.R | ||||
| 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.data.local.models.timer_functional.FunctionalTimer | ||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer.StudyState | ||||
| import be.ugent.sel.studeez.resources | ||||
| import kotlinx.coroutines.delay | ||||
| import kotlin.time.Duration.Companion.seconds | ||||
| 
 | ||||
| data class SessionActions( | ||||
|     val getTimer: () -> FunctionalTimer, | ||||
|     val getTask: () -> String, | ||||
|     val releaseMediaPlayer: () -> Unit, | ||||
|     val startMediaPlayer: () -> Unit, | ||||
| ) | ||||
| 
 | ||||
| fun getSessionActions( | ||||
|     viewModel: SessionViewModel, | ||||
|     mediaplayer: MediaPlayer, | ||||
| ): SessionActions { | ||||
|     return SessionActions( | ||||
|         getTimer = viewModel::getTimer, | ||||
|         getTask = viewModel::getTask, | ||||
|         releaseMediaPlayer = mediaplayer::release, | ||||
|         startMediaPlayer = mediaplayer::start, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun SessionRoute( | ||||
|     open: (String) -> Unit, | ||||
|     viewModel: SessionViewModel, | ||||
| ) { | ||||
|     val context = LocalContext.current | ||||
|     val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) | ||||
|     val mediaplayer = MediaPlayer.create(context, uri) | ||||
|     mediaplayer.isLooping = false | ||||
| 
 | ||||
|     InvisibleSessionManager.setParameters( | ||||
|         viewModel = viewModel, | ||||
|         mediaplayer = mediaplayer | ||||
|     ) | ||||
| 
 | ||||
|     SessionScreen( | ||||
|         open = open, | ||||
|         sessionActions = getSessionActions(viewModel, mediaplayer) | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun SessionScreen( | ||||
|     open: (String) -> Unit, | ||||
|     sessionActions: SessionActions | ||||
| ) { | ||||
|     Column( | ||||
|         modifier = Modifier.padding(10.dp) | ||||
|     ) { | ||||
|         Timer( | ||||
|             sessionActions = sessionActions | ||||
|         ) | ||||
| 
 | ||||
|         Box( | ||||
|             contentAlignment = Alignment.Center, | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth() | ||||
|                 .padding(50.dp) | ||||
|         ) { | ||||
|             TextButton( | ||||
|                 onClick = { | ||||
|                     sessionActions.releaseMediaPlayer | ||||
|                     InvisibleSessionManager.removeParameters() | ||||
|                     open(StudeezDestinations.HOME_SCREEN) | ||||
|                     // Vanaf hier ook naar report gaan als "end session" knop word ingedrukt | ||||
|                 }, | ||||
|                 modifier = Modifier | ||||
|                     .padding(horizontal = 20.dp) | ||||
|                     .border(1.dp, Color.Red, RoundedCornerShape(32.dp)) | ||||
|                     .background(Color.Transparent) | ||||
|             ) { | ||||
|                 Text( | ||||
|                     text = resources().getString(R.string.end_session), | ||||
|                     color = Color.Red, | ||||
|                     fontWeight = FontWeight.Bold, | ||||
|                     fontSize = 18.sp, | ||||
|                     modifier = Modifier | ||||
|                         .padding(1.dp) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| private fun Timer( | ||||
|     sessionActions: SessionActions | ||||
| ) { | ||||
|     var tikker by remember { mutableStateOf(false) } | ||||
|     LaunchedEffect(tikker) { | ||||
|         delay(1.seconds) | ||||
|         sessionActions.getTimer().tick() | ||||
|         tikker = !tikker | ||||
|     } | ||||
| 
 | ||||
|     if (sessionActions.getTimer().hasCurrentCountdownEnded() && !sessionActions.getTimer().hasEnded()) { | ||||
|         sessionActions.startMediaPlayer | ||||
|     } | ||||
| 
 | ||||
|     val hms = sessionActions.getTimer().getHoursMinutesSeconds() | ||||
|     Column { | ||||
|         Text( | ||||
|             text = "${hms.hours} : ${hms.minutes} : ${hms.seconds}", | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth() | ||||
|                 .padding(50.dp), | ||||
|             textAlign = TextAlign.Center, | ||||
|             fontWeight = FontWeight.Bold, | ||||
|             fontSize = 40.sp, | ||||
|         ) | ||||
|         val stateString: String = when (sessionActions.getTimer().view) { | ||||
|             StudyState.DONE -> resources().getString(R.string.state_done) | ||||
|             StudyState.FOCUS -> resources().getString(R.string.state_focus) | ||||
|             StudyState.BREAK -> resources().getString(R.string.state_take_a_break) | ||||
|             StudyState.FOCUS_REMAINING -> | ||||
|                 (sessionActions.getTimer() as FunctionalPomodoroTimer?)?.breaksRemaining?.let { | ||||
|                     resources().getQuantityString(R.plurals.state_focus_remaining, it, it) | ||||
|                 }.toString() | ||||
|         } | ||||
| 
 | ||||
|         Text( | ||||
|             text = stateString, | ||||
|             modifier = Modifier.fillMaxWidth(), | ||||
|             textAlign = TextAlign.Center, | ||||
|             fontWeight = FontWeight.Light, | ||||
|             fontSize = 30.sp | ||||
|         ) | ||||
| 
 | ||||
|         Box( | ||||
|             contentAlignment = Alignment.Center, | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth() | ||||
|                 .padding(50.dp) | ||||
|         ) { | ||||
|             Box( | ||||
|                 contentAlignment = Alignment.Center, | ||||
|                 modifier = Modifier | ||||
|                     .padding(16.dp) | ||||
|                     .background(Color.Blue, RoundedCornerShape(32.dp)) | ||||
|             ) { | ||||
|                 Text( | ||||
|                     text = sessionActions.getTask(), | ||||
|                     color = Color.White, | ||||
|                     fontSize = 18.sp, | ||||
|                     fontWeight = FontWeight.Bold, | ||||
|                     modifier = Modifier | ||||
|                         .padding(vertical = 4.dp, horizontal = 20.dp) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun TimerPreview() { | ||||
|     Timer(sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {})) | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun SessionPreview() { | ||||
|     SessionScreen( | ||||
|         open = {}, | ||||
|         sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {}) | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
|  | @ -0,0 +1,136 @@ | |||
| package be.ugent.sel.studeez.screens.session.sessionScreens | ||||
| 
 | ||||
| import androidx.compose.foundation.background | ||||
| import androidx.compose.foundation.border | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material.TextButton | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| 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.data.local.models.timer_functional.FunctionalEndlessTimer | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.screens.session.SessionActions | ||||
| import kotlinx.coroutines.delay | ||||
| import kotlin.time.Duration.Companion.seconds | ||||
| 
 | ||||
| abstract class AbstractSessionScreen { | ||||
| 
 | ||||
|     @Composable | ||||
|     operator fun invoke( | ||||
|         open: (String) -> Unit, | ||||
|         sessionActions: SessionActions, | ||||
|     ) { | ||||
|         Column( | ||||
|             modifier = Modifier.padding(10.dp) | ||||
|         ) { | ||||
|             Timer( | ||||
|                 sessionActions = sessionActions, | ||||
|             ) | ||||
|             Box( | ||||
|                 contentAlignment = Alignment.Center, modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .padding(50.dp) | ||||
|             ) { | ||||
|                 TextButton( | ||||
|                     onClick = { | ||||
|                         sessionActions.releaseMediaPlayer | ||||
|                         open(StudeezDestinations.HOME_SCREEN) | ||||
|                         // Vanaf hier ook naar report gaan als "end session" knop word ingedrukt | ||||
|                     }, | ||||
|                     modifier = Modifier | ||||
|                         .padding(horizontal = 20.dp) | ||||
|                         .border(1.dp, Color.Red, RoundedCornerShape(32.dp)) | ||||
|                         .background(Color.Transparent) | ||||
|                 ) { | ||||
|                     Text( | ||||
|                         text = "End session", | ||||
|                         color = Color.Red, | ||||
|                         fontWeight = FontWeight.Bold, | ||||
|                         fontSize = 18.sp, | ||||
|                         modifier = Modifier.padding(1.dp) | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Composable | ||||
|     fun Timer( | ||||
|         sessionActions: SessionActions, | ||||
|     ) { | ||||
|         var tikker by remember { mutableStateOf(false) } | ||||
|         LaunchedEffect(tikker) { | ||||
|             delay(1.seconds) | ||||
|             sessionActions.getTimer().tick() | ||||
|             tikker = !tikker | ||||
|         } | ||||
| 
 | ||||
|         val hms = sessionActions.getTimer().getHoursMinutesSeconds() | ||||
|         Column { | ||||
|             Text( | ||||
|                 text = "${hms.hours} : ${hms.minutes} : ${hms.seconds}", | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .padding(50.dp), | ||||
|                 textAlign = TextAlign.Center, | ||||
|                 fontWeight = FontWeight.Bold, | ||||
|                 fontSize = 40.sp, | ||||
|             ) | ||||
| 
 | ||||
|             Text( | ||||
|                 text = motivationString(), | ||||
|                 modifier = Modifier.fillMaxWidth(), | ||||
|                 textAlign = TextAlign.Center, | ||||
|                 fontWeight = FontWeight.Light, | ||||
|                 fontSize = 30.sp | ||||
|             ) | ||||
| 
 | ||||
|             Box( | ||||
|                 contentAlignment = Alignment.Center, modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .padding(50.dp) | ||||
|             ) { | ||||
|                 Box( | ||||
|                     contentAlignment = Alignment.Center, | ||||
|                     modifier = Modifier | ||||
|                         .padding(16.dp) | ||||
|                         .background(Color.Blue, RoundedCornerShape(32.dp)) | ||||
|                 ) { | ||||
|                     Text( | ||||
|                         text = sessionActions.getTask(), | ||||
|                         color = Color.White, | ||||
|                         fontSize = 18.sp, | ||||
|                         fontWeight = FontWeight.Bold, | ||||
|                         modifier = Modifier.padding(vertical = 4.dp, horizontal = 20.dp) | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Composable | ||||
|     abstract fun motivationString(): String | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun TimerPreview() { | ||||
|     val sessionScreen = object : AbstractSessionScreen() { | ||||
|         @Composable | ||||
|         override fun motivationString(): String = "Test" | ||||
| 
 | ||||
|     } | ||||
|     sessionScreen.Timer(sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {})) | ||||
| } | ||||
|  | @ -0,0 +1,30 @@ | |||
| package be.ugent.sel.studeez.screens.session.sessionScreens | ||||
| 
 | ||||
| import androidx.compose.runtime.Composable | ||||
| 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 | ||||
| 
 | ||||
| class BreakSessionScreen( | ||||
|     private val funPomoDoroTimer: FunctionalPomodoroTimer | ||||
| ): AbstractSessionScreen() { | ||||
| 
 | ||||
|     @Composable | ||||
|     override fun motivationString(): String { | ||||
|         if (funPomoDoroTimer.isInBreak) { | ||||
|             return resources().getString(AppText.state_take_a_break) | ||||
|         } | ||||
| 
 | ||||
|         if (funPomoDoroTimer.hasEnded()) { | ||||
|             return resources().getString(AppText.state_done) | ||||
|         } | ||||
| 
 | ||||
|         return resources().getQuantityString( | ||||
|             R.plurals.state_focus_remaining, | ||||
|             funPomoDoroTimer.breaksRemaining, | ||||
|             funPomoDoroTimer.breaksRemaining | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| package be.ugent.sel.studeez.screens.session.sessionScreens | ||||
| 
 | ||||
| import androidx.compose.runtime.Composable | ||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalCustomTimer | ||||
| import be.ugent.sel.studeez.resources | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| 
 | ||||
| class CustomSessionScreen( | ||||
|     private val functionalTimer: FunctionalCustomTimer | ||||
| ): AbstractSessionScreen() { | ||||
| 
 | ||||
|     @Composable | ||||
|     override fun motivationString(): String { | ||||
|         if (functionalTimer.hasEnded()) { | ||||
|             return resources().getString(AppText.state_done) | ||||
|         } | ||||
|         return resources().getString(AppText.state_focus) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| package be.ugent.sel.studeez.screens.session.sessionScreens | ||||
| 
 | ||||
| import androidx.compose.runtime.Composable | ||||
| import be.ugent.sel.studeez.resources | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| 
 | ||||
| class EndlessSessionScreen : AbstractSessionScreen() { | ||||
| 
 | ||||
|     @Composable | ||||
|     override fun motivationString(): String { | ||||
|         return resources().getString(AppText.state_focus) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,17 @@ | |||
| package be.ugent.sel.studeez.screens.session.sessionScreens | ||||
| 
 | ||||
| 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.data.local.models.timer_functional.FunctionalTimerVisitor | ||||
| 
 | ||||
| class GetSessionScreen : FunctionalTimerVisitor<AbstractSessionScreen> { | ||||
|     override fun visitFunctionalCustomTimer(functionalCustomTimer: FunctionalCustomTimer): AbstractSessionScreen = | ||||
|         CustomSessionScreen(functionalCustomTimer) | ||||
| 
 | ||||
|     override fun visitFunctionalEndlessTimer(functionalEndlessTimer: FunctionalEndlessTimer): AbstractSessionScreen = | ||||
|         EndlessSessionScreen() | ||||
| 
 | ||||
|     override fun visitFunctionalBreakTimer(functionalPomodoroTimer: FunctionalPomodoroTimer): AbstractSessionScreen = | ||||
|         BreakSessionScreen(functionalPomodoroTimer) | ||||
| } | ||||
		Reference in a new issue
	
	 Rune Dyselinck
						Rune Dyselinck