feat : design et responsive pagelobby et pagecreationlobby
continuous-integration/drone/push Build is passing Details

androidCompose
Maxence GUITARD 1 year ago
parent c0ece5a6f1
commit 820ec2b59b

@ -144,8 +144,7 @@ fun ConnexionPlayerContent(navController: NavController) {
if (isAuthenticated != -1) { if (isAuthenticated != -1) {
MainActivity.idPlayerConnected = isAuthenticated MainActivity.idPlayerConnected = isAuthenticated
Toast.makeText(context, "Connexion réussie, bienvenue $nickname !", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Connexion réussie, bienvenue $nickname !", Toast.LENGTH_SHORT).show()
val intent = Intent(context, MainActivity::class.java) navController.navigate("home")
context.startActivity(intent)
} else { } else {
Toast.makeText(context, "Connexion échouée. Veuillez réessayer.", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Connexion échouée. Veuillez réessayer.", Toast.LENGTH_SHORT).show()
} }

@ -1,6 +1,8 @@
package com.example.mathseduc package com.example.mathseduc
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -8,14 +10,17 @@ import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@ -35,15 +40,23 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import com.example.mathseduc.controllers.ControllerChapter import com.example.mathseduc.controllers.ControllerChapter
import com.example.mathseduc.controllers.ControllerLobby import com.example.mathseduc.controllers.ControllerLobby
import com.example.mathseduc.controllers.ControllerPlayer import com.example.mathseduc.controllers.ControllerPlayer
@ -70,7 +83,8 @@ class ServerDetailsActivity : ComponentActivity() {
onBackPressedDispatcher.addCallback(this, onBackPressedCallback) onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
setContent { setContent {
ServerDetailPage() val navController = rememberNavController()
ServerDetailPage(navController = navController)
} }
} }
@ -95,7 +109,7 @@ class ServerDetailsActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun ServerDetailPage() { fun ServerDetailPage(navController: NavController) {
val context = LocalContext.current val context = LocalContext.current
val serverName = intent.getStringExtra("serverName") val serverName = intent.getStringExtra("serverName")
@ -110,6 +124,16 @@ class ServerDetailsActivity : ComponentActivity() {
var refreshState by rememberSaveable { mutableStateOf(true) } var refreshState by rememberSaveable { mutableStateOf(true) }
var showDialog by rememberSaveable { mutableStateOf(false) } var showDialog by rememberSaveable { mutableStateOf(false) }
val isPortrait = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT
val activity = LocalView.current.context as Activity
val windowInsetsController = remember {
WindowCompat.getInsetsController(activity.window, activity.window.decorView)
}
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
DisposableEffect(refreshState) { DisposableEffect(refreshState) {
val handler = Handler(Looper.getMainLooper()) val handler = Handler(Looper.getMainLooper())
val refreshRunnable = object : Runnable { val refreshRunnable = object : Runnable {
@ -170,7 +194,7 @@ class ServerDetailsActivity : ComponentActivity() {
val modifier = Modifier val modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp) .padding(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 8.dp)
Column( Column(
modifier = modifier, modifier = modifier,
@ -184,7 +208,7 @@ class ServerDetailsActivity : ComponentActivity() {
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
Spacer(modifier = Modifier.height(25.dp)) Spacer(modifier = Modifier.height(if(isPortrait)25.dp else 10.dp))
Text( Text(
text = "Lobby Settings", text = "Lobby Settings",
@ -194,27 +218,29 @@ class ServerDetailsActivity : ComponentActivity() {
) )
Text( Text(
text = "Chapter : ${ControllerChapter.getChapterNameById(chapterId).toString()}", text = "Chapter : ${ControllerChapter.getChapterNameById(chapterId).toString()}",
fontSize = 20.sp, fontSize = 19.sp,
color = Color.White color = Color.White
) )
Row {
Text( Text(
text = "Players : ${ControllerLobby.getNbPlayerInLobby(lobbyId)}/${nbPlayers}", text = "Players : ${ControllerLobby.getNbPlayerInLobby(lobbyId)}/${nbPlayers}",
fontSize = 20.sp, fontSize = 19.sp,
color = (if(ControllerLobby.getNbPlayerInLobby(lobbyId)==nbPlayers) Color.Red else Color.White) color = (if(ControllerLobby.getNbPlayerInLobby(lobbyId)==nbPlayers) Color.Red else Color.White)
) )
Spacer(modifier = Modifier.width(40.dp))
Text( Text(
text = "Difficulty : $lobbyDifficulty", text = "Difficulty : $lobbyDifficulty",
fontSize = 20.sp, fontSize = 19.sp,
color = Colors.White, color = Colors.White,
) )
}
Spacer(modifier = Modifier.height(if(isPortrait)30.dp else 10.dp))
Spacer(modifier = Modifier.height(30.dp))
Text( Text(
text = "Player Name", text = "Player Name",
fontSize = 20.sp, fontSize = 19.sp,
modifier = Modifier.background(Color.Black),
color = Colors.White, color = Colors.White,
) )
Divider( Divider(
@ -226,7 +252,7 @@ class ServerDetailsActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.weight(0.75f) .weight(0.75f)
.padding(top = 2.dp), .padding(top = 1.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
items(playerListInfos) { player -> items(playerListInfos) { player ->
@ -234,8 +260,9 @@ class ServerDetailsActivity : ComponentActivity() {
text = player.nickname, text = player.nickname,
fontSize = 18.sp, fontSize = 18.sp,
color = Colors.White, color = Colors.White,
modifier = Modifier.weight(1f) modifier = Modifier
.padding(top = 5.dp) .weight(1f)
.padding(top = if (isPortrait) 5.dp else 1.dp)
) )
} }
} }
@ -261,7 +288,7 @@ class ServerDetailsActivity : ComponentActivity() {
} }
} }
if (showDialog) { if (showDialog) {
LeaveLobbyDialog(serverName, onConfirmLeave = {},onCancelLeave = { showDialog = false }) LeaveLobbyDialog(serverName, onConfirmLeave = {navController.navigate("multiplayer")},onCancelLeave = { showDialog = false })
} }
} }
} }

@ -3,16 +3,21 @@ package com.example.mathseduc.ui
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.icons.filled.ArrowDropDown
@ -28,21 +33,27 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import com.example.mathseduc.MainActivity import com.example.mathseduc.MainActivity
import com.example.mathseduc.ServerDetailsActivity import com.example.mathseduc.ServerDetailsActivity
import com.example.mathseduc.controllers.ControllerChapter import com.example.mathseduc.controllers.ControllerChapter
@ -67,6 +78,7 @@ fun CreateLobbyPage(navController: NavController) {
val context = LocalContext.current val context = LocalContext.current
val activity = LocalView.current.context as Activity val activity = LocalView.current.context as Activity
val keyboardController = LocalSoftwareKeyboardController.current val keyboardController = LocalSoftwareKeyboardController.current
val isPortrait = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT
val windowInsetsController = remember { val windowInsetsController = remember {
WindowCompat.getInsetsController(activity.window, activity.window.decorView) WindowCompat.getInsetsController(activity.window, activity.window.decorView)
@ -77,158 +89,169 @@ fun CreateLobbyPage(navController: NavController) {
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp) .padding(if(isPortrait)16.dp else 5.dp),
.background(Colors.Black) verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) { ) {
TextField( Text(
value = lobbyName, text = "Create Lobby",
onValueChange = { lobbyName = it }, fontSize = (if(isPortrait) 30.sp else 0.sp),
modifier = Modifier color = Color.White,
.fillMaxWidth() )
.background(Colors.White)
.padding(8.dp),
label = { Text("Lobby Name") }
)
Spacer(modifier = Modifier.height(if(isPortrait)25.dp else 0.dp))
TextField( Column(
value = password, modifier = Modifier.background(Colors.White, shape = RoundedCornerShape(8.dp)),
onValueChange = { password = it }, horizontalAlignment = Alignment.CenterHorizontally
modifier = Modifier ) {
.fillMaxWidth() TextField(
.background(Colors.White) value = lobbyName,
.padding(8.dp), onValueChange = { lobbyName = it },
label = { Text("Password") }, modifier = Modifier
visualTransformation = PasswordVisualTransformation(), .fillMaxWidth(if (isPortrait) 1f else 0.5f)
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Password) .padding(if(isPortrait) 8.dp else 4.dp),
) shape = RoundedCornerShape(8.dp),
label = { Text("Lobby Name") }
)
TextField( TextField(
value = nbPlayers, value = password,
onValueChange = { nbPlayers = it }, onValueChange = { password = it },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth(if (isPortrait) 1f else 0.5f)
.background(Colors.White) .padding(if(isPortrait) 8.dp else 4.dp),
.padding(8.dp), shape = RoundedCornerShape(8.dp),
label = { Text("Number of Players") }, label = { Text("Password") },
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number) visualTransformation = PasswordVisualTransformation(),
) keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Password)
)
Box {
TextField( TextField(
value = difficulty, value = nbPlayers,
onValueChange = { difficulty = it }, onValueChange = { nbPlayers = it },
readOnly = true, modifier = Modifier
enabled = false, .fillMaxWidth(if (isPortrait) 1f else 0.5f)
colors = TextFieldDefaults.colors( .padding(if(isPortrait) 8.dp else 4.dp),
disabledTextColor = Colors.Black, label = { Text("Number of Players") },
disabledLabelColor = Colors.Black, keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number)
disabledTrailingIconColor = Colors.Black,
disabledIndicatorColor = Color.Black
),
modifier = Modifier
.clickable(onClick = {
expandedDifficulty = !expandedDifficulty
})
.onGloballyPositioned {
size = it.size
}
.fillMaxWidth()
.background(Colors.White)
.padding(8.dp),
label = { Text("Difficulté") },
trailingIcon = {
Icon(
Icons.Default.ArrowDropDown,
contentDescription = null,
Modifier.clickable {
expandedDifficulty = !expandedDifficulty
}
)
}
) )
DropdownMenu(
expanded = expandedDifficulty,
onDismissRequest = { expandedDifficulty = false }, Box{
modifier = Modifier TextField(
.width(with(LocalDensity.current) { size.width.toDp() }) value = difficulty,
.background(Colors.White) onValueChange = { difficulty = it },
.padding(8.dp) readOnly = true,
) { enabled = false,
difficultyOptions.forEach { option -> colors = TextFieldDefaults.colors(
DropdownMenuItem( disabledTextColor = Colors.Black,
text = { Text(option, color = Colors.Black) }, disabledLabelColor = Colors.Black,
onClick = { disabledTrailingIconColor = Colors.Black,
difficulty = option disabledIndicatorColor = Color.Black
expandedDifficulty = false ),
keyboardController?.hide() modifier = Modifier
.clickable(onClick = {
expandedDifficulty = !expandedDifficulty
})
.onGloballyPositioned {
size = it.size
}
.fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(if(isPortrait) 8.dp else 4.dp),
label = { Text("Difficulté") },
trailingIcon = {
Icon(
Icons.Default.ArrowDropDown,
contentDescription = null,
Modifier.clickable {
expandedDifficulty = !expandedDifficulty
}
)
} }
) )
DropdownMenu(
expanded = expandedDifficulty,
onDismissRequest = { expandedDifficulty = false },
modifier = Modifier
.width(with(LocalDensity.current) { size.width.toDp() })
.padding(if(isPortrait) 8.dp else 4.dp)
) {
difficultyOptions.forEach { option ->
DropdownMenuItem(
text = { Text(option, color = Colors.Black) },
onClick = {
difficulty = option
expandedDifficulty = false
keyboardController?.hide()
}
)
}
} }
} }
}
Box { Box{
val chapterOptions = ControllerChapter.getChapters() val chapterOptions = ControllerChapter.getChapters()
TextField( TextField(
value = chapter, value = chapter,
onValueChange = { chapter = it }, onValueChange = { chapter = it },
readOnly = true, readOnly = true,
enabled = false, enabled = false,
colors = TextFieldDefaults.colors( colors = TextFieldDefaults.colors(
disabledTextColor = Colors.Black, disabledTextColor = Colors.Black,
disabledLabelColor = Colors.Black, disabledLabelColor = Colors.Black,
disabledTrailingIconColor = Colors.Black, disabledTrailingIconColor = Colors.Black,
disabledIndicatorColor = Color.Black disabledIndicatorColor = Color.Black
), ),
modifier = Modifier modifier = Modifier
.clickable(onClick = { .clickable(onClick = {
expandedChapter = !expandedChapter expandedChapter = !expandedChapter
}) })
.onGloballyPositioned { .onGloballyPositioned {
size = it.size size = it.size
} }
.fillMaxWidth() .fillMaxWidth(if (isPortrait) 1f else 0.5f)
.background(Colors.White) .padding(if(isPortrait) 8.dp else 4.dp),
.padding(8.dp), label = { Text("Chapitre") },
label = { Text("Chapitre") }, trailingIcon = {
trailingIcon = { Icon(
Icon( Icons.Default.ArrowDropDown,
Icons.Default.ArrowDropDown, contentDescription = null,
contentDescription = null, Modifier.clickable {
Modifier.clickable { expandedChapter = !expandedChapter
expandedChapter = !expandedChapter }
)
} }
) )
} DropdownMenu(
) expanded = expandedChapter,
DropdownMenu( onDismissRequest = { expandedChapter = false },
expanded = expandedChapter, modifier = Modifier
onDismissRequest = { expandedChapter = false }, .width(with(LocalDensity.current) { size.width.toDp() })
modifier = Modifier .padding(if(isPortrait) 8.dp else 4.dp)
.background(Colors.White) ) {
.padding(8.dp)
) {
chapterOptions?.forEach { option -> chapterOptions?.forEach { option ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(option.name, color = Colors.Black) }, text = { Text(option.name, color = Colors.Black) },
onClick = { onClick = {
chapter = option.name chapter = option.name
expandedChapter = false expandedChapter = false
keyboardController?.hide() keyboardController?.hide()
} }
) )
}
} }
} }
} }
Button( Button(
onClick = { onClick = {
// Handle button click (Create Lobby) // Handle button click (Create Lobby)
@ -281,8 +304,8 @@ fun CreateLobbyPage(navController: NavController) {
} }
}, },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(8.dp) .padding(if(isPortrait) 8.dp else 4.dp)
) { ) {
Text(text = "Create Lobby", color = Colors.White) Text(text = "Create Lobby", color = Colors.White)
} }

@ -263,7 +263,7 @@ fun LobbyItem(lobby: Lobby, isSelected: Boolean, onItemClick: (Lobby) -> Unit) {
Text( Text(
text = "${ControllerLobby.getNbPlayerInLobby(lobby.id)}/${lobby.nbplayers}", text = "${ControllerLobby.getNbPlayerInLobby(lobby.id)}/${lobby.nbplayers}",
fontSize = 18.sp, fontSize = 18.sp,
color = Colors.White, color = (if(ControllerLobby.getNbPlayerInLobby(lobby.id)==lobby.nbplayers) Color.Red else Color.White),
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )
Text( Text(

Loading…
Cancel
Save