la notification fonctionne correctement

This commit is contained in:
ImAliant 2024-01-05 13:39:22 +01:00
parent 7be0eeea21
commit 77ad522ce2
6 changed files with 110 additions and 33 deletions

View file

@ -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")

View file

@ -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"

View file

@ -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()
}
} }

View file

@ -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!")
}
}
} }
} }

View file

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

View file

@ -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
}
} }