commit
						295f3b730a
					
				
					 7 changed files with 132 additions and 10 deletions
				
			
		
							
								
								
									
										5
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
										
									
										generated
									
									
									
								
							|  | @ -37,5 +37,10 @@ | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|       <option name="previewFile" value="true" /> |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|  |     <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> | ||||||
|  |       <option name="processCode" value="true" /> | ||||||
|  |       <option name="processLiterals" value="true" /> | ||||||
|  |       <option name="processComments" value="true" /> | ||||||
|  |     </inspection_tool> | ||||||
|   </profile> |   </profile> | ||||||
| </component> | </component> | ||||||
|  | @ -11,6 +11,11 @@ class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun hasEnded(): Boolean { |     override fun hasEnded(): Boolean { | ||||||
|  |         return view == StudyState.DONE | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun hasCurrentCountdownEnded(): Boolean { | ||||||
|         return time.time == 0 |         return time.time == 0 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | @ -6,6 +6,10 @@ class FunctionalEndlessTimer() : FunctionalTimer(0) { | ||||||
|         return false |         return false | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     override fun hasCurrentCountdownEnded(): Boolean { | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     override fun tick() { |     override fun tick() { | ||||||
|         time.plusOne() |         time.plusOne() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -31,4 +31,8 @@ class FunctionalPomodoroTimer( | ||||||
|     override fun hasEnded(): Boolean { |     override fun hasEnded(): Boolean { | ||||||
|         return breaksRemaining == 0 && time.time == 0 |         return breaksRemaining == 0 && time.time == 0 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     override fun hasCurrentCountdownEnded(): Boolean { | ||||||
|  |         return time.time == 0 | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | @ -12,6 +12,8 @@ abstract class FunctionalTimer(initialValue: Int) { | ||||||
| 
 | 
 | ||||||
|     abstract fun hasEnded(): Boolean |     abstract fun hasEnded(): Boolean | ||||||
| 
 | 
 | ||||||
|  |     abstract fun hasCurrentCountdownEnded(): Boolean | ||||||
|  | 
 | ||||||
|     enum class StudyState { |     enum class StudyState { | ||||||
|         FOCUS, DONE, BREAK, FOCUS_REMAINING |         FOCUS, DONE, BREAK, FOCUS_REMAINING | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,8 +1,18 @@ | ||||||
| package be.ugent.sel.studeez.screens.session | 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.Column | ||||||
| import androidx.compose.foundation.layout.fillMaxWidth | 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.Text | ||||||
|  | import androidx.compose.material.TextButton | ||||||
|  | import androidx.compose.ui.Alignment | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
| import androidx.compose.runtime.LaunchedEffect | import androidx.compose.runtime.LaunchedEffect | ||||||
| import androidx.compose.runtime.getValue | import androidx.compose.runtime.getValue | ||||||
|  | @ -10,45 +20,106 @@ import androidx.compose.runtime.mutableStateOf | ||||||
| import androidx.compose.runtime.remember | import androidx.compose.runtime.remember | ||||||
| import androidx.compose.runtime.setValue | import androidx.compose.runtime.setValue | ||||||
| import androidx.compose.ui.Modifier | 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.font.FontWeight | ||||||
| import androidx.compose.ui.text.style.TextAlign | import androidx.compose.ui.text.style.TextAlign | ||||||
|  | import androidx.compose.ui.unit.dp | ||||||
|  | import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||||
| import androidx.compose.ui.unit.sp | import androidx.compose.ui.unit.sp | ||||||
| import androidx.hilt.navigation.compose.hiltViewModel | import androidx.hilt.navigation.compose.hiltViewModel | ||||||
| import be.ugent.sel.studeez.R | import be.ugent.sel.studeez.R | ||||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer | 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.data.local.models.timer_functional.FunctionalTimer.StudyState | ||||||
| import be.ugent.sel.studeez.resources | import be.ugent.sel.studeez.resources | ||||||
| import kotlinx.coroutines.delay | import kotlinx.coroutines.delay | ||||||
| import kotlin.time.Duration.Companion.seconds | import kotlin.time.Duration.Companion.seconds | ||||||
| 
 | 
 | ||||||
|  | var timerEnd = false | ||||||
|  | 
 | ||||||
| @Composable | @Composable | ||||||
| fun SessionScreen( | fun SessionScreen( | ||||||
|     open: (String) -> Unit, |     open: (String) -> Unit, | ||||||
|     openAndPopUp: (String, String) -> Unit, |     openAndPopUp: (String, String) -> Unit, | ||||||
|  |     viewModel: SessionViewModel = hiltViewModel() | ||||||
| ) { | ) { | ||||||
|     Timer() |     val context = LocalContext.current | ||||||
|  |     val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) | ||||||
|  |     val mediaplayer = MediaPlayer.create(context, uri) | ||||||
|  |     mediaplayer.setOnCompletionListener { | ||||||
|  |         if (!mediaplayer.isPlaying) { | ||||||
|  |             mediaplayer.stop() | ||||||
|  |         } | ||||||
|  |         if (timerEnd) { | ||||||
|  |             mediaplayer.release() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     mediaplayer.setOnPreparedListener { | ||||||
|  |         mediaplayer.start() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Column( | ||||||
|  |        modifier = Modifier.padding(10.dp) | ||||||
|  |    ) { | ||||||
|  |         Timer(viewModel, mediaplayer) | ||||||
|  | 
 | ||||||
|  |         Box( | ||||||
|  |             contentAlignment = Alignment.Center, | ||||||
|  |             modifier = Modifier | ||||||
|  |                 .fillMaxWidth() | ||||||
|  |                 .padding(50.dp) | ||||||
|  |         ) { | ||||||
|  |             TextButton( | ||||||
|  |                 onClick = { | ||||||
|  |                     mediaplayer.release() | ||||||
|  |                     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 | @Composable | ||||||
| fun Timer(viewModel: SessionViewModel = hiltViewModel()) { | private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: MediaPlayer) { | ||||||
| 
 |     var tikker by remember { mutableStateOf(false) } | ||||||
| 
 |     LaunchedEffect(tikker) { | ||||||
|     var ticker by remember { mutableStateOf(false) } |  | ||||||
|     LaunchedEffect(ticker) { |  | ||||||
|         delay(1.seconds) |         delay(1.seconds) | ||||||
|         viewModel.getTimer().tick() |         viewModel.getTimer().tick() | ||||||
|         ticker = !ticker |         tikker = !tikker | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (viewModel.getTimer().hasCurrentCountdownEnded() && !viewModel.getTimer().hasEnded()) { | ||||||
|  |         mediaplayer.prepare() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!timerEnd && viewModel.getTimer().hasEnded()) { | ||||||
|  |         mediaplayer.prepare() | ||||||
|  |         timerEnd = true // Placeholder, vanaf hier moet het report opgestart worden en de sessie afgesloten | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     val hms = viewModel.getTimer().getHoursMinutesSeconds() |     val hms = viewModel.getTimer().getHoursMinutesSeconds() | ||||||
|     Column { |     Column { | ||||||
|         Text( |         Text( | ||||||
|             text = "${hms.hours} : ${hms.minutes} : ${hms.seconds}", |             text = "${hms.hours} : ${hms.minutes} : ${hms.seconds}", | ||||||
|             modifier = Modifier.fillMaxWidth(), |             modifier = Modifier | ||||||
|  |                 .fillMaxWidth() | ||||||
|  |                 .padding(50.dp), | ||||||
|             textAlign = TextAlign.Center, |             textAlign = TextAlign.Center, | ||||||
|             fontWeight = FontWeight.Bold, |             fontWeight = FontWeight.Bold, | ||||||
|             fontSize = 80.sp |             fontSize = 40.sp, | ||||||
|         ) |         ) | ||||||
|         val stateString: String = when (viewModel.getTimer().view) { |         val stateString: String = when (viewModel.getTimer().view) { | ||||||
|             StudyState.DONE -> resources().getString(R.string.state_done) |             StudyState.DONE -> resources().getString(R.string.state_done) | ||||||
|  | @ -67,6 +138,29 @@ fun Timer(viewModel: SessionViewModel = hiltViewModel()) { | ||||||
|             fontWeight = FontWeight.Light, |             fontWeight = FontWeight.Light, | ||||||
|             fontSize = 30.sp |             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 = viewModel.getTask(), | ||||||
|  |                     color = Color.White, | ||||||
|  |                     fontSize = 18.sp, | ||||||
|  |                     fontWeight = FontWeight.Bold, | ||||||
|  |                     modifier = Modifier | ||||||
|  |                         .padding(vertical = 4.dp, horizontal = 20.dp) | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer | ||||||
| import be.ugent.sel.studeez.domain.LogService | import be.ugent.sel.studeez.domain.LogService | ||||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | import be.ugent.sel.studeez.screens.StudeezViewModel | ||||||
| import be.ugent.sel.studeez.data.SelectedTimerState | 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 dagger.hilt.android.lifecycle.HiltViewModel | ||||||
| import javax.inject.Inject | import javax.inject.Inject | ||||||
| 
 | 
 | ||||||
|  | @ -13,7 +14,14 @@ class SessionViewModel @Inject constructor( | ||||||
|     logService: LogService |     logService: LogService | ||||||
| ) : StudeezViewModel(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 { |     fun getTimer() : FunctionalTimer { | ||||||
|         return selectedTimerState.selectedTimer!! |         return selectedTimerState.selectedTimer!! | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fun getTask(): String { | ||||||
|  |         return task | ||||||
|  |     } | ||||||
| } | } | ||||||
		Reference in a new issue
	
	 brreynie
						brreynie