cleaner code

This commit is contained in:
ImAliant 2024-01-06 20:15:47 +01:00
parent 920bd24742
commit 80310b2855
9 changed files with 233 additions and 107 deletions

View file

@ -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
)
}
ShowDialog(creationRequest) { CreationDialog(model::dismissCreation, model) }
ShowDialog(importationRequest) { ImportDialog(model::dismissImportation, model) }
ShowDialog(deletionRequest) {
DeletionDialog(model::dismissDeleteOne, model::deleteSelected)
}
if (creationRequest) {
CreationDialog(
dismiss = model::dismissCreation, model = model
Home(
padding,
navController,
model,
setOfQuestions,
currentSelection
)
}
if (importationRequest) {
ImportDialog(
dismiss = model::dismissImportation, model = model
)
}
if (deletionRequest) {
DeletionDialog(
model::dismissDeleteOne,
model::deleteSelected
)
}
@Composable
private fun Home(
padding: PaddingValues,
navController: NavController,
model: HomeViewModel,
setOfQuestions: List<SetOfQuestions> = 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

View file

@ -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<Preferences> 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 <T: Any> ShowDialog(
condition: Boolean,
dialog: @Composable () -> T
) {
if (condition) {
dialog()
}
}

View file

@ -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,21 +46,34 @@ 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<Question>,
currentSelection: Question?
) {
val context = LocalContext.current
Column(
modifier = Modifier.padding(padding),
horizontalAlignment = Alignment.CenterHorizontally
@ -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))
}
}

View file

@ -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,42 +40,55 @@ 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
SnackbarAnswer(
model,
snackbarHostState,
cpt,
correction
)
model.resetAfterSb()
}
}
if (gameEnded) {
EndDialog { navController.navigate(HOME) }
}
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),
horizontalAlignment = Alignment.CenterHorizontally
@ -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()
}
}
}

View file

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

View file

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

View file

@ -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<Question?>(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
}
}

View file

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

View file

@ -63,6 +63,7 @@
<string name="confirm">Confirmer</string>
<string name="game">Parametre du jeu</string>
<string name="choice_delay_button">Délai avant solution</string>
<string name="reset_button">Réinitialiser par défaut</string>
<string name="reset_game_settings_button">Réinitialiser les paramètres du jeu</string>
<string name="choice_delay">Choix du délai avant solution</string>
<string name="enter_integer">Entrez un entier (en ms)</string>