diff --git a/app/src/main/java/com/faraphel/tasks_valider/connectivity/bwd/README.md b/app/src/main/java/com/faraphel/tasks_valider/connectivity/bwd/README.md index 4e0acc5..b94ec29 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/connectivity/bwd/README.md +++ b/app/src/main/java/com/faraphel/tasks_valider/connectivity/bwd/README.md @@ -1,6 +1,6 @@ -# Better WiFi-Direct (BWD) +# Better Wi-Fi Direct (BWD) -This package contain code to improve the base WiFi-Direct implementation. +This package contain code to improve the base Wi-Fi Direct implementation. The base have some issue, like an abusive usage of listener, error code and events that make using it very impractical. diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/selection.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/selection.kt index 91247e1..7f6e353 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/selection.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/selection.kt @@ -18,7 +18,6 @@ import androidx.navigation.compose.rememberNavController import com.faraphel.tasks_valider.database.TaskDatabase -@RequiresApi(Build.VERSION_CODES.O) @Composable fun CommunicationInternetSelectScreen(activity: Activity, database: TaskDatabase) { val controller = rememberNavController() diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/server.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/server.kt index 6d4d179..9021139 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/server.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/internet/server.kt @@ -1,9 +1,7 @@ package com.faraphel.tasks_valider.ui.screen.communication.connection.internet import android.app.Activity -import android.os.Build import android.util.Log -import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.Button @@ -75,7 +73,6 @@ fun CommunicationInternetServerScreen( } -@RequiresApi(Build.VERSION_CODES.O) @Composable fun CommunicationInternetServerContent( database: TaskDatabase, @@ -182,12 +179,7 @@ fun CommunicationInternetServerContent( val session = database.sessionDao().getById(sessionId)!! // TODO(Faraphel): remove, this is a test function - Thread { - populateSubjectSessionPersonTest(database, session) - }.let { thread -> - thread.start() - thread.join() - } + populateSubjectSessionPersonTest(database, session) // Create the server Log.i("room-server", "creating the server") diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/selection.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/selection.kt index 30b967f..896a262 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/selection.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/selection.kt @@ -6,6 +6,7 @@ import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -15,23 +16,20 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import com.faraphel.tasks_valider.connectivity.bwd.BwdManager +import com.faraphel.tasks_valider.database.TaskDatabase @Composable -fun CommunicationWifiP2pScreen(activity: Activity) { +fun CommunicationWifiP2pScreen(activity: Activity, database: TaskDatabase) { val controller = rememberNavController() - var bwdManager: BwdManager? = null - - LaunchedEffect(true) { - // start the BWD manager - bwdManager = BwdManager.fromActivity(activity) - } + // create the Wi-Fi Direct manager + val bwdManager = remember { BwdManager.fromActivity(activity) } NavHost(navController = controller, startDestination = "mode") { composable("mode") { CommunicationWifiP2pSelectContent(controller) } - // composable("client") { CommunicationWifiP2pClientScreen(activity, bwdManager) } - composable("server") { CommunicationWifiP2pServerScreen(activity, bwdManager!!) } + composable("client") { CommunicationWifiP2pClientScreen(activity, bwdManager) } + composable("server") { CommunicationWifiP2pServerScreen(activity, database, bwdManager) } } } diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/server.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/server.kt index 20d428d..36cdf26 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/server.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/connection/wifiP2p/server.kt @@ -1,18 +1,72 @@ package com.faraphel.tasks_valider.ui.screen.communication.connection.wifiP2p import android.app.Activity -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import android.util.Log +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController import com.faraphel.tasks_valider.connectivity.bwd.BwdManager import com.faraphel.tasks_valider.connectivity.task.TaskClient +import com.faraphel.tasks_valider.connectivity.task.TaskServer +import com.faraphel.tasks_valider.database.TaskDatabase +import com.faraphel.tasks_valider.database.entities.ClassEntity +import com.faraphel.tasks_valider.database.entities.PersonEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity +import com.faraphel.tasks_valider.database.populateSubjectSessionPersonTest +import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT +import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT +import com.faraphel.tasks_valider.ui.screen.communication.authentication.AuthenticationServerScreen +import com.faraphel.tasks_valider.ui.screen.communication.connection.internet.CommunicationInternetServerContent +import com.faraphel.tasks_valider.ui.screen.task.TaskSessionController +import java.time.Instant @Composable -fun CommunicationWifiP2pServerScreen(activity: Activity, bwdManager: BwdManager) { +fun CommunicationWifiP2pServerScreen( + activity: Activity, + database: TaskDatabase, + bwdManager: BwdManager +) { + val controller = rememberNavController() + + val adminPersonEntityRaw = remember { mutableStateOf(null) } + val adminPersonEntity = remember { mutableStateOf(null) } val client = remember { mutableStateOf(null) } + NavHost(navController = controller, startDestination = "authentication") { + composable("authentication") { + // if the admin person is not created, prompt the user for the admin information + if (adminPersonEntityRaw.value == null) AuthenticationServerScreen(adminPersonEntityRaw) + else controller.navigate("configuration") + } + composable("configuration") { + if (client.value == null) + CommunicationWifiP2pServerContent( + database, + bwdManager, + adminPersonEntityRaw, + adminPersonEntity, + client, + ) + else controller.navigate("session") + } + composable("session") { + TaskSessionController( + activity, + client.value!!, + adminPersonEntity.value!! + ) + } + } // TODO(Faraphel): fix and get a user // if the server is not created, prompt the user for the server configuration // if (client.value == null) CommunicationWifiP2pServerContent(activity, bwfManager, client) @@ -23,83 +77,115 @@ fun CommunicationWifiP2pServerScreen(activity: Activity, bwdManager: BwdManager) @Composable fun CommunicationWifiP2pServerContent( - activity: Activity, + database: TaskDatabase, bwdManager: BwdManager, + adminPersonEntityRaw: MutableState, + adminPersonEntity: MutableState, client: MutableState ) { - /* - val expandedStudentList = remember { mutableStateOf(false) } - val serverPort = remember { mutableIntStateOf(DEFAULT_SERVER_PORT) } + val classes = remember { mutableStateOf?>(null) } + val selectedClass = remember { mutableStateOf(null) } + val areClassesExpanded = remember { mutableStateOf(false) } - Column { - // student list - Button(onClick = { expandedStudentList.value = !expandedStudentList.value }) { - Text(text = "Select Students List") - } - DropdownMenu( - expanded = expandedStudentList.value, - onDismissRequest = { expandedStudentList.value = false } - ) { - DropdownMenuItem( - text = { Text("ISRI") }, - onClick = {} - ) - DropdownMenuItem( - text = { Text("MIAGE") }, - onClick = {} - ) - // TODO(Faraphel): student lists should be loaded from the database or a file - } + LaunchedEffect(true) { + // refresh the list of classes + Thread { refreshClasses(database, classes) }.start() + } - // server port - TextField( - value = serverPort.intValue.toString(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - onValueChange = { text -> - val port = text.toInt() - if (port in RANGE_SERVER_PORT) { - serverPort.intValue = port - } - } + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + // title + Text( + text = "New Session", + fontSize = 32.sp ) - Button(onClick = { - // TODO(Faraphel): should be merged with the internet server + // separator + Spacer(modifier = Modifier.height(24.dp)) - // Reset the database | TODO(Faraphel): only for testing purpose - activity.deleteDatabase("local") - - // Create the database - val database = Room.databaseBuilder( - activity, - TaskDatabase::class.java, - "local" - ).build() - - // Create the admin - // TODO: the admin should be created from the card reader - val adminPersonEntity = PersonEntity( - "admin", - "admin", - "123456789", - "admin", - - ) - - // Insert the admin in the database - database.personDao().insert(adminPersonEntity) - - bwfManager.recreateGroup { - // Create the server - val server = TaskServer(serverPort.intValue, database, adminPersonEntity) - server.start() - - // Get the client from the server - client.value = server.getAdminClient() + // classes + Row(verticalAlignment = Alignment.CenterVertically) { + // description + Text(text = "Class", fontSize = 12.sp) + // separator + Spacer(modifier = Modifier.width(width = 12.dp)) + // selector + Button(onClick = { areClassesExpanded.value = !areClassesExpanded.value }) { + // display the selected class, if selected + if (selectedClass.value != null) Text(text = selectedClass.value!!.name) + else Text(text = "") + } + + // class selector + DropdownMenu( + expanded = areClassesExpanded.value, + onDismissRequest = { areClassesExpanded.value = false } + ) { + // TODO(Faraphel): student lists should be loaded from the database or a file + classes.value?.forEach { class_ -> + DropdownMenuItem( + text = { Text(class_.name) }, + onClick = { + selectedClass.value = class_ + areClassesExpanded.value = false + } + ) + } } - }) { - Text("Create") } + + // check if a class is selected + if (selectedClass.value != null) + // button to create the server + Button(onClick = { + Thread { // a thread is used for networking + // Insert the admin in the database and get its id + val adminPersonEntityId = database.personDao().insert(adminPersonEntityRaw.value!!) + adminPersonEntity.value = database.personDao().getById(adminPersonEntityId)!! + + // Create a new session + // TODO(Faraphel): name + val sessionId = database.sessionDao().insert( + SessionEntity( + name="NOM", + start= Instant.now(), + classId=selectedClass.value!!.id, + ) + ) + val session = database.sessionDao().getById(sessionId)!! + + // TODO(Faraphel): remove, this is a test function + populateSubjectSessionPersonTest(database, session) + + // create a new Wi-Fi Direct group + bwdManager.recreateGroup { + // Create the server + Log.i("room-server", "creating the server") + val server = TaskServer( + DEFAULT_SERVER_PORT, + database, + session, + adminPersonEntity.value!!, + ) + server.start() + + // Get the client from the server + client.value = server.getAdminClient() + } + }.start() + }) { + Text("Create") + } } - */ -} \ No newline at end of file +} + + +/** + * Refresh the list of classes + */ +fun refreshClasses(database: TaskDatabase, classes: MutableState?>) { + classes.value = database.classDao().getAll() +} diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt index 5190732..86aedf3 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt @@ -46,7 +46,7 @@ fun CommunicationModeSelectionScreen(activity: Activity, database: TaskDatabase) CommunicationInternetSelectScreen(activity, database) } composable("wifi-p2p") { - CommunicationWifiP2pScreen(activity) + CommunicationWifiP2pScreen(activity, database) } } }