diff --git a/app/src/main/java/com/example/myapplication/UI_Components/Timer/TimerScreen.kt b/app/src/main/java/com/example/myapplication/UI_Components/Timer/TimerScreen.kt index 5a921fecbb234ba213e3a77d493cb6f02fb463c1..364e587d7ae7fdbc56c48f5bdcb4c312e25e1e8a 100644 --- a/app/src/main/java/com/example/myapplication/UI_Components/Timer/TimerScreen.kt +++ b/app/src/main/java/com/example/myapplication/UI_Components/Timer/TimerScreen.kt @@ -1,15 +1,12 @@ +import android.content.SharedPreferences import android.media.MediaPlayer import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material3.* -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.runtime.* +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -19,6 +16,7 @@ import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.work.* import com.example.myapplication.R import com.example.myapplication.Room.SettingsTimer import com.example.myapplication.Room.Task @@ -26,65 +24,59 @@ import com.example.myapplication.Room.TaskViewModel import com.example.myapplication.UI_Components.Dialogs.MyAlertDialog import com.example.myapplication.UI_Components.Title import com.example.myapplication.background.startPomodoro -import kotlinx.coroutines.delay +import java.util.UUID @Composable -fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificationCallback: (titel: String, text: String) -> Unit, onClickEndSession: () -> Unit) { +fun TimerScreen( + todayTasks: List<Task>, + settingsTimer: SettingsTimer, + notificationCallback: (titel: String, text: String) -> Unit, + onClickEndSession: () -> Unit +) { var showInfoDialog by remember { mutableStateOf(true) } val tasks by remember(todayTasks) { mutableStateOf(todayTasks) } val appSettings by remember(settingsTimer) { mutableStateOf(settingsTimer) } var mediaPlayer by remember { mutableStateOf<MediaPlayer?>(null) } - var timeLeft by remember { mutableStateOf(appSettings.dauer * 60) } - var round by remember { mutableStateOf(1) } var isRunning by remember { mutableStateOf(false) } - var isInPause by remember { mutableStateOf(false) } var pauseText by remember { mutableStateOf("Start") } val context = LocalContext.current + val workManager = WorkManager.getInstance(context) + // UUID des WorkManagers für Pomodoro speichern + val pomodoroWorkId = remember { mutableStateOf<UUID?>(null) } + + // Überwachung der WorkInfo für den Pomodoro-Timer + val workInfo by workManager.getWorkInfosForUniqueWorkLiveData("pomodoroWork").observeAsState() + + // Extrahiere den verbleibenden Timerwert vom Worker + val timeLeft = workInfo?.find { it.id == pomodoroWorkId.value }?.progress?.getInt( + "TIME_LEFT", + settingsTimer.dauer * 60 + ) ?: (settingsTimer.dauer * 60) + + // Musik-Player initialisieren LaunchedEffect(Unit) { - if(appSettings.musik != "---"){ - mediaPlayer = MediaPlayer.create(context, getMusik(appSettings.musik)).apply{ + if (appSettings.musik != "---") { + mediaPlayer = MediaPlayer.create(context, getMusik(appSettings.musik)).apply { setVolume(1.0f, 1.0f) isLooping = true } } } - - LaunchedEffect(isRunning, isInPause) { - while (round <= appSettings.langePauseNachEinheiten) { - if (isRunning) { - while (timeLeft > 0) { - delay(1000) - timeLeft -= 1 - } - isInPause = true - isRunning = false - timeLeft = if(round == 4) appSettings.langePause * 60 else appSettings.kurzePause * 60 - } - if (isInPause) { - notificationCallback("Congratulation", "Nice you have ${appSettings.dauer * round} minutes worked :).") - while (timeLeft > 0) { - delay(1000) - timeLeft -= 1 - } - isInPause = false - isRunning = true - timeLeft = appSettings.dauer * 60 - round += 1 - } - if (!isRunning && !isInPause) { - delay(1000) - } + // Überwachung für Start/Pause-Status und Starten des Workers + LaunchedEffect(isRunning) { + if (isRunning) { + // Worker starten + pomodoroWorkId.value = startPomodoro(context, timeLeft) + } else { + // Worker anhalten + pomodoroWorkId.value?.let { workManager.cancelWorkById(it) } } - round = 1 - isRunning = false - isInPause = false - timeLeft = appSettings.dauer * 60 } - if(tasks.isEmpty() && showInfoDialog) { + if (tasks.isEmpty() && showInfoDialog) { MyAlertDialog(text = "Please make sure you have Task for Today!") { showInfoDialog = false } @@ -92,6 +84,7 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati showInfoDialog = false } + // UI-Anzeige Column( modifier = Modifier .fillMaxSize() @@ -105,8 +98,8 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati .padding(vertical = 16.dp), contentAlignment = Alignment.Center ) { - val text = if(isInPause) "Pause" else "$round.Arbeitsphase" - TimerDisplay(text ,timeLeft = timeLeft) + val text = if (isRunning && timeLeft > 0) "Arbeitsphase" else "Pause" + TimerDisplay(text, timeLeft) } Spacer(modifier = Modifier.height(16.dp)) @@ -116,7 +109,6 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati // Liste der Aufgaben TaskList(tasks = tasks) - // Platzhalter, um die Buttons nach unten zu schieben Spacer(modifier = Modifier.weight(1f)) // Schaltflächen für Start/Pause und Ende @@ -129,11 +121,10 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati Button( onClick = { isRunning = !isRunning - pauseText = if (pauseText == "Pause") "Start" else "Pause" - - if(mediaPlayer != null) if(isRunning) mediaPlayer?.start() else mediaPlayer?.pause() + pauseText = if (isRunning) "Pause" else "Start" - if (pauseText=="Pause") startPomodoro(context) + if (mediaPlayer != null) + if (isRunning) mediaPlayer?.start() else mediaPlayer?.pause() }, modifier = Modifier.weight(1f), colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF7F56D9)) @@ -155,6 +146,18 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati } } + +fun getStoredTimeLeft(sharedPreferences: SharedPreferences, defaultTimeLeft: Int): Int { + return sharedPreferences.getInt("timeLeft", defaultTimeLeft) +} + +fun saveTimeLeft(sharedPreferences: SharedPreferences, timeLeft: Int) { + sharedPreferences.edit().putInt("timeLeft", timeLeft).apply() +} + + + + @Composable fun TimerDisplay(text: String, timeLeft: Int) { val minutes = (timeLeft / 60).toString().padStart(2, '0') @@ -208,8 +211,8 @@ fun TaskList(tasks: List<Task>, taskViewModel: TaskViewModel = viewModel()) { } } -fun getMusik(music:String):Int { - return when(music) { +fun getMusik(music: String): Int { + return when (music) { "day" -> R.raw.day "farm" -> R.raw.farm "fire" -> R.raw.fire diff --git a/app/src/main/java/com/example/myapplication/background/PomodoroWorker.kt b/app/src/main/java/com/example/myapplication/background/PomodoroWorker.kt index bb6b3434335d03872e0621527feb590b2249b124..5b300b4f5eab139b58b3450353ea0401a1399ea9 100644 --- a/app/src/main/java/com/example/myapplication/background/PomodoroWorker.kt +++ b/app/src/main/java/com/example/myapplication/background/PomodoroWorker.kt @@ -5,26 +5,51 @@ import android.content.Context import androidx.core.app.NotificationCompat import androidx.work.Worker import androidx.work.WorkerParameters +import androidx.work.workDataOf import com.example.myapplication.R +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking class PomodoroWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { - override fun doWork(): Result { - - // Benachrichtigung start - showNotification("Pomodoro beginnt!", "Let's GO!") + private var isPaused = false + private var timeLeft: Int = 25 * 60 // Standardzeit in Sekunden (25 Minuten) - // Timer-Logik oder andere Hintergrundaufgaben - val pomodoroDuration = 25 * 60 * 1000L // 25 Minuten in Millisekunden - Thread.sleep(pomodoroDuration) - - // Benachrichtigung anzeigen + override fun doWork(): Result { + // Lade den verbleibenden Fortschritt, falls vorhanden + timeLeft = inputData.getInt("TIME_LEFT", 25 * 60) + + runBlocking(Dispatchers.IO) { + while (timeLeft > 0) { + if (!isPaused) { + delay(1000L) // Warte 1 Sekunde + timeLeft -= 1 + + // Fortschrittsaktualisierung + setProgressAsync(workDataOf("TIME_LEFT" to timeLeft)) + } else { + // Pausiert, warte weiter + delay(1000L) + } + } + } + + // Benachrichtigung, wenn der Timer abgelaufen ist showNotification("Pomodoro beendet!", "Zeit für eine Pause.") return Result.success() } + fun pauseTimer() { + isPaused = true + } + + fun resumeTimer() { + isPaused = false + } + private fun showNotification(title: String, message: String) { val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationBuilder = NotificationCompat.Builder(applicationContext, "POMODORO_CHANNEL") diff --git a/app/src/main/java/com/example/myapplication/background/startPomodoro.kt b/app/src/main/java/com/example/myapplication/background/startPomodoro.kt index d37dcc5d2622a38301e964acf7dafa9473036774..f5b8cd95f69297a6ce5e7df210f095c3b6e40bdd 100644 --- a/app/src/main/java/com/example/myapplication/background/startPomodoro.kt +++ b/app/src/main/java/com/example/myapplication/background/startPomodoro.kt @@ -1,12 +1,24 @@ package com.example.myapplication.background import android.content.Context -import androidx.work.OneTimeWorkRequest -import androidx.work.WorkManager +import androidx.work.* +import java.util.UUID -fun startPomodoro(context: Context) { - val workRequest = OneTimeWorkRequest.Builder(PomodoroWorker::class.java) +fun startPomodoro(context: Context, timeLeft: Int): UUID { + val workManager = WorkManager.getInstance(context) + + // Erstelle den WorkRequest mit den Input-Daten + val workRequest = OneTimeWorkRequestBuilder<PomodoroWorker>() + .setInputData(workDataOf("TIME_LEFT" to timeLeft)) .build() - WorkManager.getInstance(context).enqueue(workRequest) -} \ No newline at end of file + // Enqueue den WorkRequest und speichere die ID des WorkRequests + workManager.enqueueUniqueWork( + "pomodoroWork", + ExistingWorkPolicy.REPLACE, + workRequest + ) + + // Gib die ID des WorkRequests zurück + return workRequest.id +}