diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 85de068d4aa574de7a0306f7ddcd4c656f77c233..da9fccbbd36c8877e16a64be8e1af7c4de3c8096 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,7 +6,7 @@ <uses-permission android:name="android.permission.VIBRATE" /> <application - android:name=".MyAppChannel" + android:name=".MyApplication" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" diff --git a/app/src/main/java/com/example/myapplication/Application.kt b/app/src/main/java/com/example/myapplication/Application.kt deleted file mode 100644 index b41be0ebe5dc658d8694622b1ca481ee575591bb..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/myapplication/Application.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.example.myapplication - -import android.app.Application -import android.util.Log - -class MyApplication : Application() { - - override fun onCreate() { - super.onCreate() - //Initialisierung der Anwendung - } - - override fun onTerminate() { - super.onTerminate() - // Bereinigen der Ressourcen - } - - override fun onLowMemory() { - super.onLowMemory() - // Ressourcen freigeben - } - - override fun onTrimMemory(level: Int) { - super.onTrimMemory(level) - // Reagieren auf verschieden Speicherknappheitensstufen - - - - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/Helpers/NotificationChannelHelper.kt b/app/src/main/java/com/example/myapplication/Helpers/NotificationChannelHelper.kt new file mode 100644 index 0000000000000000000000000000000000000000..97bd128b277485c2e7ebc8c2b9384252d27ea6b0 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/Helpers/NotificationChannelHelper.kt @@ -0,0 +1,54 @@ +package com.example.myapplication.Helpers + +import android.Manifest +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import androidx.core.app.NotificationCompat +import androidx.core.content.ContextCompat +import com.example.myapplication.R + + +private const val channelId = "POMODORO_CHANNEL_ID" +const val channelName = "Pomodoro_Notifications" +const val channelDescription = "Channel for Pomodoro notifications" + +fun createNotificationChannel(context: Context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API-Level 26 + val channel = NotificationChannel( + channelId, + channelName, + NotificationManager.IMPORTANCE_DEFAULT + ).apply { + description = channelDescription + enableVibration(true) + vibrationPattern = longArrayOf(0, 500, 1000, 500) // Vibration: Start sofort, 500ms Vibration, 1000ms Pause + } + + val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + manager.createNotificationChannel(channel) + } +} + +fun hasNotificationPermission(context: Context): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } + + return true +} + +fun showNotification(hasPermission: Boolean, title: String, text: String, context: Context) { + if (hasPermission) { + val notification = NotificationCompat.Builder(context.applicationContext, channelId) + .setSmallIcon(R.drawable.ic_launcher_foreground) + .setContentTitle(title) + .setContentText(text) + .build() + + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.notify(1, notification) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/Helpers/ViewModelProvider.kt b/app/src/main/java/com/example/myapplication/Helpers/ViewModelProvider.kt new file mode 100644 index 0000000000000000000000000000000000000000..d1fe9186e7e32c4a645fe0d706e7306dc106f5cc --- /dev/null +++ b/app/src/main/java/com/example/myapplication/Helpers/ViewModelProvider.kt @@ -0,0 +1,24 @@ +package com.example.myapplication.Helpers + +import androidx.compose.runtime.Composable +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.myapplication.Room.AppViewModel +import com.example.myapplication.Room.SettingsViewModel +import com.example.myapplication.Room.TaskViewModel + +object ViewModelProvider { + private var settingsViewModel: SettingsViewModel? = null + private var taskViewModel: TaskViewModel? = null + private var appViewModel: AppViewModel? = null + + @Composable + fun initViewModels() { + settingsViewModel = viewModel() + taskViewModel = viewModel() + appViewModel = viewModel() + } + + fun getSettingsViewModel() = settingsViewModel ?: throw Error("ERROR") + fun getTaskViewModel() = taskViewModel ?: throw Error("ERROR") + fun getAppViewModel() = appViewModel ?: throw Error("ERROR") +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/MainActivity.kt b/app/src/main/java/com/example/myapplication/MainActivity.kt index 47736f5347d53b2fd85ab011edd154f88f63eb02..1f9b1e62e4dbaa65ff0b499b8a81fb7f210918f0 100644 --- a/app/src/main/java/com/example/myapplication/MainActivity.kt +++ b/app/src/main/java/com/example/myapplication/MainActivity.kt @@ -12,39 +12,54 @@ import androidx.compose.ui.unit.dp import com.example.myapplication.UI_Components.main_app import com.example.myapplication.ui.theme.MyApplicationTheme import android.Manifest -import android.app.NotificationManager -import android.content.Context -import android.content.pm.PackageManager import android.os.Build import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels 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.platform.LocalContext -import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat -import com.example.myapplication.Room.MyDatabase -import com.example.myapplication.background.createNotificationChannel - - +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.myapplication.Helpers.ViewModelProvider +import com.example.myapplication.Helpers.createNotificationChannel +import com.example.myapplication.Helpers.hasNotificationPermission +import com.example.myapplication.Helpers.showNotification +import com.example.myapplication.Room.AppViewModel +import com.example.myapplication.Room.SettingsViewModel +import com.example.myapplication.Room.TaskViewModel +import com.example.myapplication.Types.NavigationType class MainActivity : ComponentActivity() { - companion object { - var database: MyDatabase? = null - } + private val settingsViewModel :SettingsViewModel by viewModels() + private val taskViewModel :TaskViewModel by viewModels() + private val appViewModel :AppViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContent { + ViewModelProvider.initViewModels() + settingsViewModel.updateSettingByEmpty() + + val context = LocalContext.current + var hasPermission by remember { mutableStateOf(hasNotificationPermission(context)) } + val permissionLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.RequestPermission(), + onResult = { isGranted -> + hasPermission = isGranted + showNotification(hasPermission,"Success Notification", "You have successfully enabled notifications. Stay tuned for updates and alerts!", context) + } + ) - database = MyDatabase.getDatabase(this) + LaunchedEffect(key1 = hasPermission) { + if (!hasPermission && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) + } + } - // Timer Notification Channel - createNotificationChannel(this) - setContent { MyApplicationTheme { Surface( modifier = Modifier @@ -52,95 +67,39 @@ class MainActivity : ComponentActivity() { .padding(8.dp), color = MaterialTheme.colorScheme.background ) { - val context = LocalContext.current - var hasPermission by remember { mutableStateOf(hasNotificationPermission(context)) } - val permissionLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.RequestPermission(), - onResult = { isGranted -> - hasPermission = isGranted - showNotification( - hasPermission, - "Success Notification", - "You have successfully enabled notifications. Stay tuned for updates and alerts!" - ) - } - ) - - LaunchedEffect(key1 = hasPermission) { - if (!hasPermission && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) - } - } main_app() { title, text -> - showNotification(hasPermission, title, text) + showNotification(hasPermission, title, text, context) } } } } + } + override fun onStart() { + super.onStart() + taskViewModel.getAllSortedByDate() + settingsViewModel.getAllSettings() + } - var protected = null - protected void onStart() - super.onStart(); - //Code, der ausgeführt wird, wenn die Aktivität sichtbar wird - var statusTextView = null - statusTextView.setText("Acitivity is now visible"); - - protected void onStop() - super.onStop(); - //Code, der ausgeführt wird, wenn die Aktivität nicht mehr sichtbar ist - - protected void onResume() - super.onResume(); - //Code, der ausgeführt wird, wenn die Aktivität den Fokus erhälrt und interaktiv wird + override fun onResume() { + super.onResume() + appViewModel.runTimer() + } - protected void onPause() + override fun onPause() { super.onPause() - //Coder, der ausgeführt wird, wenn die Akitvität den Fokus verliert, aber noch sichtbar ist - - protected void onRestart() - super.onRestart() - //Code, der ausgeführt wird, wenn eine gestoppte Aktivität erneut gestartet wird. - - protected void onDestroy() - super.onDestroy() - //Code, der ausgeführt wird, bevor die Aktivität gelöscht wird. - - } + appViewModel.stopTimer() } -private fun Nothing?.setText(s: String) { - -} - -private infix fun Nothing?.void(onStart: Unit) { - -} - -fun hasNotificationPermission(context: Context): Boolean { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - return ContextCompat.checkSelfPermission( - context, - Manifest.permission.POST_NOTIFICATIONS - ) == PackageManager.PERMISSION_GRANTED - } - - return true + override fun onStop() { + super.onStop() + appViewModel.stopTimer() } - fun showNotification(hasPermission: Boolean, title: String, text: String) { - if (hasPermission) { - val notification = NotificationCompat.Builder(applicationContext, "channel_id") - .setSmallIcon(R.drawable.ic_launcher_foreground) - .setContentTitle(title) - .setContentText(text) - .build() - - val notificationManager = - getSystemService(NOTIFICATION_SERVICE) as NotificationManager - notificationManager.notify(1, notification) - } + override fun onDestroy() { + super.onDestroy() + appViewModel.setSelectedNavigation(NavigationType.Home) + appViewModel.destroyMediaPlayer() } - - +} diff --git a/app/src/main/java/com/example/myapplication/MyAppChannel.kt b/app/src/main/java/com/example/myapplication/MyAppChannel.kt deleted file mode 100644 index 363bbe4c51f1e8fe95a9bccf6dfa78e653a6c335..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/myapplication/MyAppChannel.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.example.myapplication - -import android.app.Application -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import android.os.Build - -class MyAppChannel: Application() { - override fun onCreate() { - super.onCreate() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - val channel = NotificationChannel( - "channel_id", "myChannel", NotificationManager.IMPORTANCE_DEFAULT - ).apply { - enableVibration(true) - vibrationPattern = longArrayOf(0, 500, 1000, 500) // Vibration: Start sofort, 500ms Vibration, 1000ms Pause - } - - val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - manager.createNotificationChannel(channel) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/MyApplication.kt b/app/src/main/java/com/example/myapplication/MyApplication.kt new file mode 100644 index 0000000000000000000000000000000000000000..c6e30da876b1405d02b9f66afe63dc89497b8cfc --- /dev/null +++ b/app/src/main/java/com/example/myapplication/MyApplication.kt @@ -0,0 +1,22 @@ +package com.example.myapplication + +import android.app.Application +import com.example.myapplication.Helpers.createNotificationChannel +import com.example.myapplication.Room.MyDatabase + +class MyApplication : Application() { + companion object{ + var database: MyDatabase? = null + } + + override fun onCreate() { + super.onCreate() + createNotificationChannel(this) + database = MyDatabase.getDatabase(this) + } + + override fun onTerminate() { + super.onTerminate() + database?.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/Room/AppViewModel.kt b/app/src/main/java/com/example/myapplication/Room/AppViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..391aa550a058877a9441a47ca17600087be83004 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/Room/AppViewModel.kt @@ -0,0 +1,67 @@ +package com.example.myapplication.Room + +import android.content.Context +import android.media.MediaPlayer +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.example.myapplication.R +import com.example.myapplication.Types.NavigationType + +class AppViewModel: ViewModel() { + var isRunning = MutableLiveData(false) + var pauseText = MutableLiveData("Start") + var selectedNavigation = MutableLiveData(NavigationType.Home) + var musicPlayer: MutableLiveData<MediaPlayer?> = MutableLiveData(null) + + fun runTimer() { + isRunning.setValue(true) + pauseText.setValue("Pause") + musicPlayer.value?.apply { + start() + } + } + + fun stopTimer() { + isRunning.setValue(false) + pauseText.setValue("Start") + musicPlayer.value?.apply { + stop() + } + } + + fun setSelectedNavigation(navigationType: NavigationType) { + selectedNavigation.setValue(navigationType) + } + + fun createMediaPlayer(context: Context, music: String) { + if(music != "---") { + musicPlayer = MutableLiveData( + MediaPlayer.create(context, getMusic(music)).apply { + setVolume(1.0f, 1.0f) + isLooping = true + } + ) + } + } + + fun destroyMediaPlayer() { + musicPlayer.value?.apply { + stop() + release() + } + + musicPlayer.setValue(null) + } + + private fun getMusic(music:String):Int { + return when(music) { + "day" -> R.raw.day + "farm" -> R.raw.farm + "fire" -> R.raw.fire + "night" -> R.raw.night + "storm" -> R.raw.storm + else -> throw Error("ERROR") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/Room/SettingsViewModel.kt b/app/src/main/java/com/example/myapplication/Room/SettingsViewModel.kt index 2c5a94a75455aa10ed03893da3779f8d5ef5ee1a..0b6d8352716fd7b36d77cc324dc1e5e356047c25 100644 --- a/app/src/main/java/com/example/myapplication/Room/SettingsViewModel.kt +++ b/app/src/main/java/com/example/myapplication/Room/SettingsViewModel.kt @@ -1,21 +1,20 @@ package com.example.myapplication.Room import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.myapplication.MainActivity +import com.example.myapplication.MyApplication import com.example.myapplication.Room.DAO.SettingsDAO import kotlinx.coroutines.launch class SettingsViewModel() : ViewModel() { - private val SettingsDAO: SettingsDAO = getSettingsDAO() + private val SettingsDAO: SettingsDAO = MyApplication.database?.settingsDAO() ?: throw Error("Error") + var settingsDataList: LiveData<SettingsTimer> = getAllSettings() - fun insert(settingsTimer: SettingsTimer) { - viewModelScope.launch { - SettingsDAO.insert(settingsTimer) - } - } + fun getAllSettings(): LiveData<SettingsTimer> = SettingsDAO.getAllSettings() fun update(settingsTimer: SettingsTimer) { viewModelScope.launch { @@ -23,8 +22,6 @@ class SettingsViewModel() : ViewModel() { } } - fun getAllSettings(): LiveData<SettingsTimer> = SettingsDAO.getAllSettings() - suspend fun getSettingsIsEmpty(): Boolean { val count = SettingsDAO.getCount() return count == 0 @@ -37,10 +34,4 @@ class SettingsViewModel() : ViewModel() { } } } - - private fun getSettingsDAO(): SettingsDAO { - val settingsDAO: SettingsDAO = MainActivity.database?.settingsDAO() ?: throw Error("FEHLER") - - return settingsDAO - } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/Room/TaskViewModel.kt b/app/src/main/java/com/example/myapplication/Room/TaskViewModel.kt index 37d06cec5f5e69181f9d37f5dca9e53acade96d7..7808252cfcf5ac15006aa7a210700fbeecac8851 100644 --- a/app/src/main/java/com/example/myapplication/Room/TaskViewModel.kt +++ b/app/src/main/java/com/example/myapplication/Room/TaskViewModel.kt @@ -1,20 +1,19 @@ package com.example.myapplication.Room import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.myapplication.Helpers.StringToDate -import com.example.myapplication.MainActivity +import com.example.myapplication.MyApplication import com.example.myapplication.Room.DAO.TaskDAO import kotlinx.coroutines.launch class TaskViewModel(): ViewModel() { + private val taskDAO: TaskDAO = MyApplication.database?.taskDAO() ?: throw Error("Error") + var taskDataList: LiveData<List<Task>> = getAllSortedByDate() - private val taskDAO: TaskDAO = getTaskDAO() - - fun getAllSortedByDate(): LiveData<List<Task>> { - return taskDAO.getAllSortedByDate() - } + fun getAllSortedByDate() = taskDAO.getAllSortedByDate() fun insert(taskName: String, taskDate:String) { viewModelScope.launch { @@ -52,10 +51,4 @@ class TaskViewModel(): ViewModel() { deletedTasks.forEach { taskDAO.delete(it) } } } - - private fun getTaskDAO(): TaskDAO { - val taskDAO: TaskDAO = MainActivity.database?.taskDAO() ?: throw Error("FEHLER") - - return taskDAO - } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/UI_Components/Dialogs/TaskDialog.kt b/app/src/main/java/com/example/myapplication/UI_Components/Dialogs/TaskDialog.kt index 10017ff473439d2ec61bf798d096bed27b7badd9..3b28f186f18f2f8cfed1d835af149f9bdde6c05f 100644 --- a/app/src/main/java/com/example/myapplication/UI_Components/Dialogs/TaskDialog.kt +++ b/app/src/main/java/com/example/myapplication/UI_Components/Dialogs/TaskDialog.kt @@ -22,13 +22,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.myapplication.Helpers.ViewModelProvider import com.example.myapplication.Helpers.isValidDate -import com.example.myapplication.Room.TaskViewModel +import com.example.myapplication.MainActivity import com.example.myapplication.ui.theme.color_FFFFFF @Composable -fun TaskDialog(currentTaskId: Int, currentTaskDate: String, currentTaskName: String, taskViewModel: TaskViewModel = viewModel(), showDialogDissmis: () -> Unit) { +fun TaskDialog(currentTaskId: Int, currentTaskDate: String, currentTaskName: String, showDialogDissmis: () -> Unit) { var taskDate by remember { mutableStateOf(currentTaskDate) } var taskName by remember { mutableStateOf(currentTaskName) } var taskFormularError by remember { mutableStateOf(false) } @@ -79,11 +79,11 @@ fun TaskDialog(currentTaskId: Int, currentTaskDate: String, currentTaskName: Str confirmButton = { Button(modifier = Modifier.padding(0.dp,0.dp, 20.dp, 0.dp).width(90.dp),onClick = { if (isValidDate(taskDate) && taskName.isNotEmpty() && currentTaskName.isNotEmpty()) { - taskViewModel.updateTaskById(currentTaskId, taskDate, taskName) + ViewModelProvider.getTaskViewModel().updateTaskById(currentTaskId, taskDate, taskName) showDialogDissmis() } else if(isValidDate(taskDate) && taskName.isNotEmpty() && currentTaskName.isEmpty()) { - taskViewModel.insert(taskName, taskDate) + ViewModelProvider.getTaskViewModel().insert(taskName, taskDate) showDialogDissmis() } else { diff --git a/app/src/main/java/com/example/myapplication/UI_Components/Home/HomeScreen.kt b/app/src/main/java/com/example/myapplication/UI_Components/Home/HomeScreen.kt index 36ea16e90972c35f492a8817e57d6baeaabafba1..22132acc6cec32238fc5bb156f3a2ebcf03cd60e 100644 --- a/app/src/main/java/com/example/myapplication/UI_Components/Home/HomeScreen.kt +++ b/app/src/main/java/com/example/myapplication/UI_Components/Home/HomeScreen.kt @@ -22,19 +22,21 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.myapplication.Helpers.ViewModelProvider import com.example.myapplication.Room.Task import com.example.myapplication.UI_Components.Dialogs.TaskDialog import com.example.myapplication.UI_Components.Dialogs.TaskInfoDialog import com.example.myapplication.UI_Components.Title import java.util.Date import com.example.myapplication.Helpers.dateToString +import com.example.myapplication.MainActivity import com.example.myapplication.Room.TaskViewModel import com.example.myapplication.UI_Components.Dialogs.MyAlertDialog // Home-Screen mit Listen für offene und erledigte Aufgaben @Composable -fun HomeScreen(currentOpenTask: List<Task>, currentCompletedTask: List<Task>, taskViewModel: TaskViewModel = viewModel(), onClickStartSession: () -> Unit) { +fun HomeScreen(currentOpenTask: List<Task>, currentCompletedTask: List<Task>, onClickStartSession: () -> Unit) { var openTask by remember(currentOpenTask) { mutableStateOf(currentOpenTask.map { it.copy() }) } var completedTask by remember(currentCompletedTask) { mutableStateOf(currentCompletedTask.map { it.copy() }) } var changesEnabled by remember { mutableStateOf(false) } @@ -124,10 +126,10 @@ fun HomeScreen(currentOpenTask: List<Task>, currentCompletedTask: List<Task>, ta if (currentAllTask.count() > allList.count()) { val deletedTasks: List<Task> = currentAllTask.filter { !allList.contains(it) } - taskViewModel.delete(deletedTasks) + ViewModelProvider.getTaskViewModel().delete(deletedTasks) } - taskViewModel.update(allList) + ViewModelProvider.getTaskViewModel().update(allList) changesEnabled = false }, enabled = changesEnabled) { diff --git a/app/src/main/java/com/example/myapplication/UI_Components/Settings/Settings.kt b/app/src/main/java/com/example/myapplication/UI_Components/Settings/Settings.kt index 18dbb5465896a67128dd74f7181699652c768f32..b7d6f20ca4343880e444abadcc8a0a9e448680ec 100644 --- a/app/src/main/java/com/example/myapplication/UI_Components/Settings/Settings.kt +++ b/app/src/main/java/com/example/myapplication/UI_Components/Settings/Settings.kt @@ -18,6 +18,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.myapplication.Helpers.ViewModelProvider +import com.example.myapplication.MainActivity import com.example.myapplication.Room.SettingsTimer import com.example.myapplication.Room.SettingsViewModel import com.example.myapplication.Types.SettingsDropdownType @@ -25,7 +27,7 @@ import com.example.myapplication.UI_Components.Title import com.example.myapplication.ui.theme.color_0066FF @Composable -fun Settings(appSettings: SettingsTimer, settingsViewModel: SettingsViewModel = viewModel()) { +fun Settings(appSettings: SettingsTimer) { val initialSettingsTimerState: SettingsTimer = appSettings var newSettingsTimerState by remember { mutableStateOf(initialSettingsTimerState) } var changesEnabled by remember { mutableStateOf(false) } @@ -111,7 +113,7 @@ fun Settings(appSettings: SettingsTimer, settingsViewModel: SettingsViewModel = } Button( onClick = { - settingsViewModel.update(newSettingsTimerState) + ViewModelProvider.getSettingsViewModel().update(newSettingsTimerState) changesEnabled = false }, enabled = changesEnabled) 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..3be5cd7de124e46128f31c97e17e6554a334651e 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 @@ -7,6 +7,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -19,6 +20,8 @@ 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 com.example.myapplication.Helpers.ViewModelProvider +import com.example.myapplication.MainActivity import com.example.myapplication.R import com.example.myapplication.Room.SettingsTimer import com.example.myapplication.Room.Task @@ -33,54 +36,41 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati 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) } + val isRunning by ViewModelProvider.getAppViewModel().isRunning.observeAsState(initial = false) + val pauseText by ViewModelProvider.getAppViewModel().pauseText.observeAsState(initial = "Start") 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 LaunchedEffect(Unit) { - if(appSettings.musik != "---"){ - mediaPlayer = MediaPlayer.create(context, getMusik(appSettings.musik)).apply{ - setVolume(1.0f, 1.0f) - isLooping = true - } - } + ViewModelProvider.getAppViewModel().createMediaPlayer(context, appSettings.musik) } - LaunchedEffect(isRunning, isInPause) { + LaunchedEffect(isRunning) { while (round <= appSettings.langePauseNachEinheiten) { if (isRunning) { while (timeLeft > 0) { delay(1000) timeLeft -= 1 } - isInPause = true - isRunning = false + ViewModelProvider.getAppViewModel().stopTimer() timeLeft = if(round == 4) appSettings.langePause * 60 else appSettings.kurzePause * 60 } - if (isInPause) { + if (!isRunning) { notificationCallback("Congratulation", "Nice you have ${appSettings.dauer * round} minutes worked :).") while (timeLeft > 0) { delay(1000) timeLeft -= 1 } - isInPause = false - isRunning = true + ViewModelProvider.getAppViewModel().runTimer() timeLeft = appSettings.dauer * 60 round += 1 } - if (!isRunning && !isInPause) { - delay(1000) - } } round = 1 - isRunning = false - isInPause = false + ViewModelProvider.getAppViewModel().stopTimer() timeLeft = appSettings.dauer * 60 } @@ -105,7 +95,7 @@ fun TimerScreen(todayTasks: List<Task>, settingsTimer: SettingsTimer, notificati .padding(vertical = 16.dp), contentAlignment = Alignment.Center ) { - val text = if(isInPause) "Pause" else "$round.Arbeitsphase" + val text = if(!isRunning) "Pause" else "$round.Arbeitsphase" TimerDisplay(text ,timeLeft = timeLeft) } @@ -128,12 +118,9 @@ 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() + if(isRunning) ViewModelProvider.getAppViewModel().stopTimer() else ViewModelProvider.getAppViewModel().runTimer() - if (pauseText=="Pause") startPomodoro(context) + // if (pauseText=="Pause") startPomodoro(context) }, modifier = Modifier.weight(1f), colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF7F56D9)) @@ -175,7 +162,7 @@ fun TimerDisplay(text: String, timeLeft: Int) { } @Composable -fun TaskList(tasks: List<Task>, taskViewModel: TaskViewModel = viewModel()) { +fun TaskList(tasks: List<Task>) { var timerState by remember { mutableStateOf(tasks) } Column { timerState.forEachIndexed() { index, task -> @@ -200,21 +187,10 @@ fun TaskList(tasks: List<Task>, taskViewModel: TaskViewModel = viewModel()) { this[index] = this[index].copy(isCompleted = !this[index].isCompleted) } - taskViewModel.updateTask(timerState[index]) + ViewModelProvider.getTaskViewModel().updateTask(timerState[index]) } ) } } } } - -fun getMusik(music:String):Int { - return when(music) { - "day" -> R.raw.day - "farm" -> R.raw.farm - "fire" -> R.raw.fire - "night" -> R.raw.night - "storm" -> R.raw.storm - else -> throw Error("ERROR") - } -} diff --git a/app/src/main/java/com/example/myapplication/UI_Components/main_app.kt b/app/src/main/java/com/example/myapplication/UI_Components/main_app.kt index 81124a656815c375fc9528f3537df5fd9be5f76e..38a43492545403c6b451f4211d2bc0a18359926a 100644 --- a/app/src/main/java/com/example/myapplication/UI_Components/main_app.kt +++ b/app/src/main/java/com/example/myapplication/UI_Components/main_app.kt @@ -13,12 +13,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.myapplication.Helpers.ViewModelProvider import com.example.myapplication.Helpers.dateAreEqual +import com.example.myapplication.MainActivity import com.example.myapplication.Room.SettingsTimer -import com.example.myapplication.Room.SettingsViewModel import com.example.myapplication.Room.Task -import com.example.myapplication.Room.TaskViewModel import com.example.myapplication.Types.NavigationType import com.example.myapplication.UI_Components.Home.HomeScreen import com.example.myapplication.UI_Components.Settings.Settings @@ -26,22 +25,18 @@ import com.example.myapplication.ui.theme.color_F5F5F5 import java.util.Date @Composable -fun main_app(settingsViewModel: SettingsViewModel = viewModel(), taskViewModel: TaskViewModel = viewModel(), notificationCallback: (titel: String, text: String) -> Unit) { - - val appSettings by settingsViewModel.getAllSettings().observeAsState(initial = SettingsTimer()) - settingsViewModel.updateSettingByEmpty() - - val allTaskList by taskViewModel.getAllSortedByDate().observeAsState(initial = emptyList()) - val currentOpenTask: List<Task> = allTaskList.filter { !it.isCompleted } - val currentCompletedTask: List<Task> = allTaskList.filter { it.isCompleted } - val todaysTask:List<Task> = allTaskList.filter { dateAreEqual(it.date, Date().time) } - - var selectedNavigation by rememberSaveable { mutableStateOf(NavigationType.Home) } +fun main_app(notificationCallback: (titel: String, text: String) -> Unit) { + val selectedNavigation by ViewModelProvider.getAppViewModel().selectedNavigation.observeAsState(initial = NavigationType.Home) + val appSettings by ViewModelProvider.getSettingsViewModel().settingsDataList.observeAsState(initial = SettingsTimer()) + val currentTasks by ViewModelProvider.getTaskViewModel().taskDataList.observeAsState(initial = emptyList()) + val openTask: List<Task> = currentTasks.filter { !it.isCompleted } + val completedTask: List<Task> = currentTasks.filter { it.isCompleted } + val todaysTask:List<Task> = currentTasks.filter { dateAreEqual(it.date, Date().time) } Scaffold( bottomBar = { if (selectedNavigation != NavigationType.Timer) { - BottomNavigationBar(selectedNavigation) { selectedNavigation = it } + BottomNavigationBar(selectedNavigation) { ViewModelProvider.getAppViewModel().setSelectedNavigation(it) } } } ) { paddingValues -> @@ -53,9 +48,11 @@ fun main_app(settingsViewModel: SettingsViewModel = viewModel(), taskViewModel: { when(selectedNavigation) { NavigationType.Settings -> Settings(appSettings) - NavigationType.Timer -> TimerScreen(todaysTask, appSettings, notificationCallback) { selectedNavigation = NavigationType.Home } - NavigationType.Home -> HomeScreen(currentOpenTask, currentCompletedTask) { - selectedNavigation = NavigationType.Timer + NavigationType.Timer -> TimerScreen(todaysTask, appSettings, notificationCallback) { + ViewModelProvider.getAppViewModel().setSelectedNavigation(NavigationType.Home) + } + NavigationType.Home -> HomeScreen(openTask, completedTask) { + ViewModelProvider.getAppViewModel().setSelectedNavigation(NavigationType.Timer) } } diff --git a/app/src/main/java/com/example/myapplication/background/createTimerNotficationChannel.kt b/app/src/main/java/com/example/myapplication/background/createTimerNotficationChannel.kt deleted file mode 100644 index 2a82a1f2bd1c7f8bcc5d98eafd87bfca84201b9b..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/myapplication/background/createTimerNotficationChannel.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.example.myapplication.background - -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import android.os.Build - -fun createNotificationChannel(context: Context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channelId = "POMODORO_CHANNEL" - val channelName = "Pomodoro Notifications" - val channelDescription = "Channel for Pomodoro notifications" - - val notificationChannel = NotificationChannel( - channelId, - channelName, - NotificationManager.IMPORTANCE_HIGH - ).apply { - description = channelDescription - } - - val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - notificationManager.createNotificationChannel(notificationChannel) - } -} \ No newline at end of file