Skip to content
Snippets Groups Projects
Commit 33a815ca authored by Kaan Kalinkarci's avatar Kaan Kalinkarci
Browse files

bugfix

- meldung wenn der timer startet, obwohl die app startet entfernt, daraufhin auch meldung wenn der timer selbst startet entfernt -> nicht nötig

, immernoch ein paar fehler -> timer beim starten nach pausieren kurz auf 25:00 und timer nach 3 mal start stopp nicht mehr funktionstüchtig und auf 25:00 stuck
parent afa65512
Branches background
No related tags found
1 merge request!7bugfix
import android.content.SharedPreferences
import android.media.MediaPlayer import android.media.MediaPlayer
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.*
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.livedata.observeAsState
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.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
...@@ -19,6 +16,7 @@ import androidx.compose.ui.text.style.TextDecoration ...@@ -19,6 +16,7 @@ import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.work.*
import com.example.myapplication.R import com.example.myapplication.R
import com.example.myapplication.Room.SettingsTimer import com.example.myapplication.Room.SettingsTimer
import com.example.myapplication.Room.Task import com.example.myapplication.Room.Task
...@@ -26,22 +24,38 @@ import com.example.myapplication.Room.TaskViewModel ...@@ -26,22 +24,38 @@ import com.example.myapplication.Room.TaskViewModel
import com.example.myapplication.UI_Components.Dialogs.MyAlertDialog import com.example.myapplication.UI_Components.Dialogs.MyAlertDialog
import com.example.myapplication.UI_Components.Title import com.example.myapplication.UI_Components.Title
import com.example.myapplication.background.startPomodoro import com.example.myapplication.background.startPomodoro
import kotlinx.coroutines.delay import java.util.UUID
@Composable @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) } var showInfoDialog by remember { mutableStateOf(true) }
val tasks by remember(todayTasks) { mutableStateOf(todayTasks) } val tasks by remember(todayTasks) { mutableStateOf(todayTasks) }
val appSettings by remember(settingsTimer) { mutableStateOf(settingsTimer) } val appSettings by remember(settingsTimer) { mutableStateOf(settingsTimer) }
var mediaPlayer by remember { mutableStateOf<MediaPlayer?>(null) } 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 isRunning by remember { mutableStateOf(false) }
var isInPause by remember { mutableStateOf(false) }
var pauseText by remember { mutableStateOf("Start") } var pauseText by remember { mutableStateOf("Start") }
val context = LocalContext.current 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) { LaunchedEffect(Unit) {
if (appSettings.musik != "---") { if (appSettings.musik != "---") {
mediaPlayer = MediaPlayer.create(context, getMusik(appSettings.musik)).apply { mediaPlayer = MediaPlayer.create(context, getMusik(appSettings.musik)).apply {
...@@ -51,37 +65,15 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati ...@@ -51,37 +65,15 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati
} }
} }
// Überwachung für Start/Pause-Status und Starten des Workers
LaunchedEffect(isRunning, isInPause) { LaunchedEffect(isRunning) {
while (round <= appSettings.langePauseNachEinheiten) {
if (isRunning) { if (isRunning) {
while (timeLeft > 0) { // Worker starten
delay(1000) pomodoroWorkId.value = startPomodoro(context, timeLeft)
timeLeft -= 1 } else {
} // Worker anhalten
isInPause = true pomodoroWorkId.value?.let { workManager.cancelWorkById(it) }
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)
}
} }
round = 1
isRunning = false
isInPause = false
timeLeft = appSettings.dauer * 60
} }
if (tasks.isEmpty() && showInfoDialog) { if (tasks.isEmpty() && showInfoDialog) {
...@@ -92,6 +84,7 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati ...@@ -92,6 +84,7 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati
showInfoDialog = false showInfoDialog = false
} }
// UI-Anzeige
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
...@@ -105,8 +98,8 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati ...@@ -105,8 +98,8 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati
.padding(vertical = 16.dp), .padding(vertical = 16.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
val text = if(isInPause) "Pause" else "$round.Arbeitsphase" val text = if (isRunning && timeLeft > 0) "Arbeitsphase" else "Pause"
TimerDisplay(text ,timeLeft = timeLeft) TimerDisplay(text, timeLeft)
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
...@@ -116,7 +109,6 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati ...@@ -116,7 +109,6 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati
// Liste der Aufgaben // Liste der Aufgaben
TaskList(tasks = tasks) TaskList(tasks = tasks)
// Platzhalter, um die Buttons nach unten zu schieben
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
// Schaltflächen für Start/Pause und Ende // Schaltflächen für Start/Pause und Ende
...@@ -129,11 +121,10 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati ...@@ -129,11 +121,10 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati
Button( Button(
onClick = { onClick = {
isRunning = !isRunning isRunning = !isRunning
pauseText = if (pauseText == "Pause") "Start" else "Pause" pauseText = if (isRunning) "Pause" else "Start"
if(mediaPlayer != null) if(isRunning) mediaPlayer?.start() else mediaPlayer?.pause()
if (pauseText=="Pause") startPomodoro(context) if (mediaPlayer != null)
if (isRunning) mediaPlayer?.start() else mediaPlayer?.pause()
}, },
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF7F56D9)) colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF7F56D9))
...@@ -155,6 +146,18 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati ...@@ -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 @Composable
fun TimerDisplay(text: String, timeLeft: Int) { fun TimerDisplay(text: String, timeLeft: Int) {
val minutes = (timeLeft / 60).toString().padStart(2, '0') val minutes = (timeLeft / 60).toString().padStart(2, '0')
......
...@@ -5,26 +5,51 @@ import android.content.Context ...@@ -5,26 +5,51 @@ import android.content.Context
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.example.myapplication.R import com.example.myapplication.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
class PomodoroWorker(context: Context, workerParams: WorkerParameters) : class PomodoroWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) { Worker(context, workerParams) {
override fun doWork(): Result { private var isPaused = false
private var timeLeft: Int = 25 * 60 // Standardzeit in Sekunden (25 Minuten)
// Benachrichtigung start
showNotification("Pomodoro beginnt!", "Let's GO!")
// Timer-Logik oder andere Hintergrundaufgaben override fun doWork(): Result {
val pomodoroDuration = 25 * 60 * 1000L // 25 Minuten in Millisekunden // Lade den verbleibenden Fortschritt, falls vorhanden
Thread.sleep(pomodoroDuration) 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 anzeigen // Benachrichtigung, wenn der Timer abgelaufen ist
showNotification("Pomodoro beendet!", "Zeit für eine Pause.") showNotification("Pomodoro beendet!", "Zeit für eine Pause.")
return Result.success() return Result.success()
} }
fun pauseTimer() {
isPaused = true
}
fun resumeTimer() {
isPaused = false
}
private fun showNotification(title: String, message: String) { private fun showNotification(title: String, message: String) {
val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationBuilder = NotificationCompat.Builder(applicationContext, "POMODORO_CHANNEL") val notificationBuilder = NotificationCompat.Builder(applicationContext, "POMODORO_CHANNEL")
......
package com.example.myapplication.background package com.example.myapplication.background
import android.content.Context import android.content.Context
import androidx.work.OneTimeWorkRequest import androidx.work.*
import androidx.work.WorkManager import java.util.UUID
fun startPomodoro(context: Context) { fun startPomodoro(context: Context, timeLeft: Int): UUID {
val workRequest = OneTimeWorkRequest.Builder(PomodoroWorker::class.java) val workManager = WorkManager.getInstance(context)
// Erstelle den WorkRequest mit den Input-Daten
val workRequest = OneTimeWorkRequestBuilder<PomodoroWorker>()
.setInputData(workDataOf("TIME_LEFT" to timeLeft))
.build() .build()
WorkManager.getInstance(context).enqueue(workRequest) // 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
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment