feat: Edit filters + fix scroll

This commit is contained in:
Lucàs
2025-01-14 16:47:08 +01:00
parent 0befbc4ef0
commit 61ea180717
7 changed files with 124 additions and 115 deletions
+3 -1
View File
@@ -15,9 +15,11 @@
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:screenOrientation="portrait"
android:exported="true" android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.Queezer"> android:theme="@style/Theme.Queezer"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@@ -3,7 +3,8 @@ package fr.univpau.queezer.data
import android.util.Log import android.util.Log
data class Filter( data class Filter(
var dateOrderIsAscending: Boolean = true, // var dateOrderIsAscending: Boolean = true,
val orderByNbTitle : Boolean = false,
val mode : Map<GameMode, Boolean> = mapOf( val mode : Map<GameMode, Boolean> = mapOf(
GameMode.TITLE to true, GameMode.TITLE to true,
@@ -11,7 +12,6 @@ data class Filter(
GameMode.ALL to true GameMode.ALL to true
), ),
val nbTitleIsAscending : Boolean = true,
) )
fun filterGames(filter: Filter, games: List<Game>): List<Game> { fun filterGames(filter: Filter, games: List<Game>): List<Game> {
@@ -19,14 +19,14 @@ fun filterGames(filter: Filter, games: List<Game>): List<Game> {
return games return games
.filter { game -> .filter { game ->
// Filtrer uniquement par les modes de jeu activés
filter.mode.filter { it.value }.keys.contains(game.settings.gameMode) filter.mode.filter { it.value }.keys.contains(game.settings.gameMode)
} }
.sortedWith(compareBy<Game> { game -> .sortedWith(compareBy<Game> { game ->
// Tri par date // Tri par date
if (filter.dateOrderIsAscending) -game.date.time else game.date.time if (filter.orderByNbTitle) {
}.thenBy { game -> -game.settings.numberOfTitles!!
// Tri par nombre de titres } else {
if (filter.nbTitleIsAscending) game.settings.numberOfTitles ?: 0 else -(game.settings.numberOfTitles ?: 0) -game.date.time
}
}) })
} }
@@ -4,6 +4,8 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -13,14 +15,10 @@ import fr.univpau.queezer.data.Game
@Composable @Composable
fun GameCardItemList(games: List<Game>) { fun GameCardItemList(games: List<Game>) {
Column( LazyColumn(
modifier = Modifier modifier = Modifier.padding(horizontal = 16.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp),
) { ) {
for (game in games) GameCardItem(game) items(games) { game -> GameCardItem(game) }
} }
} }
@@ -4,6 +4,8 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -12,10 +14,10 @@ import fr.univpau.queezer.data.Track
@Composable @Composable
fun TrackCardItemList(tracks: List<Track>) { fun TrackCardItemList(tracks: List<Track>) {
Column( LazyColumn(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
for (track in tracks) TrackCardItem(track) items(tracks) { track -> TrackCardItem(track) }
} }
} }
@@ -46,6 +46,7 @@ import fr.univpau.queezer.data.Playlist
import fr.univpau.queezer.manager.GameManager import fr.univpau.queezer.manager.GameManager
import fr.univpau.queezer.manager.fetchPlaylist import fr.univpau.queezer.manager.fetchPlaylist
import fr.univpau.queezer.service.DatabaseService import fr.univpau.queezer.service.DatabaseService
import fr.univpau.queezer.view.components.TrackCardItemList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@Composable @Composable
@@ -258,17 +259,39 @@ fun LoadingScreen() {
@Composable @Composable
fun FinishScreen(gameManager: GameManager, context: Context, navController: NavHostController) { fun FinishScreen(gameManager: GameManager, context: Context, navController: NavHostController) {
Column( Scaffold(
modifier = Modifier.fillMaxSize(), bottomBar = {
verticalArrangement = Arrangement.Center, Row(
horizontalAlignment = Alignment.CenterHorizontally modifier = Modifier
) { .fillMaxWidth()
Text("Partie terminée !", fontSize = 24.sp) .padding(16.dp),
Text("Score : ${gameManager.score}", fontSize = 20.sp) horizontalArrangement = Arrangement.SpaceBetween
Button(onClick = { ) {
gameManager.save(context) Button(
gameManager.stop() modifier = Modifier.fillMaxWidth(),
navController.popBackStack() onClick = {
}) { Text(context.resources.getString(R.string.back)) } gameManager.save(context)
gameManager.stop()
navController.popBackStack()
}) { Text(context.resources.getString(R.string.back)) }
}
}
) { innerPadding ->
Column(
modifier = Modifier.padding(innerPadding),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
){
Text("Partie terminée !", fontSize = 24.sp)
Text("Score : ${gameManager.score}", fontSize = 20.sp)
TrackCardItemList(gameManager.playlist.tracks)
}
}
} }
} }
@@ -58,7 +58,10 @@ fun HomeScreen(navController: NavHostController) {
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp) .padding(vertical = 8.dp)
) { ) {
Text("Partie rapide") Text(
"Partie rapide",
fontSize = 18.sp
)
} }
Button( Button(
@@ -70,7 +73,7 @@ fun HomeScreen(navController: NavHostController) {
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp) .padding(vertical = 8.dp)
) { ) {
Text("Partie personnalisée") Text("Partie personnalisée", fontSize = 18.sp)
} }
Button( Button(
@@ -80,7 +83,7 @@ fun HomeScreen(navController: NavHostController) {
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp) .padding(vertical = 8.dp)
) { ) {
Text("Paramètres") Text("Paramètres", fontSize = 18.sp)
} }
Button( Button(
@@ -88,9 +91,8 @@ fun HomeScreen(navController: NavHostController) {
shape = RoundedCornerShape(8.dp), shape = RoundedCornerShape(8.dp),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp)
) { ) {
Text("Scores") Text("Scores", fontSize = 18.sp)
} }
} }
} }
@@ -23,6 +23,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -47,7 +48,7 @@ import fr.univpau.queezer.data.filterGames
import fr.univpau.queezer.view.components.GameCardItemList import fr.univpau.queezer.view.components.GameCardItemList
import fr.univpau.queezer.viewmodel.GameViewModel import fr.univpau.queezer.viewmodel.GameViewModel
import java.util.Locale import java.util.Locale
import kotlin.math.round import java.util.concurrent.Flow
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@Composable @Composable
@@ -86,8 +87,7 @@ fun ScoreScreen(navController: NavHostController, gameViewModel: GameViewModel)
}, },
) { innerPadding -> ) { innerPadding ->
Column( Column(
modifier = Modifier modifier = Modifier.padding(innerPadding),
.padding(innerPadding),
verticalArrangement = Arrangement.spacedBy(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp),
) { ) {
Row( Row(
@@ -108,89 +108,71 @@ fun ScoreScreen(navController: NavHostController, gameViewModel: GameViewModel)
HorizontalDivider() HorizontalDivider()
// Todo add filters Column(
modifier = Modifier.fillMaxWidth()
FlowRow( .padding(16.dp),
modifier = Modifier verticalArrangement = Arrangement.spacedBy(8.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) { ) {
FilterChip( Column(
selected = true, modifier = Modifier.fillMaxWidth(),
onClick = { verticalArrangement = Arrangement.spacedBy(4.dp),
// Inverser l'ordre de tri ) {
filter = filter.copy(dateOrderIsAscending = !filter.dateOrderIsAscending) Text("Mode de jeu", fontSize = 16.sp)
}, FlowRow(
label = { Text("Date") }, modifier = Modifier.fillMaxWidth(),
leadingIcon = { horizontalArrangement = Arrangement.spacedBy(8.dp),
if (filter.dateOrderIsAscending) { ) {
Icon( val gameModesLabels = context.resources.getStringArray(R.array.game_modes)
imageVector = Icons.Filled.KeyboardArrowUp, filter.mode.entries.forEachIndexed { index, entry ->
contentDescription = "Tri Ascendant", FilterChip(
modifier = Modifier.size(FilterChipDefaults.IconSize) selected = entry.value,
) onClick = {
} else { filter = filter.copy(mode = filter.mode.toMutableMap().apply {
Icon( this[entry.key] = !entry.value
imageVector = Icons.Filled.KeyboardArrowDown, })
contentDescription = "Tri Descendant", },
modifier = Modifier.size(FilterChipDefaults.IconSize)
leadingIcon = {
if (entry.value) {
Icon(
imageVector = Icons.Filled.Check,
contentDescription = "Filtre activé",
modifier = Modifier.size(FilterChipDefaults.IconSize)
)
}
},
label = { Text(
gameModesLabels[index],
maxLines = 1,
) },
) )
} }
}, }
)
val gameModesLabels = context.resources.getStringArray(R.array.game_modes)
filter.mode.entries.forEachIndexed { index, entry ->
FilterChip(
selected = entry.value,
onClick = {
filter = filter.copy(mode = filter.mode.toMutableMap().apply {
this[entry.key] = !entry.value
})
},
leadingIcon = {
if (entry.value) {
Icon(
imageVector = Icons.Filled.Check,
contentDescription = "Filtre activé",
modifier = Modifier.size(FilterChipDefaults.IconSize)
)
}
},
label = { Text(
gameModesLabels[index],
maxLines = 1,
) },
)
} }
// Filtrer par nombre de titres Column(
FilterChip( modifier = Modifier.fillMaxWidth(),
selected = true, verticalArrangement = Arrangement.spacedBy(4.dp),
onClick = { ) {
// Inverser l'ordre de tri Text("Filtrer par", fontSize = 16.sp)
filter = filter.copy(nbTitleIsAscending = !filter.nbTitleIsAscending) Row(
}, modifier = Modifier.fillMaxWidth(),
label = { Text("Nombre de titres") }, horizontalArrangement = Arrangement.spacedBy(8.dp),
leadingIcon = { verticalAlignment = Alignment.CenterVertically
if (filter.nbTitleIsAscending) { ) {
Icon( Text("Date")
imageVector = Icons.Filled.KeyboardArrowUp,
contentDescription = "Tri Ascendant", Switch(
modifier = Modifier.size(FilterChipDefaults.IconSize) checked = filter.orderByNbTitle,
) onCheckedChange = {
} else { filter = filter.copy(orderByNbTitle = it)
Icon( }
imageVector = Icons.Filled.KeyboardArrowDown, )
contentDescription = "Tri Descendant",
modifier = Modifier.size(FilterChipDefaults.IconSize) Text("Nombre de titres")
) }
} }
},
)
} }
if (filteredGames.isEmpty()) { if (filteredGames.isEmpty()) {