From 4776e5ae0d568b7d69150d8831395fbf17e75da0 Mon Sep 17 00:00:00 2001 From: "maxence.guitard" Date: Sun, 31 Mar 2024 06:20:04 +0200 Subject: [PATCH] feat : option deletePlayer, Disconnected and ChangeInfosPlayer --- .../mathseduc/ConnexionPlayerActivity.kt | 40 +++++-- .../mathseduc/controllers/ControllerPlayer.kt | 46 ++++++-- .../mathseduc/ui/activity_profil_player.kt | 109 +++++++++++++++--- 3 files changed, 160 insertions(+), 35 deletions(-) diff --git a/Android/app/src/main/java/com/example/mathseduc/ConnexionPlayerActivity.kt b/Android/app/src/main/java/com/example/mathseduc/ConnexionPlayerActivity.kt index e2e779d..f8db6df 100644 --- a/Android/app/src/main/java/com/example/mathseduc/ConnexionPlayerActivity.kt +++ b/Android/app/src/main/java/com/example/mathseduc/ConnexionPlayerActivity.kt @@ -147,6 +147,8 @@ fun ConnexionPlayerContent(navController: NavController) { navController.navigate("home") } else { Toast.makeText(context, "Connexion échouée. Veuillez réessayer.", Toast.LENGTH_SHORT).show() + nickname = "" + password = "" } }, modifier = Modifier @@ -183,6 +185,9 @@ fun RegisterDialog(onDismiss: () -> Unit) { var nickname by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } + var nicknameError by remember { mutableStateOf(false) } + var passwordError by remember { mutableStateOf(false) } + AlertDialog( onDismissRequest = { onDismiss() @@ -191,8 +196,13 @@ fun RegisterDialog(onDismiss: () -> Unit) { confirmButton = { Button( onClick = { - val playerId = ControllerPlayer.createPlayer(nickname, password) - onDismiss() + if (nickname.isNotBlank() && password.isNotBlank()) { + val playerId = ControllerPlayer.createPlayer(nickname, password) + onDismiss() + } else { + if (nickname.isBlank()) nicknameError = true + if (password.isBlank()) passwordError = true + } } ) { Text("Save") @@ -215,16 +225,23 @@ fun RegisterDialog(onDismiss: () -> Unit) { ) { OutlinedTextField( value = nickname, - onValueChange = { nickname = it }, + onValueChange = { + nickname = it + nicknameError = false + }, label = { Text("Nickname") }, modifier = Modifier .fillMaxWidth() - .padding(8.dp) + .padding(8.dp), + isError = nicknameError ) OutlinedTextField( value = password, - onValueChange = { password = it }, + onValueChange = { + password = it + passwordError = false + }, label = { Text("Password") }, visualTransformation = PasswordVisualTransformation(), keyboardOptions = KeyboardOptions.Default.copy( @@ -232,9 +249,18 @@ fun RegisterDialog(onDismiss: () -> Unit) { ), modifier = Modifier .fillMaxWidth() - .padding(8.dp) + .padding(8.dp), + isError = passwordError ) + + if (nicknameError || passwordError) { + Text( + text = "Please fill in all fields", + color = Color.Red, + modifier = Modifier.padding(start = 8.dp) + ) + } } } ) -} \ No newline at end of file +} diff --git a/Android/app/src/main/java/com/example/mathseduc/controllers/ControllerPlayer.kt b/Android/app/src/main/java/com/example/mathseduc/controllers/ControllerPlayer.kt index 12ce4e5..f97e7ed 100644 --- a/Android/app/src/main/java/com/example/mathseduc/controllers/ControllerPlayer.kt +++ b/Android/app/src/main/java/com/example/mathseduc/controllers/ControllerPlayer.kt @@ -6,6 +6,7 @@ import com.example.mathseduc.models.* import com.google.gson.Gson import com.google.gson.reflect.TypeToken import okhttp3.FormBody +import okhttp3.MultipartBody import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response @@ -96,34 +97,55 @@ class ControllerPlayer { } } } - /* - fun updatePlayer(playerId: String,nickname: String, password: String) { + + fun deletePlayer(playerId: String) { try { val policy = StrictMode.ThreadPolicy.Builder().permitAll().build() StrictMode.setThreadPolicy(policy) + // Client HTTP API val client = OkHttpClient() - val hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt()) - - val requestBody = FormBody.Builder() - .add("nickname", nickname) - .add("password", hashedPassword) + // API Access - Suppression du player + val deleteRequest = Request.Builder() + .url("https://trusting-panini.87-106-126-109.plesk.page/api/delete/player/$playerId/qUOGkWdoPCgbmuqxIC8xiaX0rV1Pw1LoPafkaoHOgszEyD9P2vcOu493xCDZpAqO") + .delete() .build() + // API Response + val deleteResponse: Response = client.newCall(deleteRequest).execute() + + // Vérifier si la suppression a réussi + if (!deleteResponse.isSuccessful) { + Log.e("deletePlayer", "Error deleting player") + } + } catch (e: Exception) { + // Log en cas d'erreur + Log.e("deletePlayer", "Error deleting player", e) + } + } + + fun updatePlayer(playerId: String,lobbyData: MultipartBody.Builder) { + try { + val policy = StrictMode.ThreadPolicy.Builder().permitAll().build() + StrictMode.setThreadPolicy(policy) + + val client = OkHttpClient() + val updateRequest = Request.Builder() .url("https://trusting-panini.87-106-126-109.plesk.page/api/update/player/${playerId}/qUOGkWdoPCgbmuqxIC8xiaX0rV1Pw1LoPafkaoHOgszEyD9P2vcOu493xCDZpAqO") - .post(requestBody) + .post(lobbyData.build()) .build() val updateResponse: Response = client.newCall(updateRequest).execute() - if (!updateResponse.isSuccessful) { + + if (!updateResponse.isSuccessful) { Log.e("updatePlayer", "Error updating player") - } + } } catch (e: Exception) { - Log.e("updateLobby", "Error updating lobby", e) + Log.e("updatePlayer", "Error updating lobby", e) } - }*/ + } fun authenticateUser(nickname: String, password: String): Int { diff --git a/Android/app/src/main/java/com/example/mathseduc/ui/activity_profil_player.kt b/Android/app/src/main/java/com/example/mathseduc/ui/activity_profil_player.kt index 7df0f3a..85517a6 100644 --- a/Android/app/src/main/java/com/example/mathseduc/ui/activity_profil_player.kt +++ b/Android/app/src/main/java/com/example/mathseduc/ui/activity_profil_player.kt @@ -2,18 +2,15 @@ package com.example.mathseduc.ui import android.app.Activity import android.content.res.Configuration -import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons @@ -39,7 +36,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType @@ -51,9 +47,10 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.navigation.NavController import com.example.mathseduc.MainActivity -import com.example.mathseduc.RegisterDialog import com.example.mathseduc.controllers.ControllerPlayer import com.example.mathseduc.ui.theme.Colors +import okhttp3.MultipartBody +import org.mindrot.jbcrypt.BCrypt @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -62,6 +59,7 @@ fun ProfilePlayerPage(navController: NavController) { val player = ControllerPlayer.getPlayerInfoById(MainActivity.idPlayerConnected.toString()) var showDialog by rememberSaveable { mutableStateOf(false) } + var confirmDialog by rememberSaveable { mutableStateOf(false) } val isPortrait = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT @@ -153,7 +151,23 @@ fun ProfilePlayerPage(navController: NavController) { Spacer(modifier = Modifier.height(10.dp)) Button( - onClick = { }, + onClick = { MainActivity.idPlayerConnected = -1 + navController.navigate("home") }, + shape = RoundedCornerShape(15), + colors = ButtonDefaults.buttonColors(Colors.Blue), + modifier = Modifier + .height(48.dp) + .padding(horizontal = 6.dp) + ) { + Text( + text = "disconnection", + color = Color.White + ) + } + + Spacer(modifier = Modifier.height(10.dp)) + Button( + onClick = { confirmDialog = true }, shape = RoundedCornerShape(15), colors = ButtonDefaults.buttonColors(Colors.Red), modifier = Modifier @@ -167,7 +181,15 @@ fun ProfilePlayerPage(navController: NavController) { } if (showDialog) { if (player != null) { - ChangeDialog(player.id.toString(),onDismiss = { showDialog = false }) + ChangeDialog(player.id.toString(),player.nickname,onDismiss = { showDialog = false }) + } + } + if (confirmDialog) { + if (player != null) { + DeleteConfirmDialog(onConfirmDelete = { ControllerPlayer.deletePlayer(player.id.toString()) + MainActivity.idPlayerConnected = -1 + navController.navigate("home") + confirmDialog = false},onDismiss = { confirmDialog = false }) } } } @@ -175,12 +197,14 @@ fun ProfilePlayerPage(navController: NavController) { } @Composable -fun ChangeDialog(playerId: String,onDismiss: () -> Unit) { - val context = LocalContext.current +fun ChangeDialog(playerId: String, currentNickname: String, onDismiss: () -> Unit) { - var nickname by rememberSaveable { mutableStateOf("") } + var nickname by rememberSaveable { mutableStateOf(currentNickname) } var password by rememberSaveable { mutableStateOf("") } + var nicknameError by remember { mutableStateOf(false) } + var passwordError by remember { mutableStateOf(false) } + AlertDialog( onDismissRequest = { onDismiss() @@ -191,10 +215,15 @@ fun ChangeDialog(playerId: String,onDismiss: () -> Unit) { colors = ButtonDefaults.buttonColors(Colors.Cyan), onClick = { if (nickname.isNotBlank() && password.isNotBlank()) { - /*ControllerPlayer.updatePlayer(playerId,nickname,password)*/ + val hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt()) + val formDataBuilder = MultipartBody.Builder().setType(MultipartBody.FORM) + formDataBuilder.addFormDataPart("nickname", nickname) + formDataBuilder.addFormDataPart("password", hashedPassword) + ControllerPlayer.updatePlayer(playerId, formDataBuilder) onDismiss() } else { - Toast.makeText(context, "Please fill in all fields", Toast.LENGTH_SHORT).show() + if (nickname.isBlank()) nicknameError = true + if (password.isBlank()) passwordError = true } } ) { @@ -219,15 +248,22 @@ fun ChangeDialog(playerId: String,onDismiss: () -> Unit) { ) { OutlinedTextField( value = nickname, - onValueChange = { nickname = it }, + onValueChange = { + nickname = it + nicknameError = false + }, label = { Text("Nickname") }, modifier = Modifier .fillMaxWidth() - .padding(8.dp) + .padding(8.dp), + isError = nicknameError ) OutlinedTextField( value = password, - onValueChange = { password = it }, + onValueChange = { + password = it + passwordError = false + }, label = { Text("Password") }, visualTransformation = PasswordVisualTransformation(), keyboardOptions = KeyboardOptions.Default.copy( @@ -235,9 +271,50 @@ fun ChangeDialog(playerId: String,onDismiss: () -> Unit) { ), modifier = Modifier .fillMaxWidth() - .padding(8.dp) + .padding(8.dp), + isError = passwordError ) + + if (nicknameError || passwordError) { + Text( + text = "Please fill in all fields", + color = Color.Red, + modifier = Modifier.padding(start = 8.dp) + ) + } } } ) } + + +@Composable +fun DeleteConfirmDialog(onConfirmDelete: () -> Unit, onDismiss: () -> Unit) { + AlertDialog( + onDismissRequest = onDismiss, + title = { Text("Confirm deleting account") }, + confirmButton = { + Button( + onClick = { + onConfirmDelete() + }, + colors = ButtonDefaults.buttonColors(Colors.Red) + ) { + Text("Delete",color = Color.White) + } + }, + dismissButton = { + Button( + onClick = { + onDismiss() + }, + colors = ButtonDefaults.buttonColors(Color.LightGray) + ) { + Text("Cancel",color = Color.White) + } + }, + text = { + Text("Are you sure you want to delete your account?") + } + ) +} \ No newline at end of file