choix rappel dans un dialog

This commit is contained in:
ImAliant 2024-01-05 16:12:58 +01:00
parent 77ad522ce2
commit 7ca1044a96
5 changed files with 105 additions and 48 deletions

View file

@ -24,6 +24,5 @@ const val STATS_TOTAL_GOOD = "total_good"
/** DataStore clef lié au nombre de questions mal répondu */ /** DataStore clef lié au nombre de questions mal répondu */
const val STATS_TOTAL_BAD = "total_bad" const val STATS_TOTAL_BAD = "total_bad"
const val ENABLED = "enabled"
const val HOUR = "hour" const val HOUR = "hour"
const val MINUTE = "minute" const val MINUTE = "minute"

View file

@ -1,7 +1,6 @@
package fr.uparis.diamantkennel.memorisationapplication package fr.uparis.diamantkennel.memorisationapplication
import android.os.Build import android.os.Build
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@ -11,22 +10,23 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TimeInput import androidx.compose.material3.TimePicker
import androidx.compose.material3.TimePickerLayoutType
import androidx.compose.material3.TimePickerState
import androidx.compose.material3.rememberTimePickerState import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue 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
@ -35,6 +35,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
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.compose.ui.window.Dialog
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import fr.uparis.diamantkennel.memorisationapplication.ui.SettingsViewModel import fr.uparis.diamantkennel.memorisationapplication.ui.SettingsViewModel
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -48,6 +49,7 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
var deletionDBRequest by model.deletionDB var deletionDBRequest by model.deletionDB
var cleanStatRequest by model.deletionStat var cleanStatRequest by model.deletionStat
var choiceTimeNotifRequest by model.notif
var permissionNotif by model.gavePermissionNow var permissionNotif by model.gavePermissionNow
val prefConfig = runBlocking { model.prefConfig.first() } val prefConfig = runBlocking { model.prefConfig.first() }
@ -57,8 +59,6 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
initialMinute = prefConfig.minute, initialMinute = prefConfig.minute,
is24Hour = true is24Hour = true
) )
var enabled by remember { mutableStateOf(prefConfig.enabled) }
model.checkPermission(context) model.checkPermission(context)
val permissionLauncher = rememberLauncherForActivityResult( val permissionLauncher = rememberLauncherForActivityResult(
@ -77,6 +77,15 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
CleanStatDialog(model::cleanStats) { cleanStatRequest = false } CleanStatDialog(model::cleanStats) { cleanStatRequest = false }
} }
if (choiceTimeNotifRequest)
{
ChoiceTimeNotifDialog(
{ (model::choiceTimeNotif)(state, context) },
{ choiceTimeNotifRequest = false },
state
)
}
Column( Column(
modifier = Modifier.padding(padding), modifier = Modifier.padding(padding),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
@ -107,31 +116,31 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
} }
} }
Button( Spacer(modifier = Modifier.padding(top = 10.dp))
enabled = !permissionNotif, Divider(color = Color.Gray)
onClick = { Spacer(modifier = Modifier.padding(top = 10.dp))
model.requestNotificationPermission(permissionLauncher)
}
) {
Text(text = context.getString(R.string.permission_button))
}
Column { Text(text = "Notifications", fontSize = 30.sp)
Row { Column(
TimeInput(state = state) modifier = Modifier.fillMaxWidth(),
Switch(enabled, { enabled = it }) horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
Button(
enabled = !permissionNotif,
onClick = {
model.requestNotificationPermission(permissionLauncher)
}
) {
Text(text = context.getString(R.string.permission_button))
} }
FloatingActionButton(onClick = { Button(
val newConfig = TimeConfig( enabled = permissionNotif,
enabled, onClick = {
state.hour, choiceTimeNotifRequest = true
state.minute }
) ) {
Log.d("Periodic", "config=$newConfig") Text(text = context.getString(R.string.time_notif_button))
model.save(newConfig)
model.schedule(newConfig, context)
}) {
Text("On y va!")
} }
} }
} }
@ -184,3 +193,41 @@ fun CleanStatDialog(confirm: () -> Unit, dismiss: () -> Unit) =
Button(onClick = confirm) { Text(text = LocalContext.current.getString(R.string.yes)) } Button(onClick = confirm) { Text(text = LocalContext.current.getString(R.string.yes)) }
}, },
dismissButton = { Button(onClick = dismiss) { Text(text = LocalContext.current.getString(R.string.no)) } }) dismissButton = { Button(onClick = dismiss) { Text(text = LocalContext.current.getString(R.string.no)) } })
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ChoiceTimeNotifDialog(confirm: () -> Unit, dismiss: () -> Unit, state: TimePickerState) {
Dialog(onDismissRequest = { dismiss() }) {
Card(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.height(550.dp),
shape = RoundedCornerShape(16.dp),
) {
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = LocalContext.current.getString(R.string.time_notif), fontSize = 30.sp)
Text(text = LocalContext.current.getString(R.string.time_notif_desc))
Spacer(modifier = Modifier.padding(top = 10.dp))
TimePicker(state = state, layoutType = TimePickerLayoutType.Vertical)
Spacer(modifier = Modifier.padding(top = 10.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(onClick = dismiss) {
Text(text = LocalContext.current.getString(R.string.no))
}
Button(onClick = confirm) {
Text(text = LocalContext.current.getString(R.string.yes))
}
}
}
}
}
}

View file

