Merge branch 'androidCompose' of https://codefirst.iut.uca.fr/git/jade.van_brabandt/3.01-QCM_MuscuMaths into androidCompose
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
1019af52d0
@ -0,0 +1,268 @@
|
||||
package com.example.mathseduc.ui
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
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.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
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.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelStoreOwner
|
||||
import androidx.navigation.NavController
|
||||
import com.example.mathseduc.QuizMultiActivity
|
||||
import com.example.mathseduc.ui.theme.Colors
|
||||
import com.example.mathseduc.viewModel.ServerDetailsViewModel
|
||||
import okhttp3.MultipartBody
|
||||
|
||||
@Composable
|
||||
fun LeaveLobbyDialog(namelobby: String, onConfirmLeave: () -> Unit, onCancelLeave: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onCancelLeave,
|
||||
title = { Text("Confirm leaving lobby") },
|
||||
confirmButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
onConfirmLeave()
|
||||
}
|
||||
) {
|
||||
Text("Leave")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
onCancelLeave()
|
||||
}
|
||||
) {
|
||||
Text("Cancel")
|
||||
}
|
||||
},
|
||||
text = {
|
||||
Text("Are you sure you want to leave the lobby $namelobby?")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ServerDetailPage(navController: NavController, serverName: String?, lobbyId: Int?, chapterId: Int?, nbPlayers: Int?, lobbyDifficulty: Int?) {
|
||||
val context = LocalContext.current
|
||||
val viewModelStoreOwner = LocalContext.current as ViewModelStoreOwner
|
||||
val viewModel = ViewModelProvider(viewModelStoreOwner).get(ServerDetailsViewModel::class.java)
|
||||
|
||||
val playerList by viewModel.playerList.collectAsState(initial = emptyList())
|
||||
val playerListInfos by viewModel.playerListInfos.collectAsState(initial = emptyList())
|
||||
val isCreator by viewModel.isCreator.collectAsState(false)
|
||||
val refreshState by viewModel.refreshState.collectAsState(true)
|
||||
val showDialog by viewModel.showDialog.collectAsState(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) {
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
val refreshRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
viewModel.updatePlayerList(lobbyId)
|
||||
viewModel.updatePlayerListInfos()
|
||||
viewModel.updateIsCreator(lobbyId)
|
||||
|
||||
if(viewModel.Launchedlobby(lobbyId)){
|
||||
val intent = Intent(context, QuizMultiActivity::class.java)
|
||||
intent.putExtra("serverName", serverName)
|
||||
intent.putExtra("lobbyId", lobbyId)
|
||||
intent.putExtra("chapterId", chapterId)
|
||||
intent.putExtra("nbPlayers", nbPlayers)
|
||||
intent.putExtra("lobbyDifficulty", lobbyDifficulty)
|
||||
context.startActivity(intent)
|
||||
viewModel.updateRefresh(false)
|
||||
}
|
||||
|
||||
if (refreshState){
|
||||
handler.postDelayed(this,3000)
|
||||
Log.e("MainActivity", "Refresh ServerDetails")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handler.post(refreshRunnable)
|
||||
|
||||
onDispose {
|
||||
viewModel.updateRefresh(false)
|
||||
handler.removeCallbacks(refreshRunnable)
|
||||
}
|
||||
}
|
||||
|
||||
TopAppBar(
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = Color.Transparent,
|
||||
),
|
||||
title = {},
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = { viewModel.updateShowDialog(true) },
|
||||
modifier = Modifier.size(60.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ArrowBack,
|
||||
contentDescription = "Retour",
|
||||
modifier = Modifier.size(36.dp),
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
val modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 8.dp)
|
||||
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = serverName!!,
|
||||
color = Color.White,
|
||||
fontSize = 30.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(if(isPortrait)25.dp else 10.dp))
|
||||
|
||||
Text(
|
||||
text = "Lobby Settings",
|
||||
fontSize = 23.sp,
|
||||
color = Color.White,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
text = "Chapter : ${viewModel.getChapterNameById(chapterId).toString()}",
|
||||
fontSize = 19.sp,
|
||||
color = Color.White
|
||||
)
|
||||
Row {
|
||||
Text(
|
||||
text = "Players : ${playerListInfos.size}/${nbPlayers}",
|
||||
fontSize = 19.sp,
|
||||
color = (if(viewModel.getNbPlayerInLobby(lobbyId)==nbPlayers) Color.Red else Color.White)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(40.dp))
|
||||
Text(
|
||||
text = "Difficulty : $lobbyDifficulty",
|
||||
fontSize = 19.sp,
|
||||
color = Colors.White,
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(if(isPortrait)30.dp else 10.dp))
|
||||
|
||||
Text(
|
||||
text = "Player Name",
|
||||
fontSize = 19.sp,
|
||||
modifier = Modifier.background(Color.Black),
|
||||
color = Colors.White,
|
||||
)
|
||||
Divider(
|
||||
color = Color.Gray,
|
||||
thickness = 2.dp,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.weight(0.75f)
|
||||
.padding(top = 1.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
items(playerListInfos) { player ->
|
||||
Text(
|
||||
text = player.nickname,
|
||||
fontSize = 18.sp,
|
||||
color = Colors.White,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(top = if (isPortrait) 5.dp else 1.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (isCreator) {
|
||||
val formDataBuilder = MultipartBody.Builder().setType(MultipartBody.FORM)
|
||||
formDataBuilder.addFormDataPart("launched", "1")
|
||||
Button(
|
||||
onClick = {
|
||||
viewModel.updateLobbyLauched(lobbyId,formDataBuilder)
|
||||
},
|
||||
shape = RoundedCornerShape(15),
|
||||
enabled = isCreator,
|
||||
colors = ButtonDefaults.buttonColors(Colors.Green),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "LAUNCH",
|
||||
color = Color.White,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
if (showDialog) {
|
||||
LeaveLobbyDialog(serverName, onConfirmLeave = {navController.navigate("multiplayer")},onCancelLeave = { viewModel.updateShowDialog(false) })
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.example.mathseduc.viewModel
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.example.mathseduc.MainActivity
|
||||
import com.example.mathseduc.controllers.ControllerChapter
|
||||
import com.example.mathseduc.controllers.ControllerLobby
|
||||
import com.example.mathseduc.controllers.ControllerPlayer
|
||||
import com.example.mathseduc.models.Lobby
|
||||
import com.example.mathseduc.models.Player
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import okhttp3.MultipartBody
|
||||
|
||||
class CreateLobbyViewModel : ViewModel() {
|
||||
|
||||
private var lobbyNameState = MutableStateFlow("")
|
||||
val lobbyName : StateFlow<String> = lobbyNameState
|
||||
|
||||
private var passwordState = MutableStateFlow("")
|
||||
val password: StateFlow<String> = passwordState
|
||||
|
||||
private var nbPlayersState = MutableStateFlow("")
|
||||
val nbPlayers: StateFlow<String> = nbPlayersState
|
||||
|
||||
private var difficultyState = MutableStateFlow("")
|
||||
val difficulty: StateFlow<String> = difficultyState
|
||||
|
||||
private var chapterState = MutableStateFlow("")
|
||||
val chapter : StateFlow<String> = chapterState
|
||||
|
||||
private var expandedDifficultyState = MutableStateFlow(false)
|
||||
val expandedDifficulty: StateFlow<Boolean> = expandedDifficultyState
|
||||
|
||||
private var expandedChapterState = MutableStateFlow(false)
|
||||
val expandedChapter: StateFlow<Boolean> = expandedChapterState
|
||||
|
||||
private var sizeState = MutableStateFlow(IntSize.Zero)
|
||||
val size : StateFlow<IntSize> = sizeState
|
||||
|
||||
fun updateLobbyName(lobbyName : String) {
|
||||
this.lobbyNameState.update { lobbyName }
|
||||
}
|
||||
|
||||
fun updatePassword(password : String) {
|
||||
this.passwordState.update { password }
|
||||
}
|
||||
|
||||
fun updateNbPlayers(nbPlayers : String) {
|
||||
this.nbPlayersState.update { nbPlayers }
|
||||
}
|
||||
|
||||
fun updateDifficulty(difficulty : String) {
|
||||
this.difficultyState.update { difficulty }
|
||||
}
|
||||
|
||||
fun updatechapter(chapter : String) {
|
||||
this.chapterState.update { chapter }
|
||||
}
|
||||
|
||||
fun updateExpandedChapter(expandedChapter : Boolean) {
|
||||
this.expandedChapterState.update { expandedChapter }
|
||||
}
|
||||
|
||||
fun updateExpandedDifficulty(expandedDifficulty : Boolean) {
|
||||
this.expandedDifficultyState.update { expandedDifficulty }
|
||||
}
|
||||
|
||||
fun updateSize(size : IntSize) {
|
||||
this.sizeState.update { size }
|
||||
}
|
||||
}
|
@ -1,23 +1,73 @@
|
||||
package com.example.mathseduc.viewModel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.example.mathseduc.MainActivity
|
||||
import com.example.mathseduc.controllers.ControllerChapter
|
||||
import com.example.mathseduc.controllers.ControllerLobby
|
||||
import com.example.mathseduc.controllers.ControllerPlayer
|
||||
import com.example.mathseduc.models.Lobby
|
||||
import com.example.mathseduc.models.Player
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import okhttp3.MultipartBody
|
||||
|
||||
class ServerDetailsViewModel : ViewModel() {
|
||||
|
||||
private var lobbyListState = MutableStateFlow<List<Lobby>>(emptyList())
|
||||
val lobbyList : StateFlow<List<Lobby>> = lobbyListState
|
||||
private var playerListState = MutableStateFlow<List<Int>>(emptyList())
|
||||
val playerList : StateFlow<List<Int>> = playerListState
|
||||
|
||||
private var playerListInfosState = MutableStateFlow<List<Player>>(emptyList())
|
||||
val playerListInfos: StateFlow<List<Player>> = playerListInfosState
|
||||
|
||||
private var isCreatorState = MutableStateFlow(false)
|
||||
val isCreator: StateFlow<Boolean> = isCreatorState
|
||||
|
||||
private var showDialogState = MutableStateFlow(false)
|
||||
val showDialog: StateFlow<Boolean> = showDialogState
|
||||
|
||||
private var refreshStateState = MutableStateFlow(true)
|
||||
val refreshState : StateFlow<Boolean> = refreshStateState
|
||||
|
||||
fun updatePlayerList(lobbyId : Int?) {
|
||||
this.playerListState.update {
|
||||
ControllerPlayer.getPlayersIdFromLobbyId(lobbyId.toString()) ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun updatePlayerListInfos() {
|
||||
this.playerListInfosState.update {
|
||||
playerList.value.mapNotNull { playerId -> ControllerPlayer.getPlayerInfoById(playerId.toString()) }
|
||||
}
|
||||
}
|
||||
|
||||
fun updateLobbyList() {
|
||||
this.lobbyListState.update {
|
||||
ControllerLobby.getLobbies() ?: emptyList()
|
||||
fun updateIsCreator(lobbyId : Int?) {
|
||||
this.isCreatorState.update {
|
||||
ControllerLobby.playerCreatorIdPresentInLobby(MainActivity.idPlayerConnected, lobbyId)
|
||||
}
|
||||
}
|
||||
|
||||
fun getNbPlayerInLobby(selectedItem : Lobby) : Int {
|
||||
return ControllerLobby.getNbPlayerInLobby(selectedItem!!.id)
|
||||
fun updateRefresh(bool : Boolean) {
|
||||
this.refreshStateState.update { bool }
|
||||
}
|
||||
|
||||
fun updateShowDialog(bool : Boolean) {
|
||||
this.showDialogState.update { bool }
|
||||
}
|
||||
|
||||
fun Launchedlobby(lobbyId : Int?): Boolean{
|
||||
return ControllerLobby.lobbyIsLaunched(lobbyId)
|
||||
}
|
||||
|
||||
fun getNbPlayerInLobby(lobbyId : Int?) : Int{
|
||||
return ControllerLobby.getNbPlayerInLobby(lobbyId)
|
||||
}
|
||||
|
||||
fun getChapterNameById(chapterId: Int?): String?{
|
||||
return ControllerChapter.getChapterNameById(chapterId)
|
||||
}
|
||||
|
||||
fun updateLobbyLauched(lobbyId : Int?,formDataBuilder: MultipartBody.Builder){
|
||||
ControllerLobby.updateLobbyLauched(lobbyId,formDataBuilder)
|
||||
}
|
||||
}
|
Loading…
Reference in new issue