mirror of
https://github.com/LucasVbr/Queezer.git
synced 2026-05-13 17:11:55 +00:00
feat: Edit filters + fix scroll
This commit is contained in:
@@ -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()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user