@ -1,7 +1,6 @@
package fr.uparis.diamantkennel.memorisationapplication package fr.uparis.diamantkennel.memorisationapplication
data class TimeConfig( data class TimeConfig(
val enabled: Boolean = false,
val hour: Int = 8, val hour: Int = 8,
val minute: Int = 0 val minute: Int = 0
) )

View file

@ -7,15 +7,15 @@ import android.os.Build
import android.util.Log import android.util.Log
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.TimePickerState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.work.PeriodicWorkRequest import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
import fr.uparis.diamantkennel.memorisationapplication.ENABLED
import fr.uparis.diamantkennel.memorisationapplication.HOUR import fr.uparis.diamantkennel.memorisationapplication.HOUR
import fr.uparis.diamantkennel.memorisationapplication.MINUTE import fr.uparis.diamantkennel.memorisationapplication.MINUTE
import fr.uparis.diamantkennel.memorisationapplication.MemoApplication import fr.uparis.diamantkennel.memorisationapplication.MemoApplication
@ -41,9 +41,8 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
private val statsKeyTotalGood = intPreferencesKey(STATS_TOTAL_GOOD) private val statsKeyTotalGood = intPreferencesKey(STATS_TOTAL_GOOD)
private val statsKeyTotalBad = intPreferencesKey(STATS_TOTAL_BAD) private val statsKeyTotalBad = intPreferencesKey(STATS_TOTAL_BAD)
private val KEY_E = booleanPreferencesKey(ENABLED) private val notifH = intPreferencesKey(HOUR)
private val KEY_H = intPreferencesKey(HOUR) private val notifM = intPreferencesKey(MINUTE)
private val KEY_M = intPreferencesKey(MINUTE)
val statTotal = stats.data.map { it[statsKeyTotal] ?: 0 } val statTotal = stats.data.map { it[statsKeyTotal] ?: 0 }
val statTotalDone = stats.data.map { it[statsKeyTotalDone] ?: 0 } val statTotalDone = stats.data.map { it[statsKeyTotalDone] ?: 0 }
@ -52,6 +51,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
val deletionDB = mutableStateOf(false) val deletionDB = mutableStateOf(false)
val deletionStat = mutableStateOf(false) val deletionStat = mutableStateOf(false)
var notif = mutableStateOf(false)
val gavePermissionNow = mutableStateOf(false) val gavePermissionNow = mutableStateOf(false)
@ -74,6 +74,18 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
fun choiceTimeNotif(state: TimePickerState, context: Context) {
notif.value = false
val newConfig = TimeConfig(
state.hour,
state.minute
)
Log.d("Periodic", "config=$newConfig")
save(newConfig)
schedule(newConfig, context)
}
fun winrate(good: Int, bad: Int): Int { fun winrate(good: Int, bad: Int): Int {
val total = good + bad val total = good + bad
if (total == 0) { if (total == 0) {
@ -96,26 +108,23 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
fun save(config: TimeConfig) { fun save(config: TimeConfig) {
viewModelScope.launch { viewModelScope.launch {
stats.edit { stats.edit {
it[KEY_E] = config.enabled it[notifH] = config.hour
it[KEY_H] = config.hour it[notifM] = config.minute
it[KEY_M] = config.minute
} }
} }
} }
val prefConfig = stats.data.map { val prefConfig = stats.data.map {
TimeConfig( TimeConfig(
it[KEY_E] ?: false, it[notifH] ?: 8,
it[KEY_H] ?: 8, it[notifM] ?: 0
it[KEY_M] ?: 0
) )
} }
fun schedule(config: TimeConfig, context: Context) { private fun schedule(config: TimeConfig, context: Context) {
val wm = WorkManager.getInstance(context) val wm = WorkManager.getInstance(context)
wm.cancelAllWork() wm.cancelAllWork()
if (config.enabled) wm.enqueue(request(config.hour, config.minute))
wm.enqueue(request(config.hour, config.minute))
} }
private fun request(h: Int, m: Int): PeriodicWorkRequest { private fun request(h: Int, m: Int): PeriodicWorkRequest {

View file

@ -21,7 +21,7 @@
<string name="error">Erreur</string> <string name="error">Erreur</string>
<string name="delete_set_questions">Supprimer un jeu de question</string> <string name="delete_set_questions">Supprimer un jeu de question</string>
<string name="delete_set_qestions_desc">Voulez-vous supprimer ce jeu de question ?</string> <string name="delete_set_qestions_desc">Voulez-vous supprimer ce jeu de question ?</string>
<string name="ok">Ok</string> <string name="ok">OK</string>
<string name="update_question">Mettre à jour la question</string> <string name="update_question">Mettre à jour la question</string>
<string name="add_question">Ajouter une question</string> <string name="add_question">Ajouter une question</string>
<string name="question">Question</string> <string name="question">Question</string>
@ -55,4 +55,7 @@
<string name="notif_channel_desc">Notifications de rappel</string> <string name="notif_channel_desc">Notifications de rappel</string>
<string name="notif_reminder_title">Rappel</string> <string name="notif_reminder_title">Rappel</string>
<string name="notif_reminder_content">Il est temps de réviser !</string> <string name="notif_reminder_content">Il est temps de réviser !</string>
<string name="time_notif_button">Modifier heure de rappel</string>
<string name="time_notif">Choix heure de rappel</string>
<string name="time_notif_desc">Choisissez l\'heure à laquelle vous souhaitez être notifié</string>
</resources> </resources>