feat : finition ServerDetailsViewModel + ajout CreateLobbyViewModel

androidCompose
Jeremy DUCOURTHIAL 1 year ago
parent 820ec2b59b
commit f6f63d73ad

@ -62,6 +62,7 @@ dependencies {
implementation("androidx.compose.ui:ui-graphics-android:1.6.3")
implementation("androidx.navigation:navigation-common-ktx:2.7.7")
implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("androidx.navigation:navigation-runtime-ktx:2.7.7")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

@ -3,6 +3,8 @@ package com.example.mathseduc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.ViewModelStoreOwner
import androidx.navigation.compose.rememberNavController
import com.example.mathseduc.ui.CreateLobbyPage
@ -11,7 +13,7 @@ class CreateLobbyActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
CreateLobbyPage(navController)
CreateLobbyPage(navController = navController)
}
}
}

@ -38,6 +38,7 @@ 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.mutableStateOf
import androidx.compose.runtime.remember
@ -55,6 +56,8 @@ 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 androidx.navigation.compose.rememberNavController
import com.example.mathseduc.controllers.ControllerChapter
@ -63,6 +66,7 @@ import com.example.mathseduc.controllers.ControllerPlayer
import com.example.mathseduc.controllers.ControllerUtiliser
import com.example.mathseduc.models.Player
import com.example.mathseduc.ui.theme.Colors
import com.example.mathseduc.viewModel.ServerDetailsViewModel
import okhttp3.MultipartBody
class ServerDetailsActivity : ComponentActivity() {
@ -111,6 +115,8 @@ class ServerDetailsActivity : ComponentActivity() {
@Composable
fun ServerDetailPage(navController: NavController) {
val context = LocalContext.current
val viewModelStoreOwner = LocalContext.current as ViewModelStoreOwner
val viewModel = ViewModelProvider(viewModelStoreOwner).get(ServerDetailsViewModel::class.java)
val serverName = intent.getStringExtra("serverName")
val lobbyId = intent.getIntExtra("lobbyId",-1)
@ -118,14 +124,15 @@ class ServerDetailsActivity : ComponentActivity() {
val nbPlayers = intent.getIntExtra("nbPlayers",-1)
val lobbyDifficulty = intent.getIntExtra("lobbyDifficulty",-1)
var isCreator by rememberSaveable { mutableStateOf(false) }
var playerListInfos: List<Player> by rememberSaveable { mutableStateOf(emptyList()) }
var playerList by rememberSaveable { mutableStateOf(ControllerPlayer.getPlayersIdFromLobbyId(lobbyId.toString()) ?: emptyList()) }
var refreshState by rememberSaveable { mutableStateOf(true) }
var showDialog by rememberSaveable { mutableStateOf(false) }
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)
}
@ -138,15 +145,11 @@ class ServerDetailsActivity : ComponentActivity() {
val handler = Handler(Looper.getMainLooper())
val refreshRunnable = object : Runnable {
override fun run() {
playerList = ControllerPlayer.getPlayersIdFromLobbyId(lobbyId.toString())!!
playerListInfos = playerList.mapNotNull { playerId ->
ControllerPlayer.getPlayerInfoById(playerId.toString())
}
viewModel.updatePlayerList(lobbyId)
viewModel.updatePlayerListInfos()
viewModel.updateIsCreator(lobbyId)
isCreator = ControllerLobby.playerCreatorIdPresentInLobby(MainActivity.idPlayerConnected, lobbyId)
if(ControllerLobby.lobbyIsLaunched(lobbyId)){
if(viewModel.Launchedlobby(lobbyId)){
val intent = Intent(context, QuizMultiActivity::class.java)
intent.putExtra("serverName", serverName)
intent.putExtra("lobbyId", lobbyId)
@ -154,7 +157,7 @@ class ServerDetailsActivity : ComponentActivity() {
intent.putExtra("nbPlayers", nbPlayers)
intent.putExtra("lobbyDifficulty", lobbyDifficulty)
context.startActivity(intent)
refreshState = false
viewModel.updateRefresh(false)
}
if (refreshState){
@ -167,7 +170,7 @@ class ServerDetailsActivity : ComponentActivity() {
handler.post(refreshRunnable)
onDispose {
refreshState = false
viewModel.updateRefresh(false)
handler.removeCallbacks(refreshRunnable)
}
}
@ -179,7 +182,7 @@ class ServerDetailsActivity : ComponentActivity() {
title = {},
navigationIcon = {
IconButton(
onClick = { showDialog = true },
onClick = { viewModel.updateShowDialog(true) },
modifier = Modifier.size(60.dp)
) {
Icon(
@ -217,15 +220,15 @@ class ServerDetailsActivity : ComponentActivity() {
fontWeight = FontWeight.Bold
)
Text(
text = "Chapter : ${ControllerChapter.getChapterNameById(chapterId).toString()}",
text = "Chapter : ${viewModel.getChapterNameById(chapterId).toString()}",
fontSize = 19.sp,
color = Color.White
)
Row {
Text(
text = "Players : ${ControllerLobby.getNbPlayerInLobby(lobbyId)}/${nbPlayers}",
text = "Players : ${playerListInfos.size}/${nbPlayers}",
fontSize = 19.sp,
color = (if(ControllerLobby.getNbPlayerInLobby(lobbyId)==nbPlayers) Color.Red else Color.White)
color = (if(viewModel.getNbPlayerInLobby(lobbyId)==nbPlayers) Color.Red else Color.White)
)
Spacer(modifier = Modifier.width(40.dp))
Text(
@ -271,7 +274,7 @@ class ServerDetailsActivity : ComponentActivity() {
formDataBuilder.addFormDataPart("launched", "1")
Button(
onClick = {
ControllerLobby.updateLobbyLauched(lobbyId,formDataBuilder)
viewModel.updateLobbyLauched(lobbyId,formDataBuilder)
},
shape = RoundedCornerShape(15),
enabled = isCreator,
@ -288,7 +291,7 @@ class ServerDetailsActivity : ComponentActivity() {
}
}
if (showDialog) {
LeaveLobbyDialog(serverName, onConfirmLeave = {navController.navigate("multiplayer")},onCancelLeave = { showDialog = false })
LeaveLobbyDialog(serverName, onConfirmLeave = {navController.navigate("multiplayer")},onCancelLeave = { viewModel.updateShowDialog(false) })
}
}
}
@ -302,6 +305,7 @@ class ServerDetailsActivity : ComponentActivity() {
confirmButton = {
Button(
onClick = {
myBackPressed()
onConfirmLeave()
}
) {

@ -29,6 +29,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -52,29 +53,36 @@ 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 androidx.navigation.compose.rememberNavController
import com.example.mathseduc.MainActivity
import com.example.mathseduc.ServerDetailsActivity
import com.example.mathseduc.controllers.ControllerChapter
import com.example.mathseduc.controllers.ControllerLobby
import com.example.mathseduc.controllers.ControllerUtiliser
import com.example.mathseduc.ui.theme.Colors
import com.example.mathseduc.viewModel.CreateLobbyViewModel
import com.example.mathseduc.viewModel.ServerDetailsViewModel
import okhttp3.MultipartBody
@Composable
fun CreateLobbyPage(navController: NavController) {
var lobbyName by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var nbPlayers by remember { mutableStateOf("") }
var difficulty by remember { mutableStateOf("") }
var chapter by remember { mutableStateOf("") }
var expandedDifficulty by remember { mutableStateOf(false) }
var expandedChapter by remember { mutableStateOf(false) }
var size by remember { mutableStateOf(IntSize.Zero) }
val viewModelStoreOwner = LocalContext.current as ViewModelStoreOwner
val viewModel = ViewModelProvider(viewModelStoreOwner).get(CreateLobbyViewModel::class.java)
val difficultyOptions = listOf("Facile", "Moyen", "Difficile")
val lobbyName by viewModel.lobbyName.collectAsState("")
val password by viewModel.password.collectAsState("")
val nbPlayers by viewModel.nbPlayers.collectAsState("")
val difficulty by viewModel.difficulty.collectAsState("")
val chapter by viewModel.chapter.collectAsState("")
val expandedDifficulty by viewModel.expandedDifficulty.collectAsState(false)
val expandedChapter by viewModel.expandedChapter.collectAsState(false)
val size by viewModel.size.collectAsState(IntSize.Zero)
val context = LocalContext.current
val activity = LocalView.current.context as Activity
val keyboardController = LocalSoftwareKeyboardController.current
@ -109,7 +117,7 @@ fun CreateLobbyPage(navController: NavController) {
) {
TextField(
value = lobbyName,
onValueChange = { lobbyName = it },
onValueChange = { viewModel.updateLobbyName(it) },
modifier = Modifier
.fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(if(isPortrait) 8.dp else 4.dp),
@ -120,7 +128,7 @@ fun CreateLobbyPage(navController: NavController) {
TextField(
value = password,
onValueChange = { password = it },
onValueChange = { viewModel.updatePassword(it) },
modifier = Modifier
.fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(if(isPortrait) 8.dp else 4.dp),
@ -133,7 +141,7 @@ fun CreateLobbyPage(navController: NavController) {
TextField(
value = nbPlayers,
onValueChange = { nbPlayers = it },
onValueChange = { viewModel.updateNbPlayers(it) },
modifier = Modifier
.fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(if(isPortrait) 8.dp else 4.dp),
@ -145,7 +153,7 @@ fun CreateLobbyPage(navController: NavController) {
Box{
TextField(
value = difficulty,
onValueChange = { difficulty = it },
onValueChange = { viewModel.updateDifficulty(it) },
readOnly = true,
enabled = false,
colors = TextFieldDefaults.colors(
@ -156,10 +164,10 @@ fun CreateLobbyPage(navController: NavController) {
),
modifier = Modifier
.clickable(onClick = {
expandedDifficulty = !expandedDifficulty
viewModel.updateExpandedDifficulty(!expandedDifficulty)
})
.onGloballyPositioned {
size = it.size
viewModel.updateSize(it.size)
}
.fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(if(isPortrait) 8.dp else 4.dp),
@ -169,14 +177,14 @@ fun CreateLobbyPage(navController: NavController) {
Icons.Default.ArrowDropDown,
contentDescription = null,
Modifier.clickable {
expandedDifficulty = !expandedDifficulty
viewModel.updateExpandedDifficulty(!expandedDifficulty)
}
)
}
)
DropdownMenu(
expanded = expandedDifficulty,
onDismissRequest = { expandedDifficulty = false },
onDismissRequest = { viewModel.updateExpandedDifficulty(false) },
modifier = Modifier
.width(with(LocalDensity.current) { size.width.toDp() })
.padding(if(isPortrait) 8.dp else 4.dp)
@ -185,8 +193,8 @@ fun CreateLobbyPage(navController: NavController) {
DropdownMenuItem(
text = { Text(option, color = Colors.Black) },
onClick = {
difficulty = option
expandedDifficulty = false
viewModel.updateDifficulty(option)
viewModel.updateExpandedDifficulty(false)
keyboardController?.hide()
}
)
@ -199,7 +207,7 @@ fun CreateLobbyPage(navController: NavController) {
val chapterOptions = ControllerChapter.getChapters()
TextField(
value = chapter,
onValueChange = { chapter = it },
onValueChange = { viewModel.updatechapter(it) },
readOnly = true,
enabled = false,
colors = TextFieldDefaults.colors(
@ -210,10 +218,10 @@ fun CreateLobbyPage(navController: NavController) {
),
modifier = Modifier
.clickable(onClick = {
expandedChapter = !expandedChapter
viewModel.updateExpandedChapter(!expandedChapter)
})
.onGloballyPositioned {
size = it.size
viewModel.updateSize(it.size)
}
.fillMaxWidth(if (isPortrait) 1f else 0.5f)
.padding(if(isPortrait) 8.dp else 4.dp),
@ -223,14 +231,14 @@ fun CreateLobbyPage(navController: NavController) {
Icons.Default.ArrowDropDown,
contentDescription = null,
Modifier.clickable {
expandedChapter = !expandedChapter
viewModel.updateExpandedChapter(!expandedChapter)
}
)
}
)
DropdownMenu(
expanded = expandedChapter,
onDismissRequest = { expandedChapter = false },
onDismissRequest = { viewModel.updateExpandedChapter(false) },
modifier = Modifier
.width(with(LocalDensity.current) { size.width.toDp() })
.padding(if(isPortrait) 8.dp else 4.dp)
@ -240,8 +248,8 @@ fun CreateLobbyPage(navController: NavController) {
DropdownMenuItem(
text = { Text(option.name, color = Colors.Black) },
onClick = {
chapter = option.name
expandedChapter = false
viewModel.updatechapter( option.name )
viewModel.updateExpandedChapter(false)
keyboardController?.hide()
}
)

@ -91,7 +91,7 @@ fun MultiPage(navController: NavController) {
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// Hide the status bar and navigation bar FERME TA GUEULE !!!
// Hide the status bar and navigation bar
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())

@ -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 }
}
}

@ -17,14 +17,6 @@ class MultiPageViewModel : ViewModel() {
private var lobbyListState = MutableStateFlow<List<Lobby>>(emptyList())
val lobbyList : StateFlow<List<Lobby>> = lobbyListState
/*
var isCreator by rememberSaveable { mutableStateOf(false) }
var playerListInfos: List<Player> by rememberSaveable { mutableStateOf(emptyList()) }
var playerList by rememberSaveable { mutableStateOf(ControllerPlayer.getPlayersIdFromLobbyId(lobbyId.toString()) ?: emptyList()) }
var refreshState by rememberSaveable { mutableStateOf(true) }
*/
fun updateLobbyList() {
this.lobbyListState.update {
ControllerLobby.getLobbies() ?: emptyList()

@ -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…
Cancel
Save