From 77ad522ce20631e6da6c52a5a4fbb692e3bc24ab Mon Sep 17 00:00:00 2001
From: ImAliant <111398111+ImAliant@users.noreply.github.com>
Date: Fri, 5 Jan 2024 13:39:22 +0100
Subject: [PATCH 1/5] la notification fonctionne correctement
---
app/build.gradle.kts | 6 +-
.../memorisationapplication/DataStore.kt | 4 ++
.../MemoApplication.kt | 30 ----------
.../memorisationapplication/SettingsScreen.kt | 40 +++++++++++++
.../memorisationapplication/TimeConfig.kt | 7 +++
.../ui/SettingsViewModel.kt | 56 +++++++++++++++++++
6 files changed, 110 insertions(+), 33 deletions(-)
create mode 100644 app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index a7cdee8..c42a35f 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -51,14 +51,14 @@ android {
}
dependencies {
- implementation("androidx.core:core-ktx:1.9.0")
+ implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
- implementation("androidx.activity:activity-compose:1.8.0")
+ implementation("androidx.activity:activity-compose:1.8.1")
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
- implementation("androidx.compose.material3:material3")
+ implementation("androidx.compose.material3:material3:1.1.2")
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.work:work-runtime-ktx:2.8.1")
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
index 22d3187..a078787 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
@@ -23,3 +23,7 @@ const val STATS_TOTAL_GOOD = "total_good"
/** DataStore clef lié au nombre de questions mal répondu */
const val STATS_TOTAL_BAD = "total_bad"
+
+const val ENABLED = "enabled"
+const val HOUR = "hour"
+const val MINUTE = "minute"
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt
index 0ad4780..57b6e80 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt
@@ -4,13 +4,8 @@ import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
-import android.content.pm.PackageManager
import android.os.Build
-import androidx.work.PeriodicWorkRequest
-import androidx.work.WorkManager
import fr.uparis.diamantkennel.memorisationapplication.data.QuestionsDB
-import java.util.Calendar
-import java.util.concurrent.TimeUnit
const val CHANNEL_ID = "MY_CHANNEL_ID"
@@ -20,10 +15,6 @@ class MemoApplication : Application() {
override fun onCreate() {
super.onCreate()
createChannel(this)
-
- if (this.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
- schedule()
- }
}
private fun createChannel(c: Context) {
@@ -39,25 +30,4 @@ class MemoApplication : Application() {
notificationManager.createNotificationChannel(channel)
}
}
-
- private fun schedule() {
- val wm = WorkManager.getInstance(this)
- wm.cancelAllWork()
- wm.enqueue(request(10, 45))
- }
-
- private fun request(h: Int, m: Int): PeriodicWorkRequest {
- val now = Calendar.getInstance()
- val target = Calendar.getInstance().apply {
- set(Calendar.HOUR_OF_DAY, h)
- set(Calendar.MINUTE, m)
- }
- if (target.before(now))
- target.add(Calendar.DAY_OF_YEAR, 1)
- val delta = target.timeInMillis - now.timeInMillis
-
- return PeriodicWorkRequest.Builder(RappelWorker::class.java, 1, TimeUnit.DAYS)
- .setInitialDelay(delta, TimeUnit.MILLISECONDS)
- .build()
- }
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
index 9ed1951..8336144 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
@@ -1,6 +1,7 @@
package fr.uparis.diamantkennel.memorisationapplication
import android.os.Build
+import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
@@ -15,10 +16,17 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Divider
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.FloatingActionButton
+import androidx.compose.material3.Switch
import androidx.compose.material3.Text
+import androidx.compose.material3.TimeInput
+import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.Modifier
@@ -29,8 +37,11 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.uparis.diamantkennel.memorisationapplication.ui.SettingsViewModel
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel()) {
val context = LocalContext.current
@@ -38,6 +49,16 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
var deletionDBRequest by model.deletionDB
var cleanStatRequest by model.deletionStat
var permissionNotif by model.gavePermissionNow
+
+ val prefConfig = runBlocking { model.prefConfig.first() }
+
+ val state = rememberTimePickerState(
+ initialHour = prefConfig.hour,
+ initialMinute = prefConfig.minute,
+ is24Hour = true
+ )
+ var enabled by remember { mutableStateOf(prefConfig.enabled) }
+
model.checkPermission(context)
val permissionLauncher = rememberLauncherForActivityResult(
@@ -94,6 +115,25 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
) {
Text(text = context.getString(R.string.permission_button))
}
+
+ Column {
+ Row {
+ TimeInput(state = state)
+ Switch(enabled, { enabled = it })
+ }
+ FloatingActionButton(onClick = {
+ val newConfig = TimeConfig(
+ enabled,
+ state.hour,
+ state.minute
+ )
+ Log.d("Periodic", "config=$newConfig")
+ model.save(newConfig)
+ model.schedule(newConfig, context)
+ }) {
+ Text("On y va!")
+ }
+ }
}
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt
new file mode 100644
index 0000000..837ce13
--- /dev/null
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt
@@ -0,0 +1,7 @@
+package fr.uparis.diamantkennel.memorisationapplication
+
+data class TimeConfig(
+ val enabled: Boolean = false,
+ val hour: Int = 8,
+ val minute: Int = 0
+)
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
index a80e26b..8a5100b 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
@@ -4,22 +4,33 @@ import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
+import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
import androidx.compose.runtime.mutableStateOf
+import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
+import androidx.work.PeriodicWorkRequest
+import androidx.work.WorkManager
+import fr.uparis.diamantkennel.memorisationapplication.ENABLED
+import fr.uparis.diamantkennel.memorisationapplication.HOUR
+import fr.uparis.diamantkennel.memorisationapplication.MINUTE
import fr.uparis.diamantkennel.memorisationapplication.MemoApplication
+import fr.uparis.diamantkennel.memorisationapplication.RappelWorker
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_BAD
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_DONE
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_GOOD
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_TRIED
+import fr.uparis.diamantkennel.memorisationapplication.TimeConfig
import fr.uparis.diamantkennel.memorisationapplication.dataStore
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
+import java.util.Calendar
+import java.util.concurrent.TimeUnit
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
private val dao = (application as MemoApplication).database.memoDao()
@@ -30,6 +41,10 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
private val statsKeyTotalGood = intPreferencesKey(STATS_TOTAL_GOOD)
private val statsKeyTotalBad = intPreferencesKey(STATS_TOTAL_BAD)
+ private val KEY_E = booleanPreferencesKey(ENABLED)
+ private val KEY_H = intPreferencesKey(HOUR)
+ private val KEY_M = intPreferencesKey(MINUTE)
+
val statTotal = stats.data.map { it[statsKeyTotal] ?: 0 }
val statTotalDone = stats.data.map { it[statsKeyTotalDone] ?: 0 }
val statTotalGood = stats.data.map { it[statsKeyTotalGood] ?: 0 }
@@ -77,4 +92,45 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
gavePermissionNow.value =
context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
}
+
+ fun save(config: TimeConfig) {
+ viewModelScope.launch {
+ stats.edit {
+ it[KEY_E] = config.enabled
+ it[KEY_H] = config.hour
+ it[KEY_M] = config.minute
+ }
+ }
+ }
+
+ val prefConfig = stats.data.map {
+ TimeConfig(
+ it[KEY_E] ?: false,
+ it[KEY_H] ?: 8,
+ it[KEY_M] ?: 0
+ )
+ }
+
+ fun schedule(config: TimeConfig, context: Context) {
+ val wm = WorkManager.getInstance(context)
+ wm.cancelAllWork()
+ if (config.enabled)
+ wm.enqueue(request(config.hour, config.minute))
+ }
+
+ private fun request(h: Int, m: Int): PeriodicWorkRequest {
+ val now = Calendar.getInstance()
+ val target = Calendar.getInstance().apply {
+ set(Calendar.HOUR_OF_DAY, h)
+ set(Calendar.MINUTE, m)
+ }
+ if (target.before(now))
+ target.add(Calendar.DAY_OF_YEAR, 1)
+ val delta = target.timeInMillis - now.timeInMillis
+ val request = PeriodicWorkRequest.Builder(RappelWorker::class.java, 1, TimeUnit.DAYS)
+ .setInitialDelay(delta, TimeUnit.MILLISECONDS)
+ .build()
+ Log.d("Periodic", "request: $request")
+ return request
+ }
}
From 7ca1044a96c2e14ac2b4b0c0c2910b86bb5c4a36 Mon Sep 17 00:00:00 2001
From: ImAliant <111398111+ImAliant@users.noreply.github.com>
Date: Fri, 5 Jan 2024 16:12:58 +0100
Subject: [PATCH 2/5] choix rappel dans un dialog
---
.../memorisationapplication/DataStore.kt | 1 -
.../memorisationapplication/SettingsScreen.kt | 109 +++++++++++++-----
.../memorisationapplication/TimeConfig.kt | 1 -
.../ui/SettingsViewModel.kt | 37 +++---
app/src/main/res/values/strings.xml | 5 +-
5 files changed, 105 insertions(+), 48 deletions(-)
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
index a078787..2076663 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
@@ -24,6 +24,5 @@ const val STATS_TOTAL_GOOD = "total_good"
/** DataStore clef lié au nombre de questions mal répondu */
const val STATS_TOTAL_BAD = "total_bad"
-const val ENABLED = "enabled"
const val HOUR = "hour"
const val MINUTE = "minute"
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
index 8336144..a5022ad 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
@@ -1,7 +1,6 @@
package fr.uparis.diamantkennel.memorisationapplication
import android.os.Build
-import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
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.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Card
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.FloatingActionButton
-import androidx.compose.material3.Switch
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.runtime.Composable
import androidx.compose.runtime.collectAsState
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.Modifier
@@ -35,6 +35,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.Dialog
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.uparis.diamantkennel.memorisationapplication.ui.SettingsViewModel
import kotlinx.coroutines.flow.first
@@ -48,6 +49,7 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
var deletionDBRequest by model.deletionDB
var cleanStatRequest by model.deletionStat
+ var choiceTimeNotifRequest by model.notif
var permissionNotif by model.gavePermissionNow
val prefConfig = runBlocking { model.prefConfig.first() }
@@ -57,8 +59,6 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
initialMinute = prefConfig.minute,
is24Hour = true
)
- var enabled by remember { mutableStateOf(prefConfig.enabled) }
-
model.checkPermission(context)
val permissionLauncher = rememberLauncherForActivityResult(
@@ -77,6 +77,15 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
CleanStatDialog(model::cleanStats) { cleanStatRequest = false }
}
+ if (choiceTimeNotifRequest)
+ {
+ ChoiceTimeNotifDialog(
+ { (model::choiceTimeNotif)(state, context) },
+ { choiceTimeNotifRequest = false },
+ state
+ )
+ }
+
Column(
modifier = Modifier.padding(padding),
horizontalAlignment = Alignment.CenterHorizontally
@@ -107,31 +116,31 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
}
}
- Button(
- enabled = !permissionNotif,
- onClick = {
- model.requestNotificationPermission(permissionLauncher)
- }
- ) {
- Text(text = context.getString(R.string.permission_button))
- }
+ Spacer(modifier = Modifier.padding(top = 10.dp))
+ Divider(color = Color.Gray)
+ Spacer(modifier = Modifier.padding(top = 10.dp))
- Column {
- Row {
- TimeInput(state = state)
- Switch(enabled, { enabled = it })
+ Text(text = "Notifications", fontSize = 30.sp)
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Button(
+ enabled = !permissionNotif,
+ onClick = {
+ model.requestNotificationPermission(permissionLauncher)
+ }
+ ) {
+ Text(text = context.getString(R.string.permission_button))
}
- FloatingActionButton(onClick = {
- val newConfig = TimeConfig(
- enabled,
- state.hour,
- state.minute
- )
- Log.d("Periodic", "config=$newConfig")
- model.save(newConfig)
- model.schedule(newConfig, context)
- }) {
- Text("On y va!")
+ Button(
+ enabled = permissionNotif,
+ onClick = {
+ choiceTimeNotifRequest = true
+ }
+ ) {
+ Text(text = context.getString(R.string.time_notif_button))
}
}
}
@@ -184,3 +193,41 @@ fun CleanStatDialog(confirm: () -> Unit, dismiss: () -> Unit) =
Button(onClick = confirm) { Text(text = LocalContext.current.getString(R.string.yes)) }
},
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))
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt
index 837ce13..eaf35c4 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/TimeConfig.kt
@@ -1,7 +1,6 @@
package fr.uparis.diamantkennel.memorisationapplication
data class TimeConfig(
- val enabled: Boolean = false,
val hour: Int = 8,
val minute: Int = 0
)
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
index 8a5100b..d0f4413 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
@@ -7,15 +7,15 @@ import android.os.Build
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.TimePickerState
import androidx.compose.runtime.mutableStateOf
-import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
-import fr.uparis.diamantkennel.memorisationapplication.ENABLED
import fr.uparis.diamantkennel.memorisationapplication.HOUR
import fr.uparis.diamantkennel.memorisationapplication.MINUTE
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 statsKeyTotalBad = intPreferencesKey(STATS_TOTAL_BAD)
- private val KEY_E = booleanPreferencesKey(ENABLED)
- private val KEY_H = intPreferencesKey(HOUR)
- private val KEY_M = intPreferencesKey(MINUTE)
+ private val notifH = intPreferencesKey(HOUR)
+ private val notifM = intPreferencesKey(MINUTE)
val statTotal = stats.data.map { it[statsKeyTotal] ?: 0 }
val statTotalDone = stats.data.map { it[statsKeyTotalDone] ?: 0 }
@@ -52,6 +51,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
val deletionDB = mutableStateOf(false)
val deletionStat = mutableStateOf(false)
+ var notif = 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 {
val total = good + bad
if (total == 0) {
@@ -96,26 +108,23 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
fun save(config: TimeConfig) {
viewModelScope.launch {
stats.edit {
- it[KEY_E] = config.enabled
- it[KEY_H] = config.hour
- it[KEY_M] = config.minute
+ it[notifH] = config.hour
+ it[notifM] = config.minute
}
}
}
val prefConfig = stats.data.map {
TimeConfig(
- it[KEY_E] ?: false,
- it[KEY_H] ?: 8,
- it[KEY_M] ?: 0
+ it[notifH] ?: 8,
+ it[notifM] ?: 0
)
}
- fun schedule(config: TimeConfig, context: Context) {
+ private fun schedule(config: TimeConfig, context: Context) {
val wm = WorkManager.getInstance(context)
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 {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ea7ff63..25f66b0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -21,7 +21,7 @@
Erreur
Supprimer un jeu de question
Voulez-vous supprimer ce jeu de question ?
- Ok
+ OK
Mettre à jour la question
Ajouter une question
Question
@@ -55,4 +55,7 @@
Notifications de rappel
Rappel
Il est temps de réviser !
+ Modifier heure de rappel
+ Choix heure de rappel
+ Choisissez l\'heure à laquelle vous souhaitez être notifié
From cb9a063e68d0c3c96d7b206a684871ced5324e7e Mon Sep 17 00:00:00 2001
From: Mylloon
Date: Fri, 5 Jan 2024 17:26:19 +0100
Subject: [PATCH 3/5] minor changes
---
.../MemoApplication.kt | 2 +-
.../memorisationapplication/SettingsScreen.kt | 80 +++++++++----------
.../ui/SettingsViewModel.kt | 18 ++---
app/src/main/res/values/strings.xml | 4 +-
4 files changed, 45 insertions(+), 59 deletions(-)
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt
index 57b6e80..64c2b4e 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MemoApplication.kt
@@ -7,7 +7,7 @@ import android.content.Context
import android.os.Build
import fr.uparis.diamantkennel.memorisationapplication.data.QuestionsDB
-const val CHANNEL_ID = "MY_CHANNEL_ID"
+const val CHANNEL_ID = "REMINDERS"
class MemoApplication : Application() {
val database: QuestionsDB by lazy { QuestionsDB.getDataBase(this) }
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
index a5022ad..c206e6c 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
@@ -33,6 +33,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
@@ -77,10 +78,9 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
CleanStatDialog(model::cleanStats) { cleanStatRequest = false }
}
- if (choiceTimeNotifRequest)
- {
+ if (choiceTimeNotifRequest) {
ChoiceTimeNotifDialog(
- { (model::choiceTimeNotif)(state, context) },
+ { model.choiceTimeNotif(state, context) },
{ choiceTimeNotifRequest = false },
state
)
@@ -96,35 +96,10 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
Divider(color = Color.Gray)
Spacer(modifier = Modifier.padding(top = 10.dp))
- Text(text = "Gestion", fontSize = 30.sp)
+ Text(text = context.getString(R.string.notification), fontSize = 30.sp)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
- ) {
- Button(
- onClick = { deletionDBRequest = true },
- colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
- ) {
- Text(text = context.getString(R.string.main_button_deletebase))
- }
-
- Button(
- onClick = { cleanStatRequest = true },
- colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
- ) {
- Text(text = context.getString(R.string.clean_stat_button))
- }
- }
-
- Spacer(modifier = Modifier.padding(top = 10.dp))
- Divider(color = Color.Gray)
- Spacer(modifier = Modifier.padding(top = 10.dp))
-
- Text(text = "Notifications", fontSize = 30.sp)
- Column(
- modifier = Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.SpaceEvenly
) {
Button(
enabled = !permissionNotif,
@@ -143,6 +118,30 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
Text(text = context.getString(R.string.time_notif_button))
}
}
+
+ Spacer(modifier = Modifier.padding(top = 10.dp))
+ Divider(color = Color.Gray)
+ Spacer(modifier = Modifier.padding(top = 10.dp))
+
+ Text(text = context.getString(R.string.gestion), fontSize = 30.sp)
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Button(
+ onClick = { deletionDBRequest = true },
+ colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
+ ) {
+ Text(text = context.getString(R.string.main_button_deletebase))
+ }
+
+ Button(
+ onClick = { cleanStatRequest = true },
+ colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
+ ) {
+ Text(text = context.getString(R.string.clean_stat_button))
+ }
+ }
}
}
@@ -197,7 +196,7 @@ fun CleanStatDialog(confirm: () -> Unit, dismiss: () -> Unit) =
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ChoiceTimeNotifDialog(confirm: () -> Unit, dismiss: () -> Unit, state: TimePickerState) {
- Dialog(onDismissRequest = { dismiss() }) {
+ Dialog(onDismissRequest = dismiss) {
Card(
modifier = Modifier
.padding(16.dp)
@@ -209,23 +208,16 @@ fun ChoiceTimeNotifDialog(confirm: () -> Unit, dismiss: () -> Unit, state: TimeP
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))
+ Text(
+ text = LocalContext.current.getString(R.string.time_notif),
+ fontSize = 30.sp,
+ textAlign = TextAlign.Center
+ )
- 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))
- }
+ Button(onClick = confirm) {
+ Text(text = LocalContext.current.getString(R.string.confirm))
}
}
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
index d0f4413..7aa6dfa 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
@@ -4,7 +4,6 @@ import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
-import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -49,6 +48,8 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
val statTotalGood = stats.data.map { it[statsKeyTotalGood] ?: 0 }
val statTotalBad = stats.data.map { it[statsKeyTotalBad] ?: 0 }
+ var prefConfig = stats.data.map { TimeConfig(it[notifH] ?: 8, it[notifM] ?: 0) }
+
val deletionDB = mutableStateOf(false)
val deletionStat = mutableStateOf(false)
var notif = mutableStateOf(false)
@@ -81,7 +82,6 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
state.hour,
state.minute
)
- Log.d("Periodic", "config=$newConfig")
save(newConfig)
schedule(newConfig, context)
}
@@ -105,7 +105,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
}
- fun save(config: TimeConfig) {
+ private fun save(config: TimeConfig) {
viewModelScope.launch {
stats.edit {
it[notifH] = config.hour
@@ -114,13 +114,6 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
}
}
- val prefConfig = stats.data.map {
- TimeConfig(
- it[notifH] ?: 8,
- it[notifM] ?: 0
- )
- }
-
private fun schedule(config: TimeConfig, context: Context) {
val wm = WorkManager.getInstance(context)
wm.cancelAllWork()
@@ -136,10 +129,9 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
if (target.before(now))
target.add(Calendar.DAY_OF_YEAR, 1)
val delta = target.timeInMillis - now.timeInMillis
- val request = PeriodicWorkRequest.Builder(RappelWorker::class.java, 1, TimeUnit.DAYS)
+
+ return PeriodicWorkRequest.Builder(RappelWorker::class.java, 1, TimeUnit.DAYS)
.setInitialDelay(delta, TimeUnit.MILLISECONDS)
.build()
- Log.d("Periodic", "request: $request")
- return request
}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 25f66b0..e1b0908 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -57,5 +57,7 @@
Il est temps de réviser !
Modifier heure de rappel
Choix heure de rappel
- Choisissez l\'heure à laquelle vous souhaitez être notifié
+ Gestion
+ Notifications
+ Confirmer
From 920bd24742f4498c9021beb0b5dffdd7f4a907ba Mon Sep 17 00:00:00 2001
From: ImAliant <111398111+ImAliant@users.noreply.github.com>
Date: Sat, 6 Jan 2024 17:25:08 +0100
Subject: [PATCH 4/5] =?UTF-8?q?parametrage=20delai=20r=C3=A9ponse?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../memorisationapplication/DataStore.kt | 2 +
.../memorisationapplication/PlayScreen.kt | 6 +-
.../memorisationapplication/SettingsScreen.kt | 182 +++++++++++++-----
.../ui/PlayViewModel.kt | 19 +-
.../ui/SettingsViewModel.kt | 29 ++-
app/src/main/res/values/strings.xml | 6 +
6 files changed, 179 insertions(+), 65 deletions(-)
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
index 2076663..d040a39 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/DataStore.kt
@@ -24,5 +24,7 @@ const val STATS_TOTAL_GOOD = "total_good"
/** DataStore clef lié au nombre de questions mal répondu */
const val STATS_TOTAL_BAD = "total_bad"
+const val DELAY = "delay"
+
const val HOUR = "hour"
const val MINUTE = "minute"
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt
index 6c0589f..d170872 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt
@@ -16,6 +16,7 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@@ -48,6 +49,7 @@ fun PlayScreen(
val correction by model.evaluatedAnswer
var giveup by model.showAnswer
val gameEnded by model.end
+ val delay by model.delay.collectAsState(initial = 3000)
val cpt by model.compteurSb
if (correction != null) {
@@ -72,7 +74,7 @@ fun PlayScreen(
}
// Update timer if needed
- if (!model.isDelayElapsed() && question != null) {
+ if (!model.isDelayElapsed(delay) && question != null) {
model.updateTime(System.currentTimeMillis())
}
@@ -109,7 +111,7 @@ fun PlayScreen(
}
Button(
- enabled = model.isDelayElapsed(),
+ enabled = model.isDelayElapsed(delay),
onClick = { giveup = true }) {
Text(text = context.getString(R.string.see_answer))
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
index c206e6c..f5159ae 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
@@ -1,7 +1,9 @@
package fr.uparis.diamantkennel.memorisationapplication
+import android.content.Context
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.Arrangement
@@ -13,12 +15,14 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TimePicker
import androidx.compose.material3.TimePickerLayoutType
@@ -27,12 +31,15 @@ import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -51,15 +58,17 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
var deletionDBRequest by model.deletionDB
var cleanStatRequest by model.deletionStat
var choiceTimeNotifRequest by model.notif
+ var choiceDelayRequest by model.delayRequest
var permissionNotif by model.gavePermissionNow
- val prefConfig = runBlocking { model.prefConfig.first() }
+ val prefConfigTime = runBlocking { model.prefConfigTime.first() }
- val state = rememberTimePickerState(
- initialHour = prefConfig.hour,
- initialMinute = prefConfig.minute,
+ val stateTime = rememberTimePickerState(
+ initialHour = prefConfigTime.hour,
+ initialMinute = prefConfigTime.minute,
is24Hour = true
)
+
model.checkPermission(context)
val permissionLauncher = rememberLauncherForActivityResult(
@@ -80,9 +89,16 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
if (choiceTimeNotifRequest) {
ChoiceTimeNotifDialog(
- { model.choiceTimeNotif(state, context) },
+ { model.choiceTimeNotif(stateTime, context) },
{ choiceTimeNotifRequest = false },
- state
+ stateTime
+ )
+ }
+
+ if (choiceDelayRequest) {
+ ChoiceDelayDialog(
+ { model.choiceDelay(it) },
+ { choiceDelayRequest = false },
)
}
@@ -92,54 +108,89 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
) {
Stats(model)
- Spacer(modifier = Modifier.padding(top = 10.dp))
- Divider(color = Color.Gray)
- Spacer(modifier = Modifier.padding(top = 10.dp))
+ AddSpacedDivider()
- Text(text = context.getString(R.string.notification), fontSize = 30.sp)
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.SpaceEvenly
- ) {
- Button(
- enabled = !permissionNotif,
- onClick = {
- model.requestNotificationPermission(permissionLauncher)
- }
- ) {
- Text(text = context.getString(R.string.permission_button))
- }
- Button(
- enabled = permissionNotif,
- onClick = {
- choiceTimeNotifRequest = true
- }
- ) {
- Text(text = context.getString(R.string.time_notif_button))
- }
+ NotificationSettings(context, model, permissionNotif, permissionLauncher) {
+ choiceTimeNotifRequest = true
}
- Spacer(modifier = Modifier.padding(top = 10.dp))
- Divider(color = Color.Gray)
- Spacer(modifier = Modifier.padding(top = 10.dp))
+ AddSpacedDivider()
- Text(text = context.getString(R.string.gestion), fontSize = 30.sp)
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.SpaceEvenly
- ) {
- Button(
- onClick = { deletionDBRequest = true },
- colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
- ) {
- Text(text = context.getString(R.string.main_button_deletebase))
+ GestionSettings(context, { deletionDBRequest = true }, { cleanStatRequest = true })
+
+ AddSpacedDivider()
+
+ GameSettings(context) { choiceDelayRequest = true }
+ }
+}
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+@Composable
+fun NotificationSettings(
+ context: Context,
+ model: SettingsViewModel,
+ permissionNotif: Boolean,
+ permissionLauncher: ActivityResultLauncher,
+ onTimeNotifButtonClick: () -> Unit,
+) {
+ Text(text = context.getString(R.string.notification), fontSize = 30.sp)
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Button(
+ enabled = !permissionNotif,
+ onClick = {
+ model.requestNotificationPermission(permissionLauncher)
}
+ ) {
+ Text(text = context.getString(R.string.permission_button))
+ }
+ Button(
+ enabled = permissionNotif,
+ onClick = onTimeNotifButtonClick
+ ) {
+ Text(text = context.getString(R.string.time_notif_button))
+ }
+ }
+}
- Button(
- onClick = { cleanStatRequest = true },
- colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
- ) {
- Text(text = context.getString(R.string.clean_stat_button))
+@Composable
+fun GestionSettings(context: Context, deletionDBRequest: () -> Unit, cleanStatRequest: () -> Unit) {
+ Text(text = context.getString(R.string.gestion), fontSize = 30.sp)
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Button(
+ onClick = deletionDBRequest,
+ colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
+ ) {
+ Text(text = context.getString(R.string.main_button_deletebase))
+ }
+
+ Button(
+ onClick = cleanStatRequest,
+ colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
+ ) {
+ Text(text = context.getString(R.string.clean_stat_button))
+ }
+ }
+}
+
+@Composable
+fun GameSettings(context: Context, onDelayButtonClick: () -> Unit) {
+ Text(text = context.getString(R.string.game), fontSize = 30.sp)
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Column (
+ modifier = Modifier.fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ){
+ Button(onClick = onDelayButtonClick) {
+ Text(text = context.getString(R.string.choice_delay_button))
}
}
}
@@ -223,3 +274,38 @@ fun ChoiceTimeNotifDialog(confirm: () -> Unit, dismiss: () -> Unit, state: TimeP
}
}
}
+
+@Composable
+fun ChoiceDelayDialog(confirm: (Int) -> Unit, dismiss: () -> Unit) {
+ var value by remember { mutableStateOf("") }
+
+ AlertDialog(onDismissRequest = dismiss,
+ title = { Text(text = LocalContext.current.getString(R.string.choice_delay)) },
+ text = {
+ OutlinedTextField(
+ value = value,
+ onValueChange = {
+ value = if (it.toIntOrNull() != null) { it } else ""
+ },
+ label = { Text(text = LocalContext.current.getString(R.string.enter_integer)) },
+ keyboardOptions = KeyboardOptions.Default.copy(
+ keyboardType = KeyboardType.Number
+ ),
+ singleLine = true
+ )
+ },
+ confirmButton = {
+ Button(onClick = { if (value.isNotBlank()) { confirm(value.toInt()) } }) {
+ Text(text = LocalContext.current.getString(R.string.confirm))
+ }
+ }
+ )
+}
+
+
+@Composable
+fun AddSpacedDivider() {
+ Spacer(modifier = Modifier.padding(top = 20.dp))
+ Divider(color = Color.Gray)
+ Spacer(modifier = Modifier.padding(top = 20.dp))
+}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt
index f9e6c5a..0d677b8 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt
@@ -11,21 +11,26 @@ import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_BAD
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_DONE
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_GOOD
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_TRIED
+import fr.uparis.diamantkennel.memorisationapplication.DELAY
import fr.uparis.diamantkennel.memorisationapplication.data.Question
import fr.uparis.diamantkennel.memorisationapplication.dataStore
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
class PlayViewModel(application: Application) : AndroidViewModel(application) {
private val dao = (application as MemoApplication).database.memoDao()
private var questions = mutableStateOf>(listOf())
- private val stats = application.dataStore
+ private val datastore = application.dataStore
private val statsKeyTotal = intPreferencesKey(STATS_TOTAL_TRIED)
private val statsKeyTotalDone = intPreferencesKey(STATS_TOTAL_DONE)
private val statsKeyTotalGood = intPreferencesKey(STATS_TOTAL_GOOD)
private val statsKeyTotalBad = intPreferencesKey(STATS_TOTAL_BAD)
+ private val delayKey= intPreferencesKey(DELAY)
+ val delay = datastore.data.map { it[delayKey] ?: 3000 }
+
var currentQuestion = mutableStateOf(null)
private var index = mutableStateOf(0)
var proposedAnswer = mutableStateOf("")
@@ -42,7 +47,7 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
dao.loadQuestions(setId).collect { questionList ->
questions.value = questionList.shuffled()
if (questions.value.isNotEmpty()) {
- stats.edit { it[statsKeyTotal] = (it[statsKeyTotal] ?: 0) + 1 }
+ datastore.edit { it[statsKeyTotal] = (it[statsKeyTotal] ?: 0) + 1 }
}
updateQuestion()
}
@@ -58,7 +63,7 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
/* Fin des questions */
end.value = true
viewModelScope.launch {
- stats.edit {
+ datastore.edit {
it[statsKeyTotalDone] = (it[statsKeyTotalDone] ?: 0) + 1
}
}
@@ -114,7 +119,7 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
when (evaluatedAnswer.value!!) {
AnswerType.GOOD -> {
viewModelScope.launch {
- stats.edit {
+ datastore.edit {
it[statsKeyTotalGood] = (it[statsKeyTotalGood] ?: 0) + 1
}
}
@@ -123,7 +128,7 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
AnswerType.BAD -> {
viewModelScope.launch {
- stats.edit {
+ datastore.edit {
it[statsKeyTotalBad] = (it[statsKeyTotalBad] ?: 0) + 1
}
}
@@ -132,10 +137,10 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
}
}
- fun isDelayElapsed() = currentTime.value - timestampQuestion.value >= 3000
+ fun isDelayElapsed(delay: Int) = currentTime.value - timestampQuestion.value >= delay
fun updateTime(time: Long) {
currentTime.value = time
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
index 7aa6dfa..4a89afb 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
@@ -17,6 +17,7 @@ import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import fr.uparis.diamantkennel.memorisationapplication.HOUR
import fr.uparis.diamantkennel.memorisationapplication.MINUTE
+import fr.uparis.diamantkennel.memorisationapplication.DELAY
import fr.uparis.diamantkennel.memorisationapplication.MemoApplication
import fr.uparis.diamantkennel.memorisationapplication.RappelWorker
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_BAD
@@ -34,7 +35,7 @@ import java.util.concurrent.TimeUnit
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
private val dao = (application as MemoApplication).database.memoDao()
- private val stats = application.dataStore
+ private val datastore = application.dataStore
private val statsKeyTotal = intPreferencesKey(STATS_TOTAL_TRIED)
private val statsKeyTotalDone = intPreferencesKey(STATS_TOTAL_DONE)
private val statsKeyTotalGood = intPreferencesKey(STATS_TOTAL_GOOD)
@@ -43,16 +44,19 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
private val notifH = intPreferencesKey(HOUR)
private val notifM = intPreferencesKey(MINUTE)
- val statTotal = stats.data.map { it[statsKeyTotal] ?: 0 }
- val statTotalDone = stats.data.map { it[statsKeyTotalDone] ?: 0 }
- val statTotalGood = stats.data.map { it[statsKeyTotalGood] ?: 0 }
- val statTotalBad = stats.data.map { it[statsKeyTotalBad] ?: 0 }
+ private val delay = intPreferencesKey(DELAY)
- var prefConfig = stats.data.map { TimeConfig(it[notifH] ?: 8, it[notifM] ?: 0) }
+ val statTotal = datastore.data.map { it[statsKeyTotal] ?: 0 }
+ val statTotalDone = datastore.data.map { it[statsKeyTotalDone] ?: 0 }
+ val statTotalGood = datastore.data.map { it[statsKeyTotalGood] ?: 0 }
+ val statTotalBad = datastore.data.map { it[statsKeyTotalBad] ?: 0 }
+
+ var prefConfigTime = datastore.data.map { TimeConfig(it[notifH] ?: 8, it[notifM] ?: 0) }
val deletionDB = mutableStateOf(false)
val deletionStat = mutableStateOf(false)
var notif = mutableStateOf(false)
+ val delayRequest = mutableStateOf(false)
val gavePermissionNow = mutableStateOf(false)
@@ -66,7 +70,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
fun cleanStats() {
deletionStat.value = false
viewModelScope.launch {
- stats.edit {
+ datastore.edit {
it[statsKeyTotal] = 0
it[statsKeyTotalDone] = 0
it[statsKeyTotalGood] = 0
@@ -86,6 +90,15 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
schedule(newConfig, context)
}
+ fun choiceDelay(value: Int) {
+ delayRequest.value = false
+ viewModelScope.launch {
+ datastore.edit {
+ it[delay] = value
+ }
+ }
+ }
+
fun winrate(good: Int, bad: Int): Int {
val total = good + bad
if (total == 0) {
@@ -107,7 +120,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
private fun save(config: TimeConfig) {
viewModelScope.launch {
- stats.edit {
+ datastore.edit {
it[notifH] = config.hour
it[notifM] = config.minute
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e1b0908..9688800 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -39,6 +39,7 @@
Voulez-vous supprimer la base de données ?
Oui
Non
+ Valider
Bravo
Le set de questions est terminé !
Statistiques
@@ -60,4 +61,9 @@
Gestion
Notifications
Confirmer
+ Parametre du jeu
+ Délai avant solution
+ Réinitialiser les paramètres du jeu
+ Choix du délai avant solution
+ Entrez un entier (en ms)
From 80310b28558892df949916d81f92fc0ffc485d70 Mon Sep 17 00:00:00 2001
From: ImAliant <111398111+ImAliant@users.noreply.github.com>
Date: Sat, 6 Jan 2024 20:15:47 +0100
Subject: [PATCH 5/5] cleaner code
---
.../memorisationapplication/HomeScreen.kt | 42 ++++----
.../memorisationapplication/MainActivity.kt | 20 +++-
.../ModifySetScreen.kt | 38 +++++---
.../memorisationapplication/PlayScreen.kt | 90 +++++++++++------
.../memorisationapplication/SettingsScreen.kt | 96 +++++++++++--------
.../ui/ModifySetViewModel.kt | 14 +++
.../ui/PlayViewModel.kt | 12 ++-
.../ui/SettingsViewModel.kt | 27 +++++-
app/src/main/res/values/strings.xml | 1 +
9 files changed, 233 insertions(+), 107 deletions(-)
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt
index 44d8990..b7db3c8 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt
@@ -68,7 +68,7 @@ fun HomeScreen(
val errorEntry by model.error
- if (errorEntry != null) {
+ ShowDialog(errorEntry != null) {
ErrorDialog(
when (errorEntry!!) {
ErrorsAjout.BAD_ENTRY -> context.getString(R.string.error_bad_entry)
@@ -76,25 +76,30 @@ fun HomeScreen(
}, model::cleanErrors
)
}
-
- if (creationRequest) {
- CreationDialog(
- dismiss = model::dismissCreation, model = model
- )
+ ShowDialog(creationRequest) { CreationDialog(model::dismissCreation, model) }
+ ShowDialog(importationRequest) { ImportDialog(model::dismissImportation, model) }
+ ShowDialog(deletionRequest) {
+ DeletionDialog(model::dismissDeleteOne, model::deleteSelected)
}
- if (importationRequest) {
- ImportDialog(
- dismiss = model::dismissImportation, model = model
- )
- }
+ Home(
+ padding,
+ navController,
+ model,
+ setOfQuestions,
+ currentSelection
+ )
+}
- if (deletionRequest) {
- DeletionDialog(
- model::dismissDeleteOne,
- model::deleteSelected
- )
- }
+@Composable
+private fun Home(
+ padding: PaddingValues,
+ navController: NavController,
+ model: HomeViewModel,
+ setOfQuestions: List = listOf(),
+ currentSelection: SetQuestions? = null,
+) {
+ val context = LocalContext.current
Column(
modifier = Modifier.padding(padding), horizontalAlignment = Alignment.CenterHorizontally
@@ -146,7 +151,6 @@ private fun ActionRow(context: Context, model: HomeViewModel, navController: Nav
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreationDialog(
dismiss: () -> Unit, model: HomeViewModel = viewModel()
@@ -172,7 +176,7 @@ fun CreationDialog(
})
}
-@OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class)
+@OptIn(DelicateCoroutinesApi::class)
@Composable
fun ImportDialog(
dismiss: () -> Unit, model: HomeViewModel
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt
index a4b928d..65c24ff 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt
@@ -1,9 +1,11 @@
package fr.uparis.diamantkennel.memorisationapplication
import android.content.Context
+import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.BottomNavigation
@@ -39,6 +41,7 @@ import fr.uparis.diamantkennel.memorisationapplication.ui.theme.MemorisationAppl
val Context.dataStore: DataStore by preferencesDataStore(name = STATS)
class MainActivity : ComponentActivity() {
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
@@ -54,18 +57,20 @@ class MainActivity : ComponentActivity() {
}
}
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Composable
fun MainScreenMainActivity() {
MainScreen()
}
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Preview(showBackground = true)
@Composable
fun MainScreenPreview() {
MainScreen()
}
-@OptIn(ExperimentalMaterial3Api::class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Composable
fun MainScreen() {
val navController = rememberNavController()
@@ -97,7 +102,7 @@ fun MainScreen() {
)
}
}
- composable(SETTINGS) { SettingsScreen(padding) }
+ composable(SETTINGS) { SettingsScreen() }
}
}
}
@@ -135,3 +140,14 @@ fun BottomBar(navController: NavHostController) =
)
})
}
+
+@Composable
+fun ShowDialog(
+ condition: Boolean,
+ dialog: @Composable () -> T
+) {
+ if (condition) {
+ dialog()
+ }
+}
+
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt
index 518089f..a364795 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt
@@ -36,7 +36,6 @@ import fr.uparis.diamantkennel.memorisationapplication.ui.ActionModifySet
import fr.uparis.diamantkennel.memorisationapplication.ui.ModifySetViewModel
import kotlin.text.Typography.ellipsis
-
@Composable
fun ModifySetScreen(
padding: PaddingValues,
@@ -47,20 +46,33 @@ fun ModifySetScreen(
model.setId.value = idSet
model.updateQuestionList(idSet)
- val context = LocalContext.current
val currentSelection by model.selection
val questions by model.questions.collectAsState(listOf())
- var action by model.action
+ val action by model.action
- if (action == ActionModifySet.AJOUT || action == ActionModifySet.MODIFICATION) {
- AjoutModifDialog(action, currentSelection, model::ajoutQuestion)
- { action = ActionModifySet.AUCUN }
+ ShowDialog(action == ActionModifySet.AJOUT || action == ActionModifySet.MODIFICATION) {
+ AjoutModifDialog(action, currentSelection, model::ajoutQuestion, model::dismissAction)
+ }
+ ShowDialog(action == ActionModifySet.SUPPRIMER) {
+ RemoveDialog(model::removeQuestion, model::dismissAction)
}
- if (action == ActionModifySet.SUPPRIMER) {
- RemoveDialog(model::removeQuestion)
- { action = ActionModifySet.AUCUN }
- }
+ Modify(
+ padding = padding,
+ model = model,
+ questions = questions,
+ currentSelection = currentSelection
+ )
+}
+
+@Composable
+fun Modify(
+ padding: PaddingValues,
+ model: ModifySetViewModel,
+ questions: List,
+ currentSelection: Question?
+) {
+ val context = LocalContext.current
Column(
modifier = Modifier.padding(padding),
@@ -71,13 +83,13 @@ fun ModifySetScreen(
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
Button(
enabled = currentSelection != null,
- onClick = { action = ActionModifySet.MODIFICATION }) {
+ onClick = model::modifAction) {
Text(text = context.getString(R.string.modify))
}
Spacer(modifier = Modifier.padding(2.dp))
- Button(onClick = { action = ActionModifySet.AJOUT }) {
+ Button(onClick = model::ajoutAction) {
Text(text = context.getString(R.string.add))
}
@@ -85,7 +97,7 @@ fun ModifySetScreen(
Button(
enabled = currentSelection != null,
- onClick = { action = ActionModifySet.SUPPRIMER }) {
+ onClick = model::supprAction) {
Text(text = context.getString(R.string.modify_button_delete))
}
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt
index d170872..67e3f1b 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/PlayScreen.kt
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
@@ -18,7 +17,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -27,10 +25,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
+import fr.uparis.diamantkennel.memorisationapplication.data.Question
import fr.uparis.diamantkennel.memorisationapplication.ui.AnswerType
import fr.uparis.diamantkennel.memorisationapplication.ui.PlayViewModel
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlayScreen(
padding: PaddingValues,
@@ -42,41 +40,54 @@ fun PlayScreen(
// First update the list of questions
model.updateQuestionList(idSet)
- val context = LocalContext.current
-
val question by model.currentQuestion
val reponse by model.proposedAnswer
val correction by model.evaluatedAnswer
- var giveup by model.showAnswer
+ val giveup by model.showAnswer
val gameEnded by model.end
- val delay by model.delay.collectAsState(initial = 3000)
+ val delay by model.delay.collectAsState(initial = 5000)
val cpt by model.compteurSb
- if (correction != null) {
- LaunchedEffect(cpt) {
- model.sbUpdate()
- snackbarHostState.showSnackbar(
- when (correction!!) {
- AnswerType.GOOD -> context.getString(R.string.good_answer)
- AnswerType.BAD -> context.getString(R.string.bad_answer)
- }, duration = SnackbarDuration.Short
- )
- model.resetAfterSb()
- }
- }
- if (gameEnded) {
- EndDialog { navController.navigate(HOME) }
- }
+ SnackbarAnswer(
+ model,
+ snackbarHostState,
+ cpt,
+ correction
+ )
- if (giveup && question != null) {
+ ShowDialog(gameEnded) { EndDialog { navController.navigate(HOME) } }
+ ShowDialog(giveup && question != null) {
SolutionDialog(question!!.reponse, model::newQuestion)
}
// Update timer if needed
- if (!model.isDelayElapsed(delay) && question != null) {
- model.updateTime(System.currentTimeMillis())
- }
+ model.updateTimer(delay)
+
+ Play(
+ padding,
+ navController,
+ idSet,
+ model,
+ question,
+ reponse,
+ correction,
+ delay
+ )
+}
+
+@Composable
+fun Play(
+ padding: PaddingValues,
+ navController: NavController,
+ idSet: Int,
+ model: PlayViewModel,
+ question: Question?,
+ reponse: String,
+ correction: AnswerType?,
+ delay: Int
+) {
+ val context = LocalContext.current
Column(
modifier = Modifier.padding(padding),
@@ -87,7 +98,7 @@ fun PlayScreen(
Text(context.getString(R.string.no_question), fontSize = 30.sp)
}
} else {
- Text(text = question!!.enonce, fontSize = 30.sp, textAlign = TextAlign.Center)
+ Text(text = question.enonce, fontSize = 30.sp, textAlign = TextAlign.Center)
Spacer(modifier = Modifier.padding(top = 20.dp))
@@ -112,7 +123,8 @@ fun PlayScreen(
Button(
enabled = model.isDelayElapsed(delay),
- onClick = { giveup = true }) {
+ onClick = model::giveUp
+ ) {
Text(text = context.getString(R.string.see_answer))
}
}
@@ -145,3 +157,25 @@ fun EndDialog(next: () -> Unit) =
confirmButton = {
Button(onClick = next) { Text(text = LocalContext.current.getString(R.string.ok)) }
})
+
+@Composable
+fun SnackbarAnswer(
+ model: PlayViewModel,
+ snackbarHostState: SnackbarHostState,
+ cpt: Int,
+ correction: AnswerType?
+) {
+ val context = LocalContext.current
+ if (correction != null) {
+ LaunchedEffect(cpt) {
+ model.sbUpdate()
+ snackbarHostState.showSnackbar(
+ when (correction) {
+ AnswerType.GOOD -> context.getString(R.string.good_answer)
+ AnswerType.BAD -> context.getString(R.string.bad_answer)
+ }, duration = SnackbarDuration.Short
+ )
+ model.resetAfterSb()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
index f5159ae..5962d02 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/SettingsScreen.kt
@@ -8,7 +8,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
@@ -52,14 +51,13 @@ import kotlinx.coroutines.runBlocking
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel()) {
+fun SettingsScreen(model: SettingsViewModel = viewModel()) {
val context = LocalContext.current
var deletionDBRequest by model.deletionDB
var cleanStatRequest by model.deletionStat
var choiceTimeNotifRequest by model.notif
var choiceDelayRequest by model.delayRequest
- var permissionNotif by model.gavePermissionNow
val prefConfigTime = runBlocking { model.prefConfigTime.first() }
@@ -71,6 +69,45 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
model.checkPermission(context)
+ ShowDialog(deletionDBRequest) { DeletionDBDialog(model::deleteDb, model::dismissDeletionDB) }
+ ShowDialog(cleanStatRequest) { CleanStatDialog(model::cleanStats, model::dismissDeletionStat) }
+ ShowDialog(choiceTimeNotifRequest) {
+ ChoiceTimeNotifDialog(
+ { model.choiceTimeNotif(stateTime, context) },
+ model::dismissNotif,
+ stateTime
+ )
+ }
+ ShowDialog(choiceDelayRequest) {
+ ChoiceDelayDialog(
+ { model.choiceDelay(it) },
+ model::dismissDelayRequest
+ )
+ }
+
+ Settings(
+ model,
+ { choiceTimeNotifRequest = true },
+ { deletionDBRequest = true },
+ { cleanStatRequest = true },
+ { choiceDelayRequest = true },
+ model::resetDelay
+ )
+}
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+@Composable
+fun Settings(
+ model: SettingsViewModel = viewModel(),
+ onTimeNotifButtonClick: () -> Unit,
+ deletionDBRequest: () -> Unit,
+ cleanStatRequest: () -> Unit,
+ onDelayButtonClick: () -> Unit,
+ onResetButtonClick: () -> Unit,
+) {
+ val context = LocalContext.current
+
+ var permissionNotif by model.gavePermissionNow
val permissionLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
) {
@@ -79,48 +116,17 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
}
}
- if (deletionDBRequest) {
- DeletionDBDialog(model::deleteDb) { deletionDBRequest = false }
- }
-
- if (cleanStatRequest) {
- CleanStatDialog(model::cleanStats) { cleanStatRequest = false }
- }
-
- if (choiceTimeNotifRequest) {
- ChoiceTimeNotifDialog(
- { model.choiceTimeNotif(stateTime, context) },
- { choiceTimeNotifRequest = false },
- stateTime
- )
- }
-
- if (choiceDelayRequest) {
- ChoiceDelayDialog(
- { model.choiceDelay(it) },
- { choiceDelayRequest = false },
- )
- }
-
Column(
- modifier = Modifier.padding(padding),
+ modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
- Stats(model)
-
+ Stats(model = model)
AddSpacedDivider()
-
- NotificationSettings(context, model, permissionNotif, permissionLauncher) {
- choiceTimeNotifRequest = true
- }
-
+ NotificationSettings(context, model, permissionNotif, permissionLauncher, onTimeNotifButtonClick)
AddSpacedDivider()
-
- GestionSettings(context, { deletionDBRequest = true }, { cleanStatRequest = true })
-
+ GestionSettings(context, deletionDBRequest, cleanStatRequest)
AddSpacedDivider()
-
- GameSettings(context) { choiceDelayRequest = true }
+ GameSettings(context, onDelayButtonClick, onResetButtonClick)
}
}
@@ -179,7 +185,7 @@ fun GestionSettings(context: Context, deletionDBRequest: () -> Unit, cleanStatRe
}
@Composable
-fun GameSettings(context: Context, onDelayButtonClick: () -> Unit) {
+fun GameSettings(context: Context, onDelayButtonClick: () -> Unit, onResetButtonClick: () -> Unit) {
Text(text = context.getString(R.string.game), fontSize = 30.sp)
Row(
modifier = Modifier.fillMaxWidth(),
@@ -192,6 +198,12 @@ fun GameSettings(context: Context, onDelayButtonClick: () -> Unit) {
Button(onClick = onDelayButtonClick) {
Text(text = context.getString(R.string.choice_delay_button))
}
+ Button(
+ onClick = onResetButtonClick,
+ colors = ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.red))
+ ) {
+ Text(text = context.getString(R.string.reset_button))
+ }
}
}
}
@@ -295,7 +307,9 @@ fun ChoiceDelayDialog(confirm: (Int) -> Unit, dismiss: () -> Unit) {
)
},
confirmButton = {
- Button(onClick = { if (value.isNotBlank()) { confirm(value.toInt()) } }) {
+ Button(onClick = {
+ if (value.isNotBlank()) { confirm(value.toInt()) } else dismiss()
+ }) {
Text(text = LocalContext.current.getString(R.string.confirm))
}
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt
index e8638e7..c9a7c32 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt
@@ -63,4 +63,18 @@ class ModifySetViewModel(application: Application) : AndroidViewModel(applicatio
dao.deleteQuestion(selection.value!!)
}
}
+
+ fun modifAction() {
+ action.value = ActionModifySet.MODIFICATION
+ }
+ fun ajoutAction() {
+ action.value = ActionModifySet.AJOUT
+ }
+ fun supprAction() {
+ action.value = ActionModifySet.SUPPRIMER
+ }
+
+ fun dismissAction() {
+ action.value = ActionModifySet.AUCUN
+ }
}
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt
index 0d677b8..5d2e71f 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/PlayViewModel.kt
@@ -29,7 +29,7 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
private val statsKeyTotalBad = intPreferencesKey(STATS_TOTAL_BAD)
private val delayKey= intPreferencesKey(DELAY)
- val delay = datastore.data.map { it[delayKey] ?: 3000 }
+ val delay = datastore.data.map { it[delayKey] ?: 5000 }
var currentQuestion = mutableStateOf(null)
private var index = mutableStateOf(0)
@@ -137,10 +137,20 @@ class PlayViewModel(application: Application) : AndroidViewModel(application) {
}
}
+ fun updateTimer(delay: Int) {
+ if (!isDelayElapsed(delay) && currentQuestion.value != null) {
+ updateTime(System.currentTimeMillis())
+ }
+ }
+
fun isDelayElapsed(delay: Int) = currentTime.value - timestampQuestion.value >= delay
fun updateTime(time: Long) {
currentTime.value = time
}
+ fun giveUp() {
+ showAnswer.value = true
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
index 4a89afb..aa63325 100644
--- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
+++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/SettingsViewModel.kt
@@ -53,10 +53,10 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
var prefConfigTime = datastore.data.map { TimeConfig(it[notifH] ?: 8, it[notifM] ?: 0) }
- val deletionDB = mutableStateOf(false)
- val deletionStat = mutableStateOf(false)
+ var deletionDB = mutableStateOf(false)
+ var deletionStat = mutableStateOf(false)
var notif = mutableStateOf(false)
- val delayRequest = mutableStateOf(false)
+ var delayRequest = mutableStateOf(false)
val gavePermissionNow = mutableStateOf(false)
@@ -99,6 +99,14 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
}
}
+ fun resetDelay() {
+ viewModelScope.launch {
+ datastore.edit {
+ it[delay] = 5000
+ }
+ }
+ }
+
fun winrate(good: Int, bad: Int): Int {
val total = good + bad
if (total == 0) {
@@ -147,4 +155,17 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
.setInitialDelay(delta, TimeUnit.MILLISECONDS)
.build()
}
+
+ fun dismissDeletionDB() {
+ deletionDB.value = false
+ }
+ fun dismissDeletionStat() {
+ deletionStat.value = false
+ }
+ fun dismissNotif() {
+ notif.value = false
+ }
+ fun dismissDelayRequest() {
+ delayRequest.value = false
+ }
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9688800..c9d8cc6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -63,6 +63,7 @@
Confirmer
Parametre du jeu
Délai avant solution
+ Réinitialiser par défaut
Réinitialiser les paramètres du jeu
Choix du délai avant solution
Entrez un entier (en ms)