implemented a better API for the client and the quick validation system
This commit is contained in:
parent
48a3932f64
commit
e12339abb5
58 changed files with 675 additions and 323 deletions
|
@ -7,14 +7,14 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
import com.faraphel.tasks_valider.connectivity.bwd.BwdManager
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
import com.faraphel.tasks_valider.database.populateTaskDatabaseTest
|
import com.faraphel.tasks_valider.database.populateTaskDatabaseTest
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.CommunicationModeSelectionScreen
|
import com.faraphel.tasks_valider.ui.screen.communication.CommunicationModeSelectionScreen
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private var bwfManager: BwfManager? = null ///< the WiFi-Direct helper
|
private var bwdManager: BwdManager? = null ///< the WiFi-Direct helper
|
||||||
private lateinit var database: TaskDatabase ///< the database manager
|
private lateinit var database: TaskDatabase ///< the database manager
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@ -50,13 +50,13 @@ class MainActivity : ComponentActivity() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
// enable the WiFi-Direct events
|
// enable the WiFi-Direct events
|
||||||
this.registerReceiver(this.bwfManager, BwfManager.ALL_INTENT_FILTER)
|
this.registerReceiver(this.bwdManager, BwdManager.ALL_INTENT_FILTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
|
||||||
// disable the WiFi-Direct events
|
// disable the WiFi-Direct events
|
||||||
this.unregisterReceiver(this.bwfManager)
|
this.unregisterReceiver(this.bwdManager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf
|
package com.faraphel.tasks_valider.connectivity.bwd
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
@ -10,7 +10,7 @@ import android.content.pm.PackageManager
|
||||||
import android.net.wifi.p2p.*
|
import android.net.wifi.p2p.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import com.faraphel.tasks_valider.connectivity.bwf.error.*
|
import com.faraphel.tasks_valider.connectivity.bwd.error.*
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ import com.faraphel.tasks_valider.connectivity.bwf.error.*
|
||||||
* @param manager The WiFi-Direct manager
|
* @param manager The WiFi-Direct manager
|
||||||
* @param channel The WiFi-Direct channel
|
* @param channel The WiFi-Direct channel
|
||||||
*/
|
*/
|
||||||
class BwfManager(
|
class BwdManager(
|
||||||
private var manager: WifiP2pManager,
|
private var manager: WifiP2pManager,
|
||||||
private var channel: WifiP2pManager.Channel,
|
private var channel: WifiP2pManager.Channel,
|
||||||
) : BroadcastReceiver() {
|
) : BroadcastReceiver() {
|
||||||
|
@ -41,11 +41,11 @@ class BwfManager(
|
||||||
* Create a new BwfManager from an activity.
|
* Create a new BwfManager from an activity.
|
||||||
* @param activity The activity to create the manager from
|
* @param activity The activity to create the manager from
|
||||||
*/
|
*/
|
||||||
fun fromActivity(activity: Activity): BwfManager {
|
fun fromActivity(activity: Activity): BwdManager {
|
||||||
// check if the system support WiFi-Direct
|
// check if the system support WiFi-Direct
|
||||||
if (this.isSupported(activity)) {
|
if (this.isSupported(activity)) {
|
||||||
Log.e("wifi-p2p", "this device does not support the WiFi-Direct feature")
|
Log.e("wifi-p2p", "this device does not support the WiFi-Direct feature")
|
||||||
throw BwfNotSupportedException()
|
throw BwdNotSupportedException()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Faraphel): more check on permissions
|
// TODO(Faraphel): more check on permissions
|
||||||
|
@ -62,11 +62,11 @@ class BwfManager(
|
||||||
|
|
||||||
// get the WiFi-Direct manager
|
// get the WiFi-Direct manager
|
||||||
val manager = activity.getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager?
|
val manager = activity.getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager?
|
||||||
?: throw BwfPermissionException()
|
?: throw BwdPermissionException()
|
||||||
|
|
||||||
// get the WiFi-Direct channel
|
// get the WiFi-Direct channel
|
||||||
val channel = manager.initialize(activity, activity.mainLooper, null)
|
val channel = manager.initialize(activity, activity.mainLooper, null)
|
||||||
return BwfManager(manager, channel)
|
return BwdManager(manager, channel)
|
||||||
|
|
||||||
// NOTE(Faraphel): the broadcast receiver should be registered in the activity onResume
|
// NOTE(Faraphel): the broadcast receiver should be registered in the activity onResume
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class BwfManager(
|
||||||
fun connect(config: WifiP2pConfig, callback: () -> Unit = {}) =
|
fun connect(config: WifiP2pConfig, callback: () -> Unit = {}) =
|
||||||
this.manager.connect(this.channel, config, object : WifiP2pManager.ActionListener {
|
this.manager.connect(this.channel, config, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() { callback() }
|
override fun onSuccess() { callback() }
|
||||||
override fun onFailure(reason: Int) = throw BwfConnectException(reason)
|
override fun onFailure(reason: Int) = throw BwdConnectException(reason)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +105,7 @@ class BwfManager(
|
||||||
fun discoverPeers(callback: () -> Unit = {}) =
|
fun discoverPeers(callback: () -> Unit = {}) =
|
||||||
this.manager.discoverPeers(this.channel, object : WifiP2pManager.ActionListener {
|
this.manager.discoverPeers(this.channel, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() { callback() }
|
override fun onSuccess() { callback() }
|
||||||
override fun onFailure(reason: Int) = throw BwfDiscoverException(reason)
|
override fun onFailure(reason: Int) = throw BwdDiscoverException(reason)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,7 +133,7 @@ class BwfManager(
|
||||||
fun createGroup(callback: () -> Unit = {}) =
|
fun createGroup(callback: () -> Unit = {}) =
|
||||||
this.manager.createGroup(this.channel, object : WifiP2pManager.ActionListener {
|
this.manager.createGroup(this.channel, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() { callback() }
|
override fun onSuccess() { callback() }
|
||||||
override fun onFailure(reason: Int) = throw BwfCreateGroupException(reason)
|
override fun onFailure(reason: Int) = throw BwdCreateGroupException(reason)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,7 +143,7 @@ class BwfManager(
|
||||||
fun removeGroup(callback: () -> Unit = {}) =
|
fun removeGroup(callback: () -> Unit = {}) =
|
||||||
this.manager.removeGroup(this.channel, object : WifiP2pManager.ActionListener {
|
this.manager.removeGroup(this.channel, object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() { callback() }
|
override fun onSuccess() { callback() }
|
||||||
override fun onFailure(reason: Int) = throw BwfRemoveGroupException(reason)
|
override fun onFailure(reason: Int) = throw BwdRemoveGroupException(reason)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,7 +161,7 @@ class BwfManager(
|
||||||
this.requestGroupInfo { group ->
|
this.requestGroupInfo { group ->
|
||||||
// if a group exist, quit it
|
// if a group exist, quit it
|
||||||
if (group != null)
|
if (group != null)
|
||||||
this.removeGroup { this@BwfManager.createGroup(callback) }
|
this.removeGroup { this@BwdManager.createGroup(callback) }
|
||||||
else
|
else
|
||||||
// create the group
|
// create the group
|
||||||
this.createGroup(callback)
|
this.createGroup(callback)
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdConnectException(
|
||||||
|
reason: Int
|
||||||
|
) : BwdException("Cannot connect to the peer. Reason: $reason")
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdCreateGroupException (
|
||||||
|
reason: Int
|
||||||
|
) : BwdException("Could not create the group : $reason")
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdDiscoverException(
|
||||||
|
reason: Int
|
||||||
|
) : BwdException("Could not discover peers : $reason")
|
|
@ -1,9 +1,9 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Exception for everything concerning the WifiP2pHelper class
|
* Base Exception for everything concerning the WifiP2pHelper class
|
||||||
*/
|
*/
|
||||||
open class BwfException(
|
open class BwdException(
|
||||||
override val message: String?
|
override val message: String?
|
||||||
) : Exception(message)
|
) : Exception(message)
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdInvalidActionException(
|
||||||
|
action: String
|
||||||
|
) : BwdException("This WiFi-Direct action is not supported : $action")
|
|
@ -0,0 +1,4 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdNotSupportedException :
|
||||||
|
BwdException("WiFi-Direct is not supported on this device.")
|
|
@ -0,0 +1,4 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdPermissionException :
|
||||||
|
BwdException("WiFi-Direct requires permissions to work properly. Please grant the permissions.")
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.faraphel.tasks_valider.connectivity.bwd.error
|
||||||
|
|
||||||
|
class BwdRemoveGroupException (
|
||||||
|
reason: Int
|
||||||
|
) : BwdException("Could not remove the group : $reason")
|
|
@ -1,5 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfConnectException(
|
|
||||||
reason: Int
|
|
||||||
) : BwfException("Cannot connect to the peer. Reason: $reason")
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfCreateGroupException (
|
|
||||||
reason: Int
|
|
||||||
) : BwfException("Could not create the group : $reason")
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfDiscoverException(
|
|
||||||
reason: Int
|
|
||||||
) : BwfException("Could not discover peers : $reason")
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfInvalidActionException(
|
|
||||||
action: String
|
|
||||||
) : BwfException("This WiFi-Direct action is not supported : $action")
|
|
|
@ -1,4 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfNotSupportedException :
|
|
||||||
BwfException("WiFi-Direct is not supported on this device.")
|
|
|
@ -1,4 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfPermissionException :
|
|
||||||
BwfException("WiFi-Direct requires permissions to work properly. Please grant the permissions.")
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.bwf.error
|
|
||||||
|
|
||||||
class BwfRemoveGroupException (
|
|
||||||
reason: Int
|
|
||||||
) : BwfException("Could not remove the group : $reason")
|
|
|
@ -1,16 +1,11 @@
|
||||||
package com.faraphel.tasks_valider.connectivity.task
|
package com.faraphel.tasks_valider.connectivity.task
|
||||||
|
|
||||||
import okhttp3.HttpUrl
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import com.faraphel.tasks_valider.database.api.client.entities.*
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import kotlin.time.Duration
|
|
||||||
import kotlin.time.Duration.Companion.seconds
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client to handle the room connection.
|
* A client to handle the room connection and access the API
|
||||||
* @param address the address of the server
|
* @param address the address of the server
|
||||||
* @param port the port of the server
|
* @param port the port of the server
|
||||||
* @param baseCookies list of cookies to use (optional)
|
* @param baseCookies list of cookies to use (optional)
|
||||||
|
@ -20,86 +15,15 @@ class TaskClient(
|
||||||
private val port: Int,
|
private val port: Int,
|
||||||
private val baseCookies: List<okhttp3.Cookie> = listOf()
|
private val baseCookies: List<okhttp3.Cookie> = listOf()
|
||||||
) {
|
) {
|
||||||
private val baseUrl = "http://$address:$port"
|
private val httpClient = TaskEntityHttpClient(address, port, baseCookies)
|
||||||
private val client = OkHttpClient().newBuilder()
|
|
||||||
.cookieJar(
|
|
||||||
// TODO(Faraphel): should be moved into another object
|
|
||||||
object : okhttp3.CookieJar {
|
|
||||||
private val cookies = baseCookies.toMutableList() ///< list of cookies
|
|
||||||
|
|
||||||
override fun loadForRequest(url: HttpUrl): List<okhttp3.Cookie> {
|
val clientApi = ClassClientApi(httpClient)
|
||||||
return this.cookies
|
val personApi = PersonClientApi(httpClient)
|
||||||
}
|
val sessionApi = SessionClientApi(httpClient)
|
||||||
override fun saveFromResponse(url: HttpUrl, cookies: List<okhttp3.Cookie>) {
|
val subjectApi = SubjectClientApi(httpClient)
|
||||||
this.cookies.addAll(cookies)
|
val taskApi = TaskClientApi(httpClient)
|
||||||
}
|
val validationApi = ValidationClientApi(httpClient)
|
||||||
}
|
|
||||||
).callTimeout(30.seconds)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// TODO(Faraphel): automatically convert content to the correct type ?
|
val relationClassPersonApi = RelationClassPersonClientApi(httpClient)
|
||||||
|
val relationPersonSessionSubjectApi = RelationPersonSessionSubjectClientApi(httpClient)
|
||||||
/**
|
|
||||||
* Return a basic request to the server
|
|
||||||
* @param endpoint the endpoint of the server
|
|
||||||
*/
|
|
||||||
private fun baseRequestBuilder(endpoint: String): okhttp3.Request.Builder =
|
|
||||||
okhttp3.Request.Builder().url("$baseUrl/$endpoint")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a HEAD request
|
|
||||||
* @param endpoint the endpoint of the server
|
|
||||||
*/
|
|
||||||
fun head(endpoint: String): okhttp3.Request =
|
|
||||||
this.baseRequestBuilder(endpoint).head().build()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a GET request
|
|
||||||
* @param endpoint the endpoint of the server
|
|
||||||
*/
|
|
||||||
fun get(endpoint: String): okhttp3.Response =
|
|
||||||
this.client.newCall(
|
|
||||||
this.baseRequestBuilder(endpoint)
|
|
||||||
.get()
|
|
||||||
.build()
|
|
||||||
).execute()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a POST request
|
|
||||||
* @param endpoint the endpoint of the server
|
|
||||||
* @param content the content of the request
|
|
||||||
* @param type the type of the content
|
|
||||||
*/
|
|
||||||
fun post(endpoint: String, content: String, type: String = "text/plain"): okhttp3.Response =
|
|
||||||
this.client.newCall(
|
|
||||||
this.baseRequestBuilder(endpoint)
|
|
||||||
.post(content.toRequestBody(type.toMediaType()))
|
|
||||||
.build()
|
|
||||||
).execute()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a PATCH request
|
|
||||||
* @param endpoint the endpoint of the server
|
|
||||||
* @param content the content of the request
|
|
||||||
* @param type the type of the content
|
|
||||||
*/
|
|
||||||
fun patch(endpoint: String, content: String, type: String = "text/plain"): okhttp3.Response =
|
|
||||||
this.client.newCall(
|
|
||||||
this.baseRequestBuilder(endpoint)
|
|
||||||
.patch(content.toRequestBody(type.toMediaType()))
|
|
||||||
.build()
|
|
||||||
).execute()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a DELETE request
|
|
||||||
* @param endpoint the endpoint of the server
|
|
||||||
* @param content the content of the request
|
|
||||||
* @param type the type of the content
|
|
||||||
*/
|
|
||||||
fun delete(endpoint: String, content: String, type: String = "text/plain"): okhttp3.Response =
|
|
||||||
this.client.newCall(
|
|
||||||
this.baseRequestBuilder(endpoint)
|
|
||||||
.delete(content.toRequestBody(type.toMediaType()))
|
|
||||||
.build()
|
|
||||||
).execute()
|
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ package com.faraphel.tasks_valider.connectivity.task
|
||||||
import com.faraphel.tasks_valider.connectivity.task.api.TaskSessionManagerApi
|
import com.faraphel.tasks_valider.connectivity.task.api.TaskSessionManagerApi
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
import com.faraphel.tasks_valider.database.api.TaskDatabaseApi
|
import com.faraphel.tasks_valider.database.api.server.DatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
@ -23,7 +23,7 @@ class TaskServer(
|
||||||
private val adminPersonEntity: PersonEntity,
|
private val adminPersonEntity: PersonEntity,
|
||||||
) : NanoHTTPD(port) {
|
) : NanoHTTPD(port) {
|
||||||
private val sessionManager = TaskSessionManager(adminPersonEntity) ///< the session manager
|
private val sessionManager = TaskSessionManager(adminPersonEntity) ///< the session manager
|
||||||
private val databaseApi = TaskDatabaseApi(this.database, session) ///< the api of the database
|
private val databaseApi = DatabaseApi(this.database, session) ///< the api of the database
|
||||||
private val sessionManagerApi = TaskSessionManagerApi(this.sessionManager, this.database) ///< the api of the session manager
|
private val sessionManagerApi = TaskSessionManagerApi(this.sessionManager, this.database) ///< the api of the session manager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.faraphel.tasks_valider.database
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
import com.faraphel.tasks_valider.database.converters.InstantConverter
|
import com.faraphel.tasks_valider.utils.converters.InstantConverter
|
||||||
import com.faraphel.tasks_valider.database.dao.*
|
import com.faraphel.tasks_valider.database.dao.*
|
||||||
import com.faraphel.tasks_valider.database.entities.*
|
import com.faraphel.tasks_valider.database.entities.*
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An HTTP client to handle the room connection.
|
||||||
|
* @param address the address of the server
|
||||||
|
* @param port the port of the server
|
||||||
|
* @param baseCookies list of cookies to use (optional)
|
||||||
|
*/
|
||||||
|
class TaskEntityHttpClient(
|
||||||
|
private val address: String,
|
||||||
|
private val port: Int,
|
||||||
|
private val baseCookies: List<okhttp3.Cookie> = listOf()
|
||||||
|
) {
|
||||||
|
// the base url for the server
|
||||||
|
private val baseUrl = "http://$address:$port"
|
||||||
|
// the HTTP client
|
||||||
|
private val client = OkHttpClient().newBuilder()
|
||||||
|
.cookieJar(
|
||||||
|
object : okhttp3.CookieJar {
|
||||||
|
private val cookies = baseCookies.toMutableList() ///< list of cookies
|
||||||
|
override fun loadForRequest(url: HttpUrl) = this.cookies
|
||||||
|
override fun saveFromResponse(url: HttpUrl, cookies: List<okhttp3.Cookie>) { this.cookies.addAll(cookies) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.callTimeout(30.seconds)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a basic request to the server
|
||||||
|
* @param endpoint the endpoint of the server
|
||||||
|
*/
|
||||||
|
private fun baseRequestBuilder(endpoint: String): okhttp3.Request.Builder =
|
||||||
|
okhttp3.Request.Builder().url("$baseUrl/$endpoint")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a HEAD request
|
||||||
|
* @param endpoint the endpoint of the server
|
||||||
|
*/
|
||||||
|
fun head(endpoint: String): okhttp3.Request =
|
||||||
|
this.baseRequestBuilder(endpoint).head().build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a GET request
|
||||||
|
* @param endpoint the endpoint of the server
|
||||||
|
*/
|
||||||
|
fun get(endpoint: String): okhttp3.Response =
|
||||||
|
this.client.newCall(
|
||||||
|
this.baseRequestBuilder(endpoint)
|
||||||
|
.get()
|
||||||
|
.build()
|
||||||
|
).execute()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a POST request
|
||||||
|
* @param endpoint the endpoint of the server
|
||||||
|
* @param content the content of the request
|
||||||
|
* @param type the type of the content
|
||||||
|
*/
|
||||||
|
fun post(endpoint: String, content: String, type: String = "text/plain"): okhttp3.Response =
|
||||||
|
this.client.newCall(
|
||||||
|
this.baseRequestBuilder(endpoint)
|
||||||
|
.post(content.toRequestBody(type.toMediaType()))
|
||||||
|
.build()
|
||||||
|
).execute()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a PATCH request
|
||||||
|
* @param endpoint the endpoint of the server
|
||||||
|
* @param content the content of the request
|
||||||
|
* @param type the type of the content
|
||||||
|
*/
|
||||||
|
fun patch(endpoint: String, content: String, type: String = "text/plain"): okhttp3.Response =
|
||||||
|
this.client.newCall(
|
||||||
|
this.baseRequestBuilder(endpoint)
|
||||||
|
.patch(content.toRequestBody(type.toMediaType()))
|
||||||
|
.build()
|
||||||
|
).execute()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a DELETE request
|
||||||
|
* @param endpoint the endpoint of the server
|
||||||
|
* @param content the content of the request
|
||||||
|
* @param type the type of the content
|
||||||
|
*/
|
||||||
|
fun delete(endpoint: String, content: String, type: String = "text/plain"): okhttp3.Response =
|
||||||
|
this.client.newCall(
|
||||||
|
this.baseRequestBuilder(endpoint)
|
||||||
|
.delete(content.toRequestBody(type.toMediaType()))
|
||||||
|
.build()
|
||||||
|
).execute()
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||||
|
|
||||||
|
|
||||||
|
class ClassClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<ClassEntity>(
|
||||||
|
client,
|
||||||
|
ClassEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||||
|
|
||||||
|
|
||||||
|
class PersonClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<PersonEntity>(
|
||||||
|
client,
|
||||||
|
PersonEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
||||||
|
|
||||||
|
|
||||||
|
class RelationClassPersonClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<RelationClassPersonEntity>(
|
||||||
|
client,
|
||||||
|
RelationClassPersonEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||||
|
|
||||||
|
|
||||||
|
class RelationPersonSessionSubjectClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<RelationPersonSessionSubjectEntity>(
|
||||||
|
client,
|
||||||
|
RelationPersonSessionSubjectEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
|
||||||
|
|
||||||
|
class SessionClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<SessionEntity>(
|
||||||
|
client,
|
||||||
|
SessionEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
||||||
|
|
||||||
|
|
||||||
|
class SubjectClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<SubjectEntity>(
|
||||||
|
client,
|
||||||
|
SubjectEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||||
|
|
||||||
|
|
||||||
|
class TaskClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<TaskEntity>(
|
||||||
|
client,
|
||||||
|
TaskEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities
|
||||||
|
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.entities.base.BaseClientApi
|
||||||
|
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationClientApi(
|
||||||
|
client: TaskEntityHttpClient,
|
||||||
|
) : BaseClientApi<ValidationEntity>(
|
||||||
|
client,
|
||||||
|
ValidationEntity::class
|
||||||
|
)
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.faraphel.tasks_valider.database.api.client.entities.base;
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.faraphel.tasks_valider.database.api.client.TaskEntityHttpClient
|
||||||
|
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
||||||
|
import com.faraphel.tasks_valider.database.entities.error.HttpException
|
||||||
|
import com.faraphel.tasks_valider.utils.parser
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.full.companionObject
|
||||||
|
import kotlin.reflect.full.companionObjectInstance
|
||||||
|
import kotlin.reflect.full.declaredMemberProperties
|
||||||
|
|
||||||
|
|
||||||
|
abstract class BaseClientApi<Entity: BaseEntity>(
|
||||||
|
private val client: TaskEntityHttpClient,
|
||||||
|
private val entityType: KClass<Entity>,
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* return the API endpoint for this entity
|
||||||
|
* @return the API endpoint for this entity
|
||||||
|
*/
|
||||||
|
private fun getEndpoint(): String {
|
||||||
|
// get the property for the name of the table
|
||||||
|
val propertyTableName = entityType.companionObject!!.declaredMemberProperties.first { member ->
|
||||||
|
member.name == "TABLE_NAME"
|
||||||
|
}
|
||||||
|
// get the table name by calling the getter of the property
|
||||||
|
val tableName = propertyTableName.getter.call(entityType.companionObjectInstance)
|
||||||
|
// return the endpoint
|
||||||
|
return "entities/${tableName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return all the entities for that table
|
||||||
|
* @return all the entities for that table
|
||||||
|
* @throws java.io.IOException reading error while parsing request
|
||||||
|
* @throws HttpException error of the request
|
||||||
|
*/
|
||||||
|
fun getAll(): List<Entity> {
|
||||||
|
// try to obtain the list of validations
|
||||||
|
Log.i("base-api", this.getEndpoint())
|
||||||
|
val response = client.get(this.getEndpoint())
|
||||||
|
|
||||||
|
// in case of error, notify it
|
||||||
|
if (!response.isSuccessful)
|
||||||
|
throw HttpException(response.code)
|
||||||
|
|
||||||
|
val data = response.body.string()
|
||||||
|
Log.i("base-api", data)
|
||||||
|
|
||||||
|
// parse the list of validations
|
||||||
|
return parser.fromJson(
|
||||||
|
data,
|
||||||
|
TypeToken.getParameterized(ArrayList::class.java, entityType.java).type
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create a new entity in the table
|
||||||
|
* @return the id of the object in the database
|
||||||
|
* @throws java.io.IOException reading error while parsing request
|
||||||
|
* @throws HttpException error of the request
|
||||||
|
*/
|
||||||
|
fun save(entity: Entity): Long {
|
||||||
|
// try to send the serialized entity as json
|
||||||
|
val response = client.post(
|
||||||
|
this.getEndpoint(),
|
||||||
|
parser.toJson(entity),
|
||||||
|
"application/json; charset=utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// in case of error, notify it
|
||||||
|
if (!response.isSuccessful)
|
||||||
|
throw HttpException(response.code)
|
||||||
|
|
||||||
|
// return the id of the object
|
||||||
|
return response.body.string().toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete an entity in the table
|
||||||
|
* @return the number of object deleted in the database
|
||||||
|
* @throws java.io.IOException reading error while parsing request
|
||||||
|
* @throws HttpException error of the request
|
||||||
|
*/
|
||||||
|
fun delete(entity: Entity): Long {
|
||||||
|
// try to delete the object
|
||||||
|
val response = client.delete(
|
||||||
|
this.getEndpoint(),
|
||||||
|
parser.toJson(entity),
|
||||||
|
"application/json; charset=utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// in case of error, notify it
|
||||||
|
if (!response.isSuccessful)
|
||||||
|
throw HttpException(response.code)
|
||||||
|
|
||||||
|
// return the id of the object
|
||||||
|
return response.body.string().toLong()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +1,28 @@
|
||||||
package com.faraphel.tasks_valider.database.api
|
package com.faraphel.tasks_valider.database.api.server
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
||||||
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
import com.faraphel.tasks_valider.database.api.entities.*
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseApi
|
import com.faraphel.tasks_valider.database.api.server.entities.*
|
||||||
import com.faraphel.tasks_valider.database.entities.*
|
import com.faraphel.tasks_valider.database.entities.*
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
class TaskDatabaseApi(
|
|
||||||
|
class DatabaseApi(
|
||||||
private val database: TaskDatabase,
|
private val database: TaskDatabase,
|
||||||
private val session: SessionEntity,
|
private val session: SessionEntity,
|
||||||
) {
|
) {
|
||||||
private val api: Map<String, BaseApi> = mapOf(
|
private val api: Map<String, BaseDatabaseApi> = mapOf(
|
||||||
ClassEntity.TABLE_NAME to ClassApi(this.database.classDao(), session),
|
ClassEntity.TABLE_NAME to ClassDatabaseApi(this.database.classDao(), session),
|
||||||
PersonEntity.TABLE_NAME to PersonApi(this.database.personDao(), session),
|
PersonEntity.TABLE_NAME to PersonDatabaseApi(this.database.personDao(), session),
|
||||||
SessionEntity.TABLE_NAME to SessionApi(this.database.sessionDao(), session),
|
SessionEntity.TABLE_NAME to SessionDatabaseApi(this.database.sessionDao(), session),
|
||||||
SubjectEntity.TABLE_NAME to SubjectApi(this.database.subjectDao(), session),
|
SubjectEntity.TABLE_NAME to SubjectDatabaseApi(this.database.subjectDao(), session),
|
||||||
TaskEntity.TABLE_NAME to TaskApi(this.database.taskDao(), session),
|
TaskEntity.TABLE_NAME to TaskDatabaseApi(database.taskDao(), session),
|
||||||
ValidationEntity.TABLE_NAME to ValidationApi(this.database.validationDao(), session),
|
ValidationEntity.TABLE_NAME to ValidationDatabaseApi(this.database.validationDao(), session),
|
||||||
|
|
||||||
RelationClassPersonEntity.TABLE_NAME to RelationClassPersonApi(this.database.relationClassPersonDao(), session),
|
RelationClassPersonEntity.TABLE_NAME to RelationClassPersonDatabaseApi(this.database.relationClassPersonDao(), session),
|
||||||
RelationPersonSessionSubjectEntity.TABLE_NAME to RelationPersonSessionSubjectApi(this.database.relationPersonSessionSubjectDao(), session),
|
RelationPersonSessionSubjectEntity.TABLE_NAME to RelationPersonSessionSubjectDatabaseApi(this.database.relationPersonSessionSubjectDao(), session),
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
|
||||||
|
|
||||||
class ClassApi(
|
class ClassDatabaseApi(
|
||||||
dao: BaseTaskDao<ClassEntity>,
|
dao: BaseTaskDao<ClassEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<ClassEntity>(
|
) : BaseTaskDatabaseApi<ClassEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
ClassEntity::class.java
|
ClassEntity::class.java
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
|
||||||
|
|
||||||
class PersonApi(
|
class PersonDatabaseApi(
|
||||||
dao: BaseTaskDao<PersonEntity>,
|
dao: BaseTaskDao<PersonEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<PersonEntity>(
|
) : BaseTaskDatabaseApi<PersonEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
PersonEntity::class.java
|
PersonEntity::class.java
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
|
||||||
|
|
||||||
class RelationClassPersonApi(
|
class RelationClassPersonDatabaseApi(
|
||||||
dao: BaseTaskDao<RelationClassPersonEntity>,
|
dao: BaseTaskDao<RelationClassPersonEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<RelationClassPersonEntity>(
|
) : BaseTaskDatabaseApi<RelationClassPersonEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
RelationClassPersonEntity::class.java
|
RelationClassPersonEntity::class.java
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
|
||||||
|
|
||||||
class RelationPersonSessionSubjectApi(
|
class RelationPersonSessionSubjectDatabaseApi(
|
||||||
dao: BaseTaskDao<RelationPersonSessionSubjectEntity>,
|
dao: BaseTaskDao<RelationPersonSessionSubjectEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<RelationPersonSessionSubjectEntity>(
|
) : BaseTaskDatabaseApi<RelationPersonSessionSubjectEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
RelationPersonSessionSubjectEntity::class.java
|
RelationPersonSessionSubjectEntity::class.java
|
|
@ -1,14 +1,14 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
|
||||||
|
|
||||||
class SessionApi(
|
class SessionDatabaseApi(
|
||||||
dao: BaseTaskDao<SessionEntity>,
|
dao: BaseTaskDao<SessionEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<SessionEntity>(
|
) : BaseTaskDatabaseApi<SessionEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
SessionEntity::class.java
|
SessionEntity::class.java
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
||||||
|
|
||||||
|
|
||||||
class SubjectApi(
|
class SubjectDatabaseApi(
|
||||||
dao: BaseTaskDao<SubjectEntity>,
|
dao: BaseTaskDao<SubjectEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<SubjectEntity>(
|
) : BaseTaskDatabaseApi<SubjectEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
SubjectEntity::class.java
|
SubjectEntity::class.java
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||||
|
|
||||||
|
|
||||||
class TaskApi(
|
class TaskDatabaseApi(
|
||||||
dao: BaseTaskDao<TaskEntity>,
|
dao: BaseTaskDao<TaskEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<TaskEntity>(
|
) : BaseTaskDatabaseApi<TaskEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
TaskEntity::class.java
|
TaskEntity::class.java
|
|
@ -1,15 +1,15 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities
|
package com.faraphel.tasks_valider.database.api.server.entities
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
import com.faraphel.tasks_valider.database.api.server.entities.base.BaseTaskDatabaseApi
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||||
|
|
||||||
|
|
||||||
class ValidationApi(
|
class ValidationDatabaseApi(
|
||||||
dao: BaseTaskDao<ValidationEntity>,
|
dao: BaseTaskDao<ValidationEntity>,
|
||||||
session: SessionEntity
|
session: SessionEntity
|
||||||
) : BaseTaskApi<ValidationEntity>(
|
) : BaseTaskDatabaseApi<ValidationEntity>(
|
||||||
dao,
|
dao,
|
||||||
session,
|
session,
|
||||||
ValidationEntity::class.java
|
ValidationEntity::class.java
|
|
@ -1,11 +1,11 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities.base
|
package com.faraphel.tasks_valider.database.api.server.entities.base
|
||||||
|
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base for the API to handle the database operations with an HTTP server.
|
* A base for the API to handle the database operations with an HTTP server.
|
||||||
*/
|
*/
|
||||||
interface BaseApi {
|
interface BaseDatabaseApi {
|
||||||
/**
|
/**
|
||||||
* Handle the HEAD request
|
* Handle the HEAD request
|
||||||
* This is used to check if a data exists in the database
|
* This is used to check if a data exists in the database
|
|
@ -1,4 +1,4 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities.base
|
package com.faraphel.tasks_valider.database.api.server.entities.base
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
@ -7,14 +7,11 @@ import com.faraphel.tasks_valider.utils.parser
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseTaskApi<Entity> (
|
abstract class BaseTaskDatabaseApi<Entity> (
|
||||||
private val dao: BaseTaskDao<Entity>,
|
private val dao: BaseTaskDao<Entity>,
|
||||||
private val session: SessionEntity,
|
private val session: SessionEntity,
|
||||||
private val entityType: Class<Entity>,
|
private val entityType: Class<Entity>,
|
||||||
) : BaseApi {
|
) : BaseDatabaseApi {
|
||||||
private fun parseJson(data: String): Entity =
|
|
||||||
parser.fromJson(data, entityType)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an HTTP HEAD request.
|
* Handle an HTTP HEAD request.
|
||||||
* Indicate if an object exist in the database.
|
* Indicate if an object exist in the database.
|
||||||
|
@ -25,7 +22,7 @@ abstract class BaseTaskApi<Entity> (
|
||||||
// get the content of the request
|
// get the content of the request
|
||||||
val data = httpSession.getBody()
|
val data = httpSession.getBody()
|
||||||
// parse the object
|
// parse the object
|
||||||
val obj = this.parseJson(data)
|
val obj = parser.fromJson(data, entityType)
|
||||||
// check if the object is in the object accessible from the session
|
// check if the object is in the object accessible from the session
|
||||||
val exists = this.dao.getAllBySession(session.id).contains(obj)
|
val exists = this.dao.getAllBySession(session.id).contains(obj)
|
||||||
|
|
|
@ -35,13 +35,28 @@ import java.time.Instant
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
data class ValidationEntity (
|
data class ValidationEntity (
|
||||||
@ColumnInfo("date") val date: Instant,
|
|
||||||
|
|
||||||
@ColumnInfo("teacher_id", index = true) val teacherId: Long,
|
@ColumnInfo("teacher_id", index = true) val teacherId: Long,
|
||||||
@ColumnInfo("student_id", index = true) val studentId: Long,
|
@ColumnInfo("student_id", index = true) val studentId: Long,
|
||||||
@ColumnInfo("task_id", index = true) val taskId: Long,
|
@ColumnInfo("task_id", index = true) val taskId: Long,
|
||||||
|
|
||||||
|
@ColumnInfo("date") val date: Instant,
|
||||||
) : BaseEntity() {
|
) : BaseEntity() {
|
||||||
companion object {
|
companion object {
|
||||||
const val TABLE_NAME = "validations"
|
const val TABLE_NAME = "validations"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new ValidationEntity. Automatically set the date to today.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
teacherId: Long,
|
||||||
|
studentId: Long,
|
||||||
|
taskId: Long
|
||||||
|
):
|
||||||
|
this(
|
||||||
|
teacherId = teacherId,
|
||||||
|
studentId = studentId,
|
||||||
|
taskId = taskId,
|
||||||
|
date = Instant.now()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
package com.faraphel.tasks_valider.database.entities.base
|
package com.faraphel.tasks_valider.database.entities.base
|
||||||
|
|
||||||
open class BaseEntity
|
open class BaseEntity {
|
||||||
|
companion object {
|
||||||
|
const val TABLE_NAME = "<Undefined>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.faraphel.tasks_valider.database.entities.error
|
||||||
|
|
||||||
|
|
||||||
|
class HttpException(
|
||||||
|
private val code: Int,
|
||||||
|
) : Exception("Http Exception: $code")
|
|
@ -24,7 +24,7 @@ fun populateTaskDatabaseTest(database: TaskDatabase) {
|
||||||
) = database.personDao().insert(
|
) = database.personDao().insert(
|
||||||
PersonEntity(
|
PersonEntity(
|
||||||
"Billy", "Bob",
|
"Billy", "Bob",
|
||||||
null,
|
"0A1A7553-9DE5-103C-B23C-630998207116",
|
||||||
"1234",
|
"1234",
|
||||||
TaskRole.STUDENT
|
TaskRole.STUDENT
|
||||||
),
|
),
|
||||||
|
|
|
@ -18,7 +18,6 @@ import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_ADDRESS
|
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_ADDRESS
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
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.RANGE_SERVER_PORT
|
||||||
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
|
|
@ -14,10 +14,7 @@ import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.text.TextMeasurer
|
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.rememberTextMeasurer
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
|
@ -33,8 +30,7 @@ import com.faraphel.tasks_valider.database.populateSubjectSessionPersonTest
|
||||||
import com.faraphel.tasks_valider.ui.screen.authentification.AuthentificationServerScreen
|
import com.faraphel.tasks_valider.ui.screen.authentification.AuthentificationServerScreen
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
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.RANGE_SERVER_PORT
|
||||||
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionController
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +66,7 @@ fun CommunicationInternetServerScreen(
|
||||||
else controller.navigate("session")
|
else controller.navigate("session")
|
||||||
}
|
}
|
||||||
composable("session") {
|
composable("session") {
|
||||||
TaskSessionScreen(
|
TaskSessionController(
|
||||||
activity,
|
activity,
|
||||||
client.value!!,
|
client.value!!,
|
||||||
adminPersonEntity.value!!
|
adminPersonEntity.value!!
|
||||||
|
|
|
@ -19,7 +19,7 @@ import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
import com.faraphel.tasks_valider.connectivity.bwd.BwdManager
|
||||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.internet.CommunicationInternetSelectScreen
|
import com.faraphel.tasks_valider.ui.screen.communication.internet.CommunicationInternetSelectScreen
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.CommunicationWifiP2pScreen
|
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.CommunicationWifiP2pScreen
|
||||||
|
@ -49,8 +49,8 @@ fun CommunicationModeSelectionScreen(activity: Activity, database: TaskDatabase)
|
||||||
CommunicationInternetSelectScreen(activity, database)
|
CommunicationInternetSelectScreen(activity, database)
|
||||||
}
|
}
|
||||||
composable("wifi-p2p") {
|
composable("wifi-p2p") {
|
||||||
val bwfManager = BwfManager.fromActivity(activity)
|
val bwdManager = BwdManager.fromActivity(activity)
|
||||||
CommunicationWifiP2pScreen(activity, bwfManager)
|
CommunicationWifiP2pScreen(activity, bwdManager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ fun CommunicationModeSelectionScreen(activity: Activity, database: TaskDatabase)
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationSelectContent(controller: NavController, activity: Activity) {
|
fun CommunicationSelectContent(controller: NavController, activity: Activity) {
|
||||||
val isWifiP2pSupported = BwfManager.isSupported(activity)
|
val isWifiP2pSupported = BwdManager.isSupported(activity)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
|
|
@ -8,12 +8,12 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
import com.faraphel.tasks_valider.connectivity.bwd.BwdManager
|
||||||
import com.faraphel.tasks_valider.ui.widgets.connectivity.WifiP2pDeviceListWidget
|
import com.faraphel.tasks_valider.ui.widgets.connectivity.WifiP2pDeviceListWidget
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationWifiP2pClientScreen(activity: Activity, bwfManager: BwfManager) {
|
fun CommunicationWifiP2pClientScreen(activity: Activity, bwdManager: BwdManager) {
|
||||||
val selectedDevice = remember { mutableStateOf<WifiP2pDevice?>(null) }
|
val selectedDevice = remember { mutableStateOf<WifiP2pDevice?>(null) }
|
||||||
val isConnected = remember { mutableStateOf(false) }
|
val isConnected = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
@ -31,25 +31,25 @@ fun CommunicationWifiP2pClientScreen(activity: Activity, bwfManager: BwfManager)
|
||||||
val config = WifiP2pConfig().apply {
|
val config = WifiP2pConfig().apply {
|
||||||
deviceAddress = selectedDevice.value!!.deviceAddress
|
deviceAddress = selectedDevice.value!!.deviceAddress
|
||||||
}
|
}
|
||||||
bwfManager.connect(config) {
|
bwdManager.connect(config) {
|
||||||
isConnected.value = true
|
isConnected.value = true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// display the list of devices
|
// display the list of devices
|
||||||
CommunicationWifiP2pClientContent(bwfManager, selectedDevice)
|
CommunicationWifiP2pClientContent(bwdManager, selectedDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationWifiP2pClientContent(
|
fun CommunicationWifiP2pClientContent(
|
||||||
bwfManager: BwfManager,
|
bwdManager: BwdManager,
|
||||||
selectedDevice: MutableState<WifiP2pDevice?>
|
selectedDevice: MutableState<WifiP2pDevice?>
|
||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
WifiP2pDeviceListWidget(
|
WifiP2pDeviceListWidget(
|
||||||
peers = bwfManager.statePeers.value,
|
peers = bwdManager.statePeers.value,
|
||||||
filter = { device: WifiP2pDevice -> device.isGroupOwner },
|
filter = { device: WifiP2pDevice -> device.isGroupOwner },
|
||||||
selectedDevice,
|
selectedDevice,
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,19 +9,19 @@ import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
import com.faraphel.tasks_valider.connectivity.bwd.BwdManager
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.client.CommunicationWifiP2pClientScreen
|
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.client.CommunicationWifiP2pClientScreen
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.server.CommunicationWifiP2pServerScreen
|
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.server.CommunicationWifiP2pServerScreen
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationWifiP2pScreen(activity: Activity, bwfManager: BwfManager) {
|
fun CommunicationWifiP2pScreen(activity: Activity, bwdManager: BwdManager) {
|
||||||
val controller = rememberNavController()
|
val controller = rememberNavController()
|
||||||
|
|
||||||
NavHost(navController = controller, startDestination = "mode") {
|
NavHost(navController = controller, startDestination = "mode") {
|
||||||
composable("mode") { CommunicationWifiP2pSelectContent(controller) }
|
composable("mode") { CommunicationWifiP2pSelectContent(controller) }
|
||||||
composable("client") { CommunicationWifiP2pClientScreen(activity, bwfManager) }
|
composable("client") { CommunicationWifiP2pClientScreen(activity, bwdManager) }
|
||||||
composable("server") { CommunicationWifiP2pServerScreen(activity, bwfManager) }
|
composable("server") { CommunicationWifiP2pServerScreen(activity, bwdManager) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,16 @@
|
||||||
package com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.server
|
package com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.server
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.DropdownMenu
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import com.faraphel.tasks_valider.connectivity.bwd.BwdManager
|
||||||
import androidx.room.Room
|
|
||||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
|
||||||
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
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.PersonEntity
|
|
||||||
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.task.TaskSessionScreen
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationWifiP2pServerScreen(activity: Activity, bwfManager: BwfManager) {
|
fun CommunicationWifiP2pServerScreen(activity: Activity, bwdManager: BwdManager) {
|
||||||
val client = remember { mutableStateOf<TaskClient?>(null) }
|
val client = remember { mutableStateOf<TaskClient?>(null) }
|
||||||
|
|
||||||
// TODO(Faraphel): fix and get a user
|
// TODO(Faraphel): fix and get a user
|
||||||
|
@ -41,7 +24,7 @@ fun CommunicationWifiP2pServerScreen(activity: Activity, bwfManager: BwfManager)
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationWifiP2pServerContent(
|
fun CommunicationWifiP2pServerContent(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
bwfManager: BwfManager,
|
bwdManager: BwdManager,
|
||||||
client: MutableState<TaskClient?>
|
client: MutableState<TaskClient?>
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.faraphel.tasks_valider.ui.screen.scan.qr
|
package com.faraphel.tasks_valider.ui.screen.scan.qr
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
@ -17,6 +19,11 @@ import com.journeyapps.barcodescanner.DefaultDecoderFactory
|
||||||
@Composable
|
@Composable
|
||||||
fun ScanBarcodeScreen(activity: Activity, barcode: MutableState<BarcodeResult?>) {
|
fun ScanBarcodeScreen(activity: Activity, barcode: MutableState<BarcodeResult?>) {
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
|
// check and prompt for the camera permission
|
||||||
|
if (activity.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
|
||||||
|
// FIXME(Faraphel): seem to crash the application
|
||||||
|
activity.requestPermissions(arrayOf(Manifest.permission.CAMERA), 1)
|
||||||
|
|
||||||
// AndroidView is used because "DecoratedBarcodeView" only support the legacy view system
|
// AndroidView is used because "DecoratedBarcodeView" only support the legacy view system
|
||||||
AndroidView(factory = {
|
AndroidView(factory = {
|
||||||
DecoratedBarcodeView(activity).apply {
|
DecoratedBarcodeView(activity).apply {
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
package com.faraphel.tasks_valider.ui.screen.task
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||||
|
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||||
|
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||||
|
import com.faraphel.tasks_valider.ui.screen.scan.qr.ScanBarcodeScreen
|
||||||
|
import com.journeyapps.barcodescanner.BarcodeResult
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun QuickValidationScreen(
|
||||||
|
controller: NavController,
|
||||||
|
activity: Activity,
|
||||||
|
client: TaskClient,
|
||||||
|
user: PersonEntity,
|
||||||
|
) {
|
||||||
|
val barcode = remember { mutableStateOf<BarcodeResult?>(null) }
|
||||||
|
|
||||||
|
// prompt for the qr code if not found
|
||||||
|
if (barcode.value == null)
|
||||||
|
return ScanBarcodeScreen(activity, barcode)
|
||||||
|
|
||||||
|
// show the content of the qr code
|
||||||
|
val studentUrl = barcode.value!!.text.toHttpUrl()
|
||||||
|
val cardId = studentUrl.pathSegments[0]
|
||||||
|
|
||||||
|
// when the barcode changed
|
||||||
|
LaunchedEffect(cardId) {
|
||||||
|
Thread {
|
||||||
|
quickValidation(
|
||||||
|
controller,
|
||||||
|
activity,
|
||||||
|
client,
|
||||||
|
user,
|
||||||
|
cardId,
|
||||||
|
)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the latest task of a user from its student card
|
||||||
|
*/
|
||||||
|
fun quickValidation(
|
||||||
|
controller: NavController,
|
||||||
|
activity: Activity,
|
||||||
|
client: TaskClient,
|
||||||
|
user: PersonEntity,
|
||||||
|
cardId: String,
|
||||||
|
) {
|
||||||
|
// action when an error occurred or everything worked
|
||||||
|
fun finish() {
|
||||||
|
activity.runOnUiThread {
|
||||||
|
// go back to the main screen
|
||||||
|
controller.navigateUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// requests all the persons
|
||||||
|
val allPersons = client.personApi.getAll()
|
||||||
|
// get the person with the matching card
|
||||||
|
val person = allPersons.firstOrNull { person -> person.cardId == cardId }
|
||||||
|
|
||||||
|
if (person == null) {
|
||||||
|
// tell to the user that this card is linked to nobody
|
||||||
|
activity.runOnUiThread {
|
||||||
|
Toast.makeText(activity, "No person found for that card.", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
return finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
// requests all the relation persons - subjects
|
||||||
|
val allRelationsPersonSubject = client.relationPersonSessionSubjectApi.getAll()
|
||||||
|
// get the corresponding relation
|
||||||
|
val relationPersonSubject = allRelationsPersonSubject.first { relation -> relation.studentId == person.id }
|
||||||
|
|
||||||
|
// requests all the tasks
|
||||||
|
val allTasks = client.taskApi.getAll()
|
||||||
|
// get the corresponding tasks
|
||||||
|
val tasks = allTasks
|
||||||
|
.filter { task -> task.subjectId == relationPersonSubject.subjectId }
|
||||||
|
.sortedBy { task -> task.order }
|
||||||
|
|
||||||
|
// requests all the validations
|
||||||
|
val allValidations = client.validationApi.getAll()
|
||||||
|
// get the corresponding relation
|
||||||
|
val validations = allValidations.filter { validation -> validation.studentId == person.id }
|
||||||
|
|
||||||
|
// get the first task without any validation
|
||||||
|
val task = tasks.firstOrNull { task ->
|
||||||
|
// check in all the validations if the task is found
|
||||||
|
val validation = validations.firstOrNull { validation -> validation.taskId == task.id }
|
||||||
|
// keep the task if it has no validation
|
||||||
|
validation == null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task == null) {
|
||||||
|
// tell to the user the action cannot be done
|
||||||
|
activity.runOnUiThread {
|
||||||
|
Toast.makeText(activity, "There are no tasks left.", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
return finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new validation on the server
|
||||||
|
client.validationApi.save(
|
||||||
|
ValidationEntity(
|
||||||
|
teacherId=user.id,
|
||||||
|
studentId=person.id,
|
||||||
|
taskId=task.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// confirm to the user the action was successful
|
||||||
|
activity.runOnUiThread {
|
||||||
|
Toast.makeText(activity, "Validated \"${task.title}\".", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
return finish()
|
||||||
|
}
|
|
@ -1,24 +1,44 @@
|
||||||
package com.faraphel.tasks_valider.ui.screen.task
|
package com.faraphel.tasks_valider.ui.screen.task
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.os.Build
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.compose.NavHost
|
||||||
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||||
import com.faraphel.tasks_valider.utils.parser
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
|
@Composable
|
||||||
|
fun TaskSessionController(
|
||||||
|
activity: Activity,
|
||||||
|
client: TaskClient,
|
||||||
|
user: PersonEntity,
|
||||||
|
) {
|
||||||
|
val controller = rememberNavController()
|
||||||
|
|
||||||
|
NavHost(
|
||||||
|
navController = controller,
|
||||||
|
startDestination = "main"
|
||||||
|
) {
|
||||||
|
composable("main") {
|
||||||
|
TaskSessionScreen(controller, activity, client, user)
|
||||||
|
}
|
||||||
|
composable("quick_validation") {
|
||||||
|
QuickValidationScreen(controller, activity, client, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +48,7 @@ import com.google.gson.reflect.TypeToken
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun TaskSessionScreen(
|
fun TaskSessionScreen(
|
||||||
|
controller: NavController,
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
client: TaskClient,
|
client: TaskClient,
|
||||||
user: PersonEntity,
|
user: PersonEntity,
|
||||||
|
@ -37,7 +58,9 @@ fun TaskSessionScreen(
|
||||||
|
|
||||||
// if the groups are not yet defined, refresh the list
|
// if the groups are not yet defined, refresh the list
|
||||||
if (students.value == null)
|
if (students.value == null)
|
||||||
return Thread { refreshStudents(activity, client, students) }.start()
|
return LaunchedEffect(true) {
|
||||||
|
Thread { refreshStudents(activity, client, students) }.start()
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedStudent.value != null)
|
if (selectedStudent.value != null)
|
||||||
return TaskStudentScreen(
|
return TaskStudentScreen(
|
||||||
|
@ -69,6 +92,17 @@ fun TaskSessionScreen(
|
||||||
Text(text = student.fullName())
|
Text(text = student.fullName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// separator
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
Row {
|
||||||
|
// quick validation
|
||||||
|
Button(onClick = { controller.navigate("quick_validation") }) {
|
||||||
|
Text("Quick Validation")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,16 +113,14 @@ fun refreshStudents(
|
||||||
client: TaskClient,
|
client: TaskClient,
|
||||||
students: MutableState<List<PersonEntity>?>
|
students: MutableState<List<PersonEntity>?>
|
||||||
) {
|
) {
|
||||||
// try to obtain the list of groups
|
try {
|
||||||
val response = client.get("entities/" + PersonEntity.TABLE_NAME)
|
// try to get all the persons in that session
|
||||||
|
students.value = client.personApi.getAll()
|
||||||
// in case of error, notify it
|
} catch (exception: Exception) {
|
||||||
if (!response.isSuccessful)
|
// in case of error, show a message
|
||||||
return activity.runOnUiThread { Toast.makeText(activity, response.message, Toast.LENGTH_LONG).show() }
|
return activity.runOnUiThread {
|
||||||
|
Log.e("students", "$exception")
|
||||||
// parse the list of groups
|
Toast.makeText(activity, "Could not retrieve students.\n\n$exception", Toast.LENGTH_LONG).show()
|
||||||
students.value = parser.fromJson(
|
}
|
||||||
response.body.string(),
|
}
|
||||||
object : TypeToken<List<PersonEntity>>(){}.type
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import com.faraphel.tasks_valider.database.entities.*
|
||||||
import com.faraphel.tasks_valider.utils.dateTimeFormatter
|
import com.faraphel.tasks_valider.utils.dateTimeFormatter
|
||||||
import com.faraphel.tasks_valider.utils.parser
|
import com.faraphel.tasks_valider.utils.parser
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,7 +94,6 @@ fun TaskStudentScreen(
|
||||||
client,
|
client,
|
||||||
state,
|
state,
|
||||||
validation ?: ValidationEntity(
|
validation ?: ValidationEntity(
|
||||||
date=Instant.now(),
|
|
||||||
teacherId=user.id,
|
teacherId=user.id,
|
||||||
studentId=student.id,
|
studentId=student.id,
|
||||||
taskId=task.id,
|
taskId=task.id,
|
||||||
|
@ -127,58 +125,26 @@ fun refreshTasksValidations(
|
||||||
validations: MutableState<List<ValidationEntity>?>,
|
validations: MutableState<List<ValidationEntity>?>,
|
||||||
) {
|
) {
|
||||||
// try to obtain the list of subject
|
// try to obtain the list of subject
|
||||||
val responseSubjects = client.get("entities/" + RelationPersonSessionSubjectEntity.TABLE_NAME)
|
val allRelationsPersonSessionSubject = client.relationPersonSessionSubjectApi.getAll()
|
||||||
|
|
||||||
// in case of error, notify it
|
|
||||||
if (!responseSubjects.isSuccessful)
|
|
||||||
return activity.runOnUiThread { Toast.makeText(activity, responseSubjects.message, Toast.LENGTH_LONG).show() }
|
|
||||||
|
|
||||||
// parse the list of subjects
|
|
||||||
val allPersonSessionSubjects = parser.fromJson<List<RelationPersonSessionSubjectEntity>>(
|
|
||||||
responseSubjects.body.string(),
|
|
||||||
object : TypeToken<List<RelationPersonSessionSubjectEntity>>(){}.type
|
|
||||||
)
|
|
||||||
|
|
||||||
// get the subject that the student is using
|
// get the subject that the student is using
|
||||||
val relationPersonSessionSubjects = allPersonSessionSubjects.firstOrNull { relation -> relation.studentId == student.id }
|
val relationPersonSessionSubject = allRelationsPersonSessionSubject.firstOrNull { relation ->
|
||||||
|
relation.studentId == student.id
|
||||||
|
}
|
||||||
|
|
||||||
if (relationPersonSessionSubjects == null)
|
if (relationPersonSessionSubject == null)
|
||||||
// TODO(Faraphel): should be able to assign a subject ?
|
// TODO(Faraphel): should be able to assign a subject ?
|
||||||
return activity.runOnUiThread { Toast.makeText(activity, "No subject assigned", Toast.LENGTH_LONG).show() }
|
return activity.runOnUiThread { Toast.makeText(activity, "No subject assigned", Toast.LENGTH_LONG).show() }
|
||||||
|
|
||||||
// try to obtain the list of tasks
|
// try to obtain the list of tasks
|
||||||
val responseTasks = client.get("entities/" + TaskEntity.TABLE_NAME)
|
val allTasks = client.taskApi.getAll()
|
||||||
|
|
||||||
// in case of error, notify it
|
|
||||||
if (!responseTasks.isSuccessful)
|
|
||||||
return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() }
|
|
||||||
|
|
||||||
// parse the list of subjects
|
|
||||||
val allTasks = parser.fromJson<List<TaskEntity>>(
|
|
||||||
responseTasks.body.string(),
|
|
||||||
object : TypeToken<List<TaskEntity>>(){}.type
|
|
||||||
)
|
|
||||||
|
|
||||||
// get the tasks that are linked to this subject
|
// get the tasks that are linked to this subject
|
||||||
tasks.value = allTasks.filter { task ->
|
tasks.value = allTasks
|
||||||
task.subjectId == relationPersonSessionSubjects.subjectId
|
.filter { task -> task.subjectId == relationPersonSessionSubject.subjectId }
|
||||||
}.sortedBy { task ->
|
.sortedBy { task -> task.order }
|
||||||
task.order
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to obtain the list of validations
|
// try to obtain the list of validations
|
||||||
val responseValidations = client.get("entities/" + ValidationEntity.TABLE_NAME)
|
val allValidations = client.validationApi.getAll()
|
||||||
|
|
||||||
// in case of error, notify it
|
|
||||||
if (!responseValidations.isSuccessful)
|
|
||||||
return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() }
|
|
||||||
|
|
||||||
// parse the list of validations
|
|
||||||
val allValidations = parser.fromJson<List<ValidationEntity>>(
|
|
||||||
responseValidations.body.string(),
|
|
||||||
object : TypeToken<List<ValidationEntity>>(){}.type
|
|
||||||
)
|
|
||||||
|
|
||||||
// filter only the interesting validations
|
// filter only the interesting validations
|
||||||
validations.value = allValidations.filter { validation ->
|
validations.value = allValidations.filter { validation ->
|
||||||
validation.studentId == student.id &&
|
validation.studentId == student.id &&
|
||||||
|
@ -188,20 +154,10 @@ fun refreshTasksValidations(
|
||||||
|
|
||||||
|
|
||||||
fun updateValidation(client: TaskClient, checked: Boolean, validation: ValidationEntity) {
|
fun updateValidation(client: TaskClient, checked: Boolean, validation: ValidationEntity) {
|
||||||
if (checked) {
|
if (checked)
|
||||||
// if the validation is not set, create it
|
// if the validation is not set, create it
|
||||||
client.post(
|
client.validationApi.save(validation)
|
||||||
"entities/" + ValidationEntity.TABLE_NAME,
|
else
|
||||||
parser.toJson(validation),
|
|
||||||
"application/json"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// if the validation is set, delete it
|
// if the validation is set, delete it
|
||||||
client.delete(
|
client.validationApi.delete(validation)
|
||||||
"entities/" + ValidationEntity.TABLE_NAME,
|
}
|
||||||
parser.toJson(validation),
|
|
||||||
"application/json"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.faraphel.tasks_valider.database.converters
|
package com.faraphel.tasks_valider.utils.converters
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.google.gson.*
|
import com.google.gson.*
|
|
@ -1,6 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.utils
|
package com.faraphel.tasks_valider.utils
|
||||||
|
|
||||||
import com.faraphel.tasks_valider.database.converters.InstantConverter
|
import com.faraphel.tasks_valider.utils.converters.InstantConverter
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
Loading…
Reference in a new issue