la notification fonctionne correctement
This commit is contained in:
parent
7be0eeea21
commit
77ad522ce2
6 changed files with 110 additions and 33 deletions
|
@ -51,14 +51,14 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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.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(platform("androidx.compose:compose-bom:2023.03.00"))
|
||||||
implementation("androidx.compose.ui:ui")
|
implementation("androidx.compose.ui:ui")
|
||||||
implementation("androidx.compose.ui:ui-graphics")
|
implementation("androidx.compose.ui:ui-graphics")
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
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.core:core-ktx:1.12.0")
|
||||||
implementation("androidx.work:work-runtime-ktx:2.8.1")
|
implementation("androidx.work:work-runtime-ktx:2.8.1")
|
||||||
|
|
||||||
|
|
|
@ -23,3 +23,7 @@ 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 MINUTE = "minute"
|
||||||
|
|
|
@ -4,13 +4,8 @@ import android.app.Application
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.work.PeriodicWorkRequest
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.data.QuestionsDB
|
import fr.uparis.diamantkennel.memorisationapplication.data.QuestionsDB
|
||||||
import java.util.Calendar
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
const val CHANNEL_ID = "MY_CHANNEL_ID"
|
const val CHANNEL_ID = "MY_CHANNEL_ID"
|
||||||
|
|
||||||
|
@ -20,10 +15,6 @@ class MemoApplication : Application() {
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
createChannel(this)
|
createChannel(this)
|
||||||
|
|
||||||
if (this.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
schedule()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createChannel(c: Context) {
|
private fun createChannel(c: Context) {
|
||||||
|
@ -39,25 +30,4 @@ class MemoApplication : Application() {
|
||||||
notificationManager.createNotificationChannel(channel)
|
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
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
|
||||||
|
@ -15,10 +16,17 @@ 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.Divider
|
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.Text
|
||||||
|
import androidx.compose.material3.TimeInput
|
||||||
|
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
|
||||||
|
@ -29,8 +37,11 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.ui.SettingsViewModel
|
import fr.uparis.diamantkennel.memorisationapplication.ui.SettingsViewModel
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel()) {
|
fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel()) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
@ -38,6 +49,16 @@ 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 permissionNotif by model.gavePermissionNow
|
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)
|
model.checkPermission(context)
|
||||||
|
|
||||||
val permissionLauncher = rememberLauncherForActivityResult(
|
val permissionLauncher = rememberLauncherForActivityResult(
|
||||||
|
@ -94,6 +115,25 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
|
||||||
) {
|
) {
|
||||||
Text(text = context.getString(R.string.permission_button))
|
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!")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package fr.uparis.diamantkennel.memorisationapplication
|
||||||
|
|
||||||
|
data class TimeConfig(
|
||||||
|
val enabled: Boolean = false,
|
||||||
|
val hour: Int = 8,
|
||||||
|
val minute: Int = 0
|
||||||
|
)
|
|
@ -4,22 +4,33 @@ import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
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.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.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.MemoApplication
|
||||||
|
import fr.uparis.diamantkennel.memorisationapplication.RappelWorker
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_BAD
|
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_BAD
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_DONE
|
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_DONE
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_GOOD
|
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_GOOD
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_TRIED
|
import fr.uparis.diamantkennel.memorisationapplication.STATS_TOTAL_TRIED
|
||||||
|
import fr.uparis.diamantkennel.memorisationapplication.TimeConfig
|
||||||
import fr.uparis.diamantkennel.memorisationapplication.dataStore
|
import fr.uparis.diamantkennel.memorisationapplication.dataStore
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
|
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
private val dao = (application as MemoApplication).database.memoDao()
|
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 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 KEY_H = intPreferencesKey(HOUR)
|
||||||
|
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 }
|
||||||
val statTotalGood = stats.data.map { it[statsKeyTotalGood] ?: 0 }
|
val statTotalGood = stats.data.map { it[statsKeyTotalGood] ?: 0 }
|
||||||
|
@ -77,4 +92,45 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
|
||||||
gavePermissionNow.value =
|
gavePermissionNow.value =
|
||||||
context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue