fmt
This commit is contained in:
parent
337f5c6342
commit
fd95c308d0
8 changed files with 105 additions and 169 deletions
|
@ -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,
|
|
||||||
title = { Text(text = "Créer un sujet") },
|
|
||||||
text = {
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
sujet,
|
sujet, label = { Text("Nouveau sujet") }, onValueChange = model::onSujetChange
|
||||||
label = { Text("Nouveau sujet") },
|
|
||||||
onValueChange = model::onSujetChange
|
|
||||||
)
|
|
||||||
},
|
|
||||||
confirmButton = {
|
|
||||||
Button(
|
|
||||||
onClick = model::addSet,
|
|
||||||
content = { Text("Ajouter") }
|
|
||||||
)
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,12 +88,9 @@ 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,
|
|
||||||
onClick = {
|
|
||||||
navController.navigate(HOME) { launchSingleTop = true }
|
navController.navigate(HOME) { launchSingleTop = true }
|
||||||
},
|
}, icon = {
|
||||||
icon = {
|
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Home,
|
imageVector = Icons.Default.Home,
|
||||||
contentDescription = LocalContext.current.getString(R.string.home_button)
|
contentDescription = LocalContext.current.getString(R.string.home_button)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -18,8 +18,7 @@ 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!!
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
ForeignKey(
|
|
||||||
entity = Question::class,
|
entity = Question::class,
|
||||||
parentColumns = ["idQuestion"],
|
parentColumns = ["idQuestion"],
|
||||||
childColumns = ["idQuestion"],
|
childColumns = ["idQuestion"],
|
||||||
onDelete = ForeignKey.CASCADE
|
onDelete = ForeignKey.CASCADE
|
||||||
)
|
)]
|
||||||
]
|
|
||||||
)
|
)
|
||||||
data class Sets(val idSet: Int, val idQuestion: Int)
|
data class Sets(val idSet: Int, val idQuestion: Int)
|
||||||
|
|
|
@ -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())
|
|
||||||
|
|
|
@ -138,12 +138,10 @@ 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 =
|
val reader = BufferedReader(
|
||||||
BufferedReader(
|
|
||||||
InputStreamReader(
|
InputStreamReader(
|
||||||
ctx.contentResolver.openInputStream(
|
ctx.contentResolver.openInputStream(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
|
|
Reference in a new issue