This commit is contained in:
Mylloon 2023-12-19 19:28:22 +01:00
parent 337f5c6342
commit fd95c308d0
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
8 changed files with 105 additions and 169 deletions

View file

@ -79,15 +79,13 @@ fun HomeScreen(padding: PaddingValues, model: HomeViewModel = viewModel()) {
if (creationRequest) { if (creationRequest) {
CreationDialog( CreationDialog(
dismiss = model::dismissCreation, dismiss = model::dismissCreation, model = model
model = model
) )
} }
if (importationRequest) { if (importationRequest) {
ImportDialog( ImportDialog(
dismiss = model::dismissImportation, dismiss = model::dismissImportation, model = model
model = model
) )
} }
@ -104,15 +102,13 @@ fun HomeScreen(padding: PaddingValues, model: HomeViewModel = viewModel()) {
} }
Column( Column(
modifier = Modifier.padding(padding), modifier = Modifier.padding(padding), horizontalAlignment = Alignment.CenterHorizontally
horizontalAlignment = Alignment.CenterHorizontally
) { ) {
ShowList(setOfQuestions, currentSelection, model::updateSelection) ShowList(setOfQuestions, currentSelection, model::updateSelection)
ActionRow(context, model) ActionRow(context, model)
Button( Button(onClick = { Toast.makeText(context, "Start", Toast.LENGTH_SHORT).show() }) {
onClick = { Toast.makeText(context, "Start", Toast.LENGTH_SHORT).show() }) {
Text(text = context.getString(R.string.main_button_start), fontSize = 30.sp) Text(text = context.getString(R.string.main_button_start), fontSize = 30.sp)
} }
@ -124,12 +120,10 @@ fun HomeScreen(padding: PaddingValues, model: HomeViewModel = viewModel()) {
@Composable @Composable
private fun DeleteRow( private fun DeleteRow(
context: Context, context: Context, model: HomeViewModel
model: HomeViewModel
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center
horizontalArrangement = Arrangement.Center
) { ) {
Button( Button(
onClick = { onClick = {
@ -142,8 +136,7 @@ private fun DeleteRow(
Spacer(modifier = Modifier.padding(2.dp)) Spacer(modifier = Modifier.padding(2.dp))
Button( Button(enabled = false, /*TODO: Activer uniquement quand on a qqch de sélectionner */
enabled = false, /*TODO: Activer uniquement quand on a qqch de sélectionner */
onClick = { onClick = {
(model::doAction)(ActionHome.DELETION_SELECT) (model::doAction)(ActionHome.DELETION_SELECT)
}) { }) {
@ -154,8 +147,7 @@ private fun DeleteRow(
@Composable @Composable
private fun ActionRow( private fun ActionRow(
context: Context, context: Context, model: HomeViewModel
model: HomeViewModel
) { ) {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
Button(onClick = { Button(onClick = {
@ -183,41 +175,25 @@ private fun ActionRow(
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CreationDialog( fun CreationDialog(
dismiss: () -> Unit, dismiss: () -> Unit, model: HomeViewModel = viewModel()
model: HomeViewModel = viewModel()
) { ) {
val sujet by model.sujet val sujet by model.sujet
AlertDialog( AlertDialog(onDismissRequest = dismiss, title = { Text(text = "Créer un sujet") }, text = {
onDismissRequest = dismiss, OutlinedTextField(
title = { Text(text = "Créer un sujet") }, sujet, label = { Text("Nouveau sujet") }, onValueChange = model::onSujetChange
text = { )
OutlinedTextField( }, confirmButton = {
sujet, Button(onClick = model::addSet, content = { Text("Ajouter") })
label = { Text("Nouveau sujet") }, }, dismissButton = {
onValueChange = model::onSujetChange Button(onClick = dismiss, content = { Text("Annuler") })
) })
},
confirmButton = {
Button(
onClick = model::addSet,
content = { Text("Ajouter") }
)
},
dismissButton = {
Button(
onClick = dismiss,
content = { Text("Annuler") }
)
}
)
} }
@OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class) @OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class)
@Composable @Composable
fun ImportDialog( fun ImportDialog(
dismiss: () -> Unit, dismiss: () -> Unit, model: HomeViewModel
model: HomeViewModel
) { ) {
val (selectedOption, onOptionSelected) = remember { mutableStateOf(ActionImport.FILE) } val (selectedOption, onOptionSelected) = remember { mutableStateOf(ActionImport.FILE) }
@ -233,8 +209,7 @@ fun ImportDialog(
} }
} }
AlertDialog( AlertDialog(onDismissRequest = dismiss,
onDismissRequest = dismiss,
title = { Text(text = "Importer un jeu de question") }, title = { Text(text = "Importer un jeu de question") },
text = { text = {
Column { Column {
@ -251,8 +226,7 @@ fun ImportDialog(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
RadioButton( RadioButton(
selected = (text == selectedOption), selected = (text == selectedOption), onClick = null
onClick = null
) )
Text( Text(
text = text.toString(), text = text.toString(),
@ -261,17 +235,14 @@ fun ImportDialog(
) )
if (text == ActionImport.FILE) { if (text == ActionImport.FILE) {
Button( Button(enabled = selectedOption == ActionImport.FILE,
enabled = selectedOption == ActionImport.FILE,
modifier = Modifier.padding(start = 16.dp), modifier = Modifier.padding(start = 16.dp),
onClick = { onClick = {
filePickerLauncher.launch( filePickerLauncher.launch(
Intent(Intent.ACTION_OPEN_DOCUMENT) Intent(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("*/*") .setType("*/*")
) )
} }) {
) {
Text( Text(
text = "Explorateur", text = "Explorateur",
style = MaterialTheme.typography.labelSmall style = MaterialTheme.typography.labelSmall
@ -282,52 +253,38 @@ fun ImportDialog(
} }
} }
OutlinedTextField( OutlinedTextField(enabled = selectedOption == ActionImport.INTERNET,
enabled = selectedOption == ActionImport.INTERNET,
value = lien, value = lien,
onValueChange = { newTextValue -> lien = newTextValue }, onValueChange = { newTextValue -> lien = newTextValue },
label = { Text(text = "Lien") } label = { Text(text = "Lien") })
)
} }
}, },
confirmButton = { confirmButton = {
Button( Button(onClick = { GlobalScope.launch { model.import(ctx, lien) } },
onClick = { GlobalScope.launch { model.import(ctx, lien) } }, content = { Text("Importer") })
content = { Text("Importer") }
)
}, },
dismissButton = { dismissButton = {
Button( Button(onClick = dismiss, content = { Text("Annuler") })
onClick = dismiss, })
content = { Text("Annuler") }
)
}
)
} }
@Composable @Composable
fun ErrorDialog(errMsg: String, dismiss: () -> Unit) = fun ErrorDialog(errMsg: String, dismiss: () -> Unit) = AlertDialog(onDismissRequest = dismiss,
AlertDialog(onDismissRequest = dismiss, title = { Text(text = "Erreur") },
title = { Text(text = "Erreur") }, text = { Text(text = errMsg) },
text = { Text(text = errMsg) }, confirmButton = { Button(onClick = dismiss) { Text(text = "Ok") } })
confirmButton = { Button(onClick = dismiss) { Text(text = "Ok") } }
)
@Composable @Composable
fun DeletionDialog(dismiss: () -> Unit) = fun DeletionDialog(dismiss: () -> Unit) = AlertDialog(onDismissRequest = dismiss,
AlertDialog(onDismissRequest = dismiss, title = { Text(text = "Supprimer un jeu de question") },
title = { Text(text = "Supprimer un jeu de question") }, text = { Text(text = "Voulez-vous supprimer ce jeu de question ?") },
text = { Text(text = "Voulez-vous supprimer ce jeu de question ?") }, confirmButton = { Button(onClick = dismiss) { Text(text = "Ok") } })
confirmButton = { Button(onClick = dismiss) { Text(text = "Ok") } }
)
@Composable @Composable
fun DeletionDBDialog(dismiss: () -> Unit) = fun DeletionDBDialog(dismiss: () -> Unit) = AlertDialog(onDismissRequest = dismiss,
AlertDialog(onDismissRequest = dismiss, title = { Text(text = "Supprimer la base de données") },
title = { Text(text = "Supprimer la base de données") }, text = { Text(text = "Voulez-vous supprimer la base de données ?") },
text = { Text(text = "Voulez-vous supprimer la base de données ?") }, confirmButton = { Button(onClick = dismiss) { Text(text = "Ok") } })
confirmButton = { Button(onClick = dismiss) { Text(text = "Ok") } }
)
@Composable @Composable
fun ShowList( fun ShowList(
@ -336,8 +293,7 @@ fun ShowList(
updateSelection: (SetQuestions) -> Unit updateSelection: (SetQuestions) -> Unit
) { ) {
LazyColumn( LazyColumn(
Modifier Modifier.fillMaxHeight(0.6f)
.fillMaxHeight(0.6f)
) { ) {
itemsIndexed(sets) { index, item -> itemsIndexed(sets) { index, item ->
ListItem(index, item, currentSelection, updateSelection) ListItem(index, item, currentSelection, updateSelection)
@ -365,8 +321,7 @@ fun ListItem(
colors = CardDefaults.cardColors(containerColor) colors = CardDefaults.cardColors(containerColor)
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly
horizontalArrangement = Arrangement.SpaceEvenly
) { ) {
Text(set.toString(), modifier = Modifier.padding(2.dp)) Text(set.toString(), modifier = Modifier.padding(2.dp))
} }

View file

@ -35,8 +35,7 @@ class MainActivity : ComponentActivity() {
MemorisationApplicationTheme { MemorisationApplicationTheme {
// A surface container using the 'background' color from the theme // A surface container using the 'background' color from the theme
Surface( Surface(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background
color = MaterialTheme.colorScheme.background
) { ) {
MainScreenMainActivity() MainScreenMainActivity()
} }
@ -61,8 +60,7 @@ fun MainScreenActivityPreview() {
fun MainScreen() { fun MainScreen() {
val navController = rememberNavController() val navController = rememberNavController()
Scaffold(topBar = { TopBar() }, Scaffold(topBar = { TopBar() }, bottomBar = { BottomBar(navController) }) { padding ->
bottomBar = { BottomBar(navController) }) { padding ->
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = HOME, startDestination = HOME,
@ -77,13 +75,12 @@ fun MainScreen() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun TopBar() = fun TopBar() = CenterAlignedTopAppBar(title = {
CenterAlignedTopAppBar(title = { Text(
Text( text = LocalContext.current.getString(R.string.app_name),
text = LocalContext.current.getString(R.string.app_name), style = MaterialTheme.typography.displayMedium
style = MaterialTheme.typography.displayMedium )
) })
})
@Composable @Composable
fun BottomBar(navController: NavHostController) = fun BottomBar(navController: NavHostController) =
@ -91,15 +88,12 @@ fun BottomBar(navController: NavHostController) =
val navBackStackEntry by navController.currentBackStackEntryAsState() val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route val currentRoute = navBackStackEntry?.destination?.route
BottomNavigationItem( BottomNavigationItem(selected = currentRoute == HOME, onClick = {
selected = currentRoute == HOME, navController.navigate(HOME) { launchSingleTop = true }
onClick = { }, icon = {
navController.navigate(HOME) { launchSingleTop = true } Icon(
}, imageVector = Icons.Default.Home,
icon = { contentDescription = LocalContext.current.getString(R.string.home_button)
Icon( )
imageVector = Icons.Default.Home, })
contentDescription = LocalContext.current.getString(R.string.home_button)
)
})
} }

View file

@ -5,14 +5,12 @@ import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@Entity( @Entity(
foreignKeys = [ foreignKeys = [ForeignKey(
ForeignKey( entity = SetQuestions::class,
entity = SetQuestions::class, parentColumns = ["idSet"],
parentColumns = ["idSet"], childColumns = ["setId"],
childColumns = ["setId"], onDelete = ForeignKey.CASCADE
onDelete = ForeignKey.CASCADE )]
)
]
) )
data class Question( data class Question(
@PrimaryKey(autoGenerate = true) val idQuestion: Int = 0, @PrimaryKey(autoGenerate = true) val idQuestion: Int = 0,

View file

@ -18,9 +18,8 @@ abstract class QuestionsDB : RoomDatabase() {
fun getDataBase(c: Context): QuestionsDB { fun getDataBase(c: Context): QuestionsDB {
if (instance != null) return instance!! if (instance != null) return instance!!
val db = val db = Room.databaseBuilder(c.applicationContext, QuestionsDB::class.java, "memo")
Room.databaseBuilder(c.applicationContext, QuestionsDB::class.java, "memo") .fallbackToDestructiveMigration().build()
.fallbackToDestructiveMigration().build()
instance = db instance = db
return instance!! return instance!!
} }

View file

@ -4,12 +4,9 @@ import androidx.room.Embedded
import androidx.room.Relation import androidx.room.Relation
data class SetOfQuestions( data class SetOfQuestions(
@Embedded val set: SetQuestions, @Embedded val set: SetQuestions, @Relation(
@Relation( parentColumn = "idSet", entityColumn = "setId"
parentColumn = "idSet", ) val questions: List<Question>
entityColumn = "setId"
)
val questions: List<Question>
) { ) {
override fun toString() = set.name override fun toString() = set.name
} }

View file

@ -7,19 +7,16 @@ import androidx.room.Index
@Entity( @Entity(
indices = [Index(value = ["idQuestion"])], indices = [Index(value = ["idQuestion"])],
primaryKeys = ["idSet", "idQuestion"], primaryKeys = ["idSet", "idQuestion"],
foreignKeys = [ foreignKeys = [ForeignKey(
ForeignKey( entity = SetQuestions::class,
entity = SetQuestions::class, parentColumns = ["idSet"],
parentColumns = ["idSet"], childColumns = ["idSet"],
childColumns = ["idSet"], onDelete = ForeignKey.CASCADE
onDelete = ForeignKey.CASCADE ), ForeignKey(
), entity = Question::class,
ForeignKey( parentColumns = ["idQuestion"],
entity = Question::class, childColumns = ["idQuestion"],
parentColumns = ["idQuestion"], onDelete = ForeignKey.CASCADE
childColumns = ["idQuestion"], )]
onDelete = ForeignKey.CASCADE
)
]
) )
data class Sets(val idSet: Int, val idQuestion: Int) data class Sets(val idSet: Int, val idQuestion: Int)

View file

@ -1,5 +1,3 @@
package fr.uparis.diamantkennel.memorisationapplication.ui package fr.uparis.diamantkennel.memorisationapplication.ui
enum class ErrorsAjout { BAD_ENTRY, DUPLICATE } enum class ErrorsAjout { BAD_ENTRY, DUPLICATE }
class Duplicate : Exception(ErrorsAjout.DUPLICATE.toString())

View file

@ -138,38 +138,36 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
} }
suspend fun import(ctx: Context, path: String) { suspend fun import(ctx: Context, path: String) {
val data = val data = flow {
flow { if (path.startsWith("content://")) {
if (path.startsWith("content://")) { // Local file
// Local file val reader = BufferedReader(
val reader = InputStreamReader(
BufferedReader( ctx.contentResolver.openInputStream(
InputStreamReader( Uri.parse(
ctx.contentResolver.openInputStream( path
Uri.parse(
path
)
)
) )
) )
)
)
emit(reader.use { it.readText() }) emit(reader.use { it.readText() })
} else { } else {
// File from internet // File from internet
val url = URL(path) val url = URL(path)
val connection = url.openConnection() as HttpURLConnection val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET" connection.requestMethod = "GET"
val inputStream = connection.inputStream val inputStream = connection.inputStream
val reader = BufferedReader(InputStreamReader(inputStream)) val reader = BufferedReader(InputStreamReader(inputStream))
val content = reader.use { it.readText() } val content = reader.use { it.readText() }
connection.disconnect() connection.disconnect()
emit(content) emit(content)
} }
}.flowOn(Dispatchers.IO) }.flowOn(Dispatchers.IO)
dismissImportation() dismissImportation()