choix rappel dans un dialog
This commit is contained in:
parent
77ad522ce2
commit
7ca1044a96
5 changed files with 105 additions and 48 deletions
|
@ -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"
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Reference in a new issue