Merge remote-tracking branch 'origin/androidCompose' into androidCompose

androidCompose
Jeremy DUCOURTHIAL 1 year ago
commit 14d05c7dd1

@ -6,9 +6,11 @@ import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
@ -30,68 +32,101 @@ class ConnexionPlayerActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
MathsEducTheme {
ConnexionPlayerContent()
ConnexionPlayerContent(activity = this@ConnexionPlayerActivity)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ConnexionPlayerContent() {
fun ConnexionPlayerContent(activity: ConnexionPlayerActivity) {
var nickname by rememberSaveable { mutableStateOf("") }
var password by rememberSaveable { mutableStateOf("") }
var showDialog by rememberSaveable { mutableStateOf(false) }
val context = LocalContext.current
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(id = R.drawable.logo),
contentDescription = null,
modifier = Modifier
.size(160.dp, 130.dp)
.background(Color.Gray) // Replace with your background color
Column(modifier = Modifier.fillMaxSize()) {
TopAppBar(
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
),
title = {},
navigationIcon = {
IconButton(
onClick = { activity.finish() },
modifier = Modifier.size(60.dp)
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Retour",
modifier = Modifier.size(36.dp),
tint = Color.White
)
}
},
)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.weight(1f),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(16.dp))
Image(
painter = painterResource(id = R.drawable.logo),
contentDescription = null,
modifier = Modifier
.size(160.dp, 130.dp)
)
OutlinedTextField(
value = nickname,
onValueChange = { nickname = it },
label = { Text("Nickname") },
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password
),
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
OutlinedTextField(
value = nickname,
onValueChange = { nickname = it },
label = { Text("Nickname") },
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = Color.White,
unfocusedContainerColor = Color.White,
disabledContainerColor = Color.White,
focusedBorderColor = Color.Blue,
),
shape = RoundedCornerShape(8.dp)
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password
),
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = Color.White,
unfocusedContainerColor = Color.White,
disabledContainerColor = Color.White,
focusedBorderColor = Color.Blue,
),
shape = RoundedCornerShape(8.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
val isAuthenticated = ControllerPlayer.authenticateUser(nickname, password)
if (isAuthenticated != -1) {
val intent = Intent(context, MainActivity::class.java)
context.startActivity(intent)
MainActivity.idPlayerConnected = isAuthenticated
Toast.makeText(context, "Connexion réussie, bienvenue $nickname !", Toast.LENGTH_SHORT).show()
} else {
@ -105,19 +140,22 @@ fun ConnexionPlayerContent() {
Text("Login")
}
Spacer(modifier = Modifier.height(16.dp))
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = { showDialog = true },
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
) {
Text("Register")
}
Button(
onClick = { showDialog = true },
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF40E0D0))
) {
Text("Register")
}
if (showDialog) {
RegisterDialog(onDismiss = { showDialog = false })
if (showDialog) {
RegisterDialog(onDismiss = { showDialog = false })
}
}
}
}
@ -130,65 +168,66 @@ fun RegisterDialog(onDismiss: () -> Unit) {
var password by remember { mutableStateOf("") }
AlertDialog(
onDismissRequest = {
onDismiss()
},
title = { Text("Register") },
confirmButton = {
Button(
onClick = {
// Save the user information or perform registration
onDismiss()
onDismissRequest = {
onDismiss()
},
title = { Text("Register") },
confirmButton = {
Button(
onClick = {
val playerId = ControllerPlayer.createPlayer(nickname, password)
onDismiss()
}
) {
Text("Save")
}
) {
Text("Save")
}
},
dismissButton = {
Button(
onClick = {
onDismiss()
},
dismissButton = {
Button(
onClick = {
onDismiss()
}
) {
Text("Dismiss")
}
},
text = {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
OutlinedTextField(
value = nickname,
onValueChange = { nickname = it },
label = { Text("Nickname") },
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password
),
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
}
) {
Text("Dismiss")
}
},
text = {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
OutlinedTextField(
value = nickname,
onValueChange = { nickname = it },
label = { Text("Nickname") },
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password
),
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
}
}
)
}
@Preview(showBackground = true)
@Composable
fun ConnexionPlayerPreview() {
val fakeActivity = ConnexionPlayerActivity()
MathsEducTheme {
ConnexionPlayerContent()
ConnexionPlayerContent(activity = fakeActivity)
}
}

@ -62,6 +62,39 @@ class ControllerPlayer {
return null
}
fun createPlayer(nickname: String, password: String): Int {
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
StrictMode.setThreadPolicy(policy)
val client = OkHttpClient()
val hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt())
val requestBody = FormBody.Builder()
.add("nickname", nickname)
.add("password", hashedPassword)
.build()
val request = Request.Builder()
.url("https://trusting-panini.87-106-126-109.plesk.page/api/add/player/qUOGkWdoPCgbmuqxIC8xiaX0rV1Pw1LoPafkaoHOgszEyD9P2vcOu493xCDZpAqO")
.post(requestBody)
.build()
client.newCall(request).execute().use { response ->
if (response.isSuccessful) {
val responseData = response.body?.string()
val gson = Gson()
val player: Player = gson.fromJson(responseData, Player::class.java)
return player.id
} else {
throw IOException("Failed to create player: ${response.code}")
}
}
}
fun authenticateUser(nickname: String, password: String): Int {
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()

@ -103,7 +103,8 @@ fun HomePage() {
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = { /* Handle connexion button click */ },
onClick = { val intent = Intent(context, ConnexionPlayerActivity::class.java)
context.startActivity(intent) },
shape = RoundedCornerShape(15),
colors = ButtonDefaults.buttonColors(Colors.Grey),
modifier = Modifier

@ -1,7 +1,7 @@
package com.example.mathseduc.ui
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.background
@ -26,6 +26,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@ -42,37 +44,47 @@ import com.example.mathseduc.controllers.ControllerLobby
import com.example.mathseduc.controllers.ControllerUtiliser
import com.example.mathseduc.models.Lobby
import com.example.mathseduc.ui.theme.Colors
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.MultipartBody
@Composable
fun MultiPage() {
val context = LocalContext.current
var selectedItem by rememberSaveable { mutableStateOf<Lobby?>(null) }
var lobbyList by rememberSaveable { mutableStateOf(ControllerLobby.getLobbies() ?: emptyList()) }
var refreshState by rememberSaveable { mutableStateOf(true) }
var lobbyList by remember { mutableStateOf<List<Lobby>>(emptyList()) }
val scope = rememberCoroutineScope()
var refreshState by remember { mutableStateOf(true) }
// Fonction pour actualiser la liste des lobbies
suspend fun refreshLobbyList() {
val refreshedLobbyList = withContext(Dispatchers.IO) {
ControllerLobby.getLobbies() ?: emptyList()
}
lobbyList = refreshedLobbyList
Log.e("MainActivity", "Refreshed Lobby List")
}
DisposableEffect(refreshState) {
val handler = Handler(Looper.getMainLooper())
val refreshRunnable = object : Runnable {
override fun run() {
lobbyList = emptyList()
lobbyList = ControllerLobby.getLobbies()!!
selectedItem = null
if (refreshState){
handler.postDelayed(this,3000)
Log.e("MainActivity", "Refresh Multi")
val refreshRunnable = {
scope.launch(Dispatchers.IO) {
try {
while (refreshState) {
delay(5000)
refreshLobbyList()
}
} catch (e: Exception) {
Log.e("MainActivity", "Error refreshing lobbies: ${e.message}")
}
}
}
handler.post(refreshRunnable)
refreshRunnable.invoke()
onDispose {
Toast.makeText(context, "Au REVOIR UwU", Toast.LENGTH_SHORT).show()
refreshState = false
handler.removeCallbacks(refreshRunnable)
}
}
@ -117,7 +129,6 @@ fun MultiPage() {
Button(
onClick = {
refreshState = false
val intent = Intent(context, CreateLobbyActivity::class.java)
context.startActivity(intent)
},
@ -136,26 +147,23 @@ fun MultiPage() {
.fillMaxSize()
.weight(0.85f)
) {
items(lobbyList ?: emptyList()) { lobby ->
items(lobbyList) { lobby ->
LobbyItem(lobby, selectedItem == lobby) {
selectedItem = it
refreshState = false
if (ControllerLobby.getNbPlayerInLobby(selectedItem!!.id) < selectedItem!!.nbplayers){
val formDataBuilder = MultipartBody.Builder().setType(MultipartBody.FORM)
formDataBuilder.addFormDataPart("idplayer", MainActivity.idPlayerConnected.toString())
formDataBuilder.addFormDataPart("idlobby", selectedItem!!.id.toString())
formDataBuilder.addFormDataPart("playertime", "0")
ControllerUtiliser.createUtiliserByIdLobby(formDataBuilder)
val intent = Intent(context, ServerDetailsActivity::class.java)
intent.putExtra("serverName", selectedItem!!.name)
intent.putExtra("lobbyId", selectedItem!!.id)
context.startActivity(intent)
if (ControllerLobby.getNbPlayerInLobby(selectedItem!!.id) < selectedItem!!.nbplayers) {
// Créer un Utiliser si le lobby n'est pas plein
scope.launch {
createUtiliserForLobby(context, selectedItem!!)
}
} else {
Toast.makeText(context, "Oh nan, le serveur est déjà plein ! Réessayer plus tard.", Toast.LENGTH_SHORT).show()
// Afficher un message Toast si le lobby est plein
Toast.makeText(
context,
"Oh nan, le serveur est déjà plein ! Réessayer plus tard.",
Toast.LENGTH_SHORT
).show()
}
}
}
@ -164,10 +172,26 @@ fun MultiPage() {
}
}
// Fonction pour créer un Utiliser pour le lobby sélectionné
private suspend fun createUtiliserForLobby(context: Context, lobby: Lobby) {
withContext(Dispatchers.IO) {
val formDataBuilder = MultipartBody.Builder().setType(MultipartBody.FORM)
formDataBuilder.addFormDataPart("idplayer", MainActivity.idPlayerConnected.toString())
formDataBuilder.addFormDataPart("idlobby", lobby.id.toString())
formDataBuilder.addFormDataPart("playertime", "0")
ControllerUtiliser.createUtiliserByIdLobby(formDataBuilder)
// Naviguer vers l'activité ServerDetails avec les détails du lobby
val intent = Intent(context, ServerDetailsActivity::class.java)
intent.putExtra("serverName", lobby.name)
intent.putExtra("lobbyId", lobby.id)
context.startActivity(intent)
}
}
@Composable
fun LobbyItem(lobby: Lobby, isSelected: Boolean, onItemClick: (Lobby) -> Unit) {
val nbCurrentPlayer = ControllerLobby.getNbPlayerInLobby(lobby.id)
Row(
modifier = Modifier
.fillMaxWidth()
@ -184,7 +208,6 @@ fun LobbyItem(lobby: Lobby, isSelected: Boolean, onItemClick: (Lobby) -> Unit) {
fontSize = 18.sp,
color = Colors.White,
modifier = Modifier.weight(1f)
)
Text(
text = "${ControllerLobby.getNbPlayerInLobby(lobby.id)}/${lobby.nbplayers}",
@ -205,5 +228,4 @@ fun LobbyItem(lobby: Lobby, isSelected: Boolean, onItemClick: (Lobby) -> Unit) {
modifier = Modifier.weight(1f)
)
}
}
}
Loading…
Cancel
Save