From a3fbe984b6f5222b20c1447f5fb95284425f9158 Mon Sep 17 00:00:00 2001 From: samuel Date: Tue, 19 Mar 2024 17:57:55 +0100 Subject: [PATCH 1/5] start login --- .../main/java/com/iqball/app/MainActivity.kt | 34 +++++++--- .../main/java/com/iqball/app/page/HomePage.kt | 10 +++ .../java/com/iqball/app/page/LoginPage.kt | 66 ++++++++++++++++++- .../java/com/iqball/app/page/RegisterPage.kt | 11 +--- .../com/iqball/app/session/DataSession.kt | 3 + .../com/iqball/app/session/MutableSession.kt | 5 -- .../java/com/iqball/app/session/Session.kt | 2 +- gradle/libs.versions.toml | 2 +- 8 files changed, 106 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/com/iqball/app/page/HomePage.kt create mode 100644 app/src/main/java/com/iqball/app/session/DataSession.kt delete mode 100644 app/src/main/java/com/iqball/app/session/MutableSession.kt diff --git a/app/src/main/java/com/iqball/app/MainActivity.kt b/app/src/main/java/com/iqball/app/MainActivity.kt index 964daee..de4e2e4 100644 --- a/app/src/main/java/com/iqball/app/MainActivity.kt +++ b/app/src/main/java/com/iqball/app/MainActivity.kt @@ -7,21 +7,23 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import com.google.gson.Gson -import com.google.gson.GsonBuilder import com.iqball.app.api.EitherBodyConverter import com.iqball.app.api.EitherCallAdapterFactory import com.iqball.app.api.service.IQBallService -import com.iqball.app.page.RegisterPage +import com.iqball.app.page.HomePage +import com.iqball.app.page.LoginPage +import com.iqball.app.session.DataSession +import com.iqball.app.session.Session import com.iqball.app.ui.theme.IQBallTheme import okhttp3.OkHttpClient -import okhttp3.ResponseBody -import retrofit2.Converter import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.create -import java.lang.reflect.Type class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -46,8 +48,12 @@ class MainActivity : ComponentActivity() { setContent { IQBallTheme { // A surface container using the 'background' color from the theme - Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { - App(service) + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + val sessionState = remember { mutableStateOf(DataSession()) } + App(service, sessionState) } } } @@ -55,6 +61,16 @@ class MainActivity : ComponentActivity() { } @Composable -fun App(service: IQBallService) { - RegisterPage(service) +fun App(service: IQBallService, sessionState: MutableState) { + + val loginPage: @Composable () -> Unit = { + LoginPage(service = service, onLoginSuccess = { auth -> + sessionState.value = DataSession(auth) + }) + } + + val homePage : @Composable () -> Unit = { HomePage(service, sessionState.value) } + val currentPage = remember(sessionState.value.auth) { if (sessionState.value.auth == null) loginPage else homePage } + + currentPage() } \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/HomePage.kt b/app/src/main/java/com/iqball/app/page/HomePage.kt new file mode 100644 index 0000000..da8f56e --- /dev/null +++ b/app/src/main/java/com/iqball/app/page/HomePage.kt @@ -0,0 +1,10 @@ +package com.iqball.app.page + +import androidx.compose.runtime.Composable +import com.iqball.app.api.service.IQBallService +import com.iqball.app.session.Session + +@Composable +fun HomePage(service: IQBallService, session: Session) { + +} \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/LoginPage.kt b/app/src/main/java/com/iqball/app/page/LoginPage.kt index f6f8748..55f6de7 100644 --- a/app/src/main/java/com/iqball/app/page/LoginPage.kt +++ b/app/src/main/java/com/iqball/app/page/LoginPage.kt @@ -2,8 +2,70 @@ package com.iqball.app.page import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Button +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import arrow.core.Either +import com.iqball.app.api.service.AuthService +import com.iqball.app.session.Authentication +import kotlinx.coroutines.runBlocking +import kotlinx.datetime.LocalDateTime @Composable -fun LoginPage() { - Text(text = "Login Page") +fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { + var username by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + + Surface( + color = Color.White, + modifier = Modifier.fillMaxSize() + ) { + Column( + modifier = Modifier + .padding(16.dp) + .fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Login", + fontSize = 28.sp, + color = Color.Black + ) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField( + value = username, + onValueChange = { username = it }, + label = { Text("Username") }, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField( + value = password, + onValueChange = { password = it }, + label = { Text("Password") }, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(16.dp)) + + Button(onClick = { + runBlocking { + when(val response = service.login(AuthService.LoginRequest(username, password))){ + is Either.Left -> println(response.value) + + is Either.Right -> onLoginSuccess(Authentication(response.value.token, LocalDateTime.parse(response.value.expirationDate))) + } + } + }) { + Text(text = "Se connecter") + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/RegisterPage.kt b/app/src/main/java/com/iqball/app/page/RegisterPage.kt index 6bb14bc..720c36e 100644 --- a/app/src/main/java/com/iqball/app/page/RegisterPage.kt +++ b/app/src/main/java/com/iqball/app/page/RegisterPage.kt @@ -3,21 +3,14 @@ package com.iqball.app.page import android.util.Log import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import arrow.core.Either import com.iqball.app.api.service.AuthService -import com.iqball.app.api.service.AuthService.RegisterRequest import com.iqball.app.api.service.IQBallService -import com.iqball.app.session.Authentication -import com.iqball.app.session.MutableSession -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking @Composable fun RegisterPage(service: IQBallService) { @@ -25,7 +18,7 @@ fun RegisterPage(service: IQBallService) { var text by remember { mutableStateOf("No message !") } - runBlocking { + LaunchedEffect(Unit) { val result = service.login(AuthService.LoginRequest("maxime@mail.com", "123456")) when (result) { diff --git a/app/src/main/java/com/iqball/app/session/DataSession.kt b/app/src/main/java/com/iqball/app/session/DataSession.kt new file mode 100644 index 0000000..686adc1 --- /dev/null +++ b/app/src/main/java/com/iqball/app/session/DataSession.kt @@ -0,0 +1,3 @@ +package com.iqball.app.session + +data class DataSession(override val auth: Authentication? = null) : Session \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/session/MutableSession.kt b/app/src/main/java/com/iqball/app/session/MutableSession.kt deleted file mode 100644 index 37219bf..0000000 --- a/app/src/main/java/com/iqball/app/session/MutableSession.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.iqball.app.session - -interface MutableSession : Session { - override var auth: Authentication -} \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/session/Session.kt b/app/src/main/java/com/iqball/app/session/Session.kt index bb34b40..e0c1975 100644 --- a/app/src/main/java/com/iqball/app/session/Session.kt +++ b/app/src/main/java/com/iqball/app/session/Session.kt @@ -1,5 +1,5 @@ package com.iqball.app.session interface Session { - val auth: Authentication + val auth: Authentication? } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c53489..f10c49e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.3.0" +agp = "8.2.2" arrowCore = "1.2.1" converterGson = "2.9.0" kotlin = "1.9.0" From 9990c69374ca7ad3820329dcdc056aac03e735be Mon Sep 17 00:00:00 2001 From: samuel Date: Thu, 21 Mar 2024 09:49:02 +0100 Subject: [PATCH 2/5] register wip --- .../main/java/com/iqball/app/MainActivity.kt | 12 +- .../main/java/com/iqball/app/page/HomePage.kt | 2 + .../java/com/iqball/app/page/LoginPage.kt | 18 +-- .../java/com/iqball/app/page/RegisterPage.kt | 106 ++++++++++++++---- 4 files changed, 106 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/iqball/app/MainActivity.kt b/app/src/main/java/com/iqball/app/MainActivity.kt index de4e2e4..bc2fc63 100644 --- a/app/src/main/java/com/iqball/app/MainActivity.kt +++ b/app/src/main/java/com/iqball/app/MainActivity.kt @@ -17,6 +17,7 @@ import com.iqball.app.api.EitherCallAdapterFactory import com.iqball.app.api.service.IQBallService import com.iqball.app.page.HomePage import com.iqball.app.page.LoginPage +import com.iqball.app.page.RegisterPage import com.iqball.app.session.DataSession import com.iqball.app.session.Session import com.iqball.app.ui.theme.IQBallTheme @@ -63,14 +64,21 @@ class MainActivity : ComponentActivity() { @Composable fun App(service: IQBallService, sessionState: MutableState) { + val registerPage: @Composable () -> Unit = { + RegisterPage(service = service, onLoginSuccess = { auth -> + sessionState.value = DataSession(auth) + }) + } + val loginPage: @Composable () -> Unit = { LoginPage(service = service, onLoginSuccess = { auth -> sessionState.value = DataSession(auth) }) } - val homePage : @Composable () -> Unit = { HomePage(service, sessionState.value) } - val currentPage = remember(sessionState.value.auth) { if (sessionState.value.auth == null) loginPage else homePage } + registerPage() + val currentPage = remember(sessionState.value.auth) { if (sessionState.value.auth == null) loginPage else homePage } currentPage() + } \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/HomePage.kt b/app/src/main/java/com/iqball/app/page/HomePage.kt index da8f56e..8bcb3bf 100644 --- a/app/src/main/java/com/iqball/app/page/HomePage.kt +++ b/app/src/main/java/com/iqball/app/page/HomePage.kt @@ -1,5 +1,6 @@ package com.iqball.app.page +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import com.iqball.app.api.service.IQBallService import com.iqball.app.session.Session @@ -7,4 +8,5 @@ import com.iqball.app.session.Session @Composable fun HomePage(service: IQBallService, session: Session) { + Text(text = "HELLO WELCOME") } \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/LoginPage.kt b/app/src/main/java/com/iqball/app/page/LoginPage.kt index 55f6de7..053e14d 100644 --- a/app/src/main/java/com/iqball/app/page/LoginPage.kt +++ b/app/src/main/java/com/iqball/app/page/LoginPage.kt @@ -18,10 +18,12 @@ import com.iqball.app.session.Authentication import kotlinx.coroutines.runBlocking import kotlinx.datetime.LocalDateTime + @Composable fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { - var username by remember { mutableStateOf("") } + var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } + var errors by remember { mutableStateOf("") } Surface( color = Color.White, @@ -35,15 +37,15 @@ fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = "Login", + text = "S'identifier", fontSize = 28.sp, color = Color.Black ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( - value = username, - onValueChange = { username = it }, - label = { Text("Username") }, + value = email, + onValueChange = { email = it }, + label = { Text("Email") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(16.dp)) @@ -57,8 +59,10 @@ fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { Button(onClick = { runBlocking { - when(val response = service.login(AuthService.LoginRequest(username, password))){ - is Either.Left -> println(response.value) + when(val response = service.login(AuthService.LoginRequest(email, password))){ + is Either.Left -> { + errors = response.value.toList().flatMap { entry -> entry.second.map { "${entry.first} : ${it}" } }.joinToString("\n") + } is Either.Right -> onLoginSuccess(Authentication(response.value.token, LocalDateTime.parse(response.value.expirationDate))) } diff --git a/app/src/main/java/com/iqball/app/page/RegisterPage.kt b/app/src/main/java/com/iqball/app/page/RegisterPage.kt index 720c36e..869a777 100644 --- a/app/src/main/java/com/iqball/app/page/RegisterPage.kt +++ b/app/src/main/java/com/iqball/app/page/RegisterPage.kt @@ -1,6 +1,16 @@ package com.iqball.app.page import android.util.Log +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -8,40 +18,90 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import arrow.core.Either import com.iqball.app.api.service.AuthService import com.iqball.app.api.service.IQBallService +import com.iqball.app.session.Authentication +import kotlinx.coroutines.runBlocking +import kotlinx.datetime.LocalDateTime +import androidx.compose.ui.text.input.VisualTransformation @Composable -fun RegisterPage(service: IQBallService) { +fun RegisterPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) { + var username by remember { mutableStateOf("") } + var email by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + var errors by remember { mutableStateOf("") } + Surface( + color = Color.White, + modifier = Modifier.fillMaxSize() - var text by remember { mutableStateOf("No message !") } - - LaunchedEffect(Unit) { - val result = service.login(AuthService.LoginRequest("maxime@mail.com", "123456")) - - when (result) { - is Either.Left -> { - println("Error : " + result.value) - text = result.toString() + ) { + Column( + modifier = Modifier + .padding(16.dp) + .fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "S'enregistrer", + fontSize = 28.sp, + color = Color.Black + ) + Spacer(modifier = Modifier.height(16.dp)) + errors?.let { message -> + Text( + text = message, + color = Color.Red, + fontSize = 14.sp, + modifier = Modifier.padding(vertical = 8.dp) + ) } - is Either.Right -> { - val token = result.value.token - val userDataResponse = service.getUserData(token) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField( + value = username, + onValueChange = { username = it }, + label = { Text("Nom d'utilisateur") }, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField( + value = password, + onValueChange = { password = it }, + label = { Text("Mot de passe") }, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField( + value = email, + onValueChange = { email = it }, + label = { Text("Email") }, + modifier = Modifier.fillMaxWidth() + ) + Button(onClick = { + runBlocking { + when (val response = + service.register(AuthService.RegisterRequest(username, email, password))) { + is Either.Left -> { + errors = response.value.toList().flatMap { entry -> entry.second.map { "${entry.first} : ${it}" } }.joinToString("\n") + } - when (userDataResponse) { - is Either.Left -> println("Error User Data : " + userDataResponse.value) - is Either.Right -> println("Success User Data : " + userDataResponse.value) + is Either.Right -> { + onLoginSuccess(Authentication(response.value.token,LocalDateTime.parse(response.value.expirationDate))) + } + } } - - text = userDataResponse.toString() + }) { + Text(text = "Créer votre compte") } } - - println(result) - Log.i("%", result.toString()) } - - Text(text = text) } + From 07252b902589a6f028cf855df8c7ee383abf8cfa Mon Sep 17 00:00:00 2001 From: KaulH Date: Wed, 27 Mar 2024 17:32:42 +0100 Subject: [PATCH 3/5] register and login wip --- .../main/java/com/iqball/app/MainActivity.kt | 4 +-- .../com/iqball/app/api/service/AuthService.kt | 2 +- .../java/com/iqball/app/page/LoginPage.kt | 27 +++++++++++++++---- .../java/com/iqball/app/page/RegisterPage.kt | 22 ++++++++------- .../com/iqball/app/session/Authentication.kt | 4 +-- 5 files changed, 39 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/iqball/app/MainActivity.kt b/app/src/main/java/com/iqball/app/MainActivity.kt index bc2fc63..9accff0 100644 --- a/app/src/main/java/com/iqball/app/MainActivity.kt +++ b/app/src/main/java/com/iqball/app/MainActivity.kt @@ -65,7 +65,7 @@ class MainActivity : ComponentActivity() { fun App(service: IQBallService, sessionState: MutableState) { val registerPage: @Composable () -> Unit = { - RegisterPage(service = service, onLoginSuccess = { auth -> + RegisterPage(service = service, onRegisterSuccess = { auth -> sessionState.value = DataSession(auth) }) } @@ -77,7 +77,7 @@ fun App(service: IQBallService, sessionState: MutableState) { } val homePage : @Composable () -> Unit = { HomePage(service, sessionState.value) } - registerPage() + //registerPage() val currentPage = remember(sessionState.value.auth) { if (sessionState.value.auth == null) loginPage else homePage } currentPage() diff --git a/app/src/main/java/com/iqball/app/api/service/AuthService.kt b/app/src/main/java/com/iqball/app/api/service/AuthService.kt index 5b88a09..bb444fe 100644 --- a/app/src/main/java/com/iqball/app/api/service/AuthService.kt +++ b/app/src/main/java/com/iqball/app/api/service/AuthService.kt @@ -11,7 +11,7 @@ import retrofit2.http.POST interface AuthService { @Serializable - data class AuthResponse(val token: String, val expirationDate: String) + data class AuthResponse(val token: String, val expirationDate: Long) @Serializable data class RegisterRequest(val username: String, val email: String, val password: String) diff --git a/app/src/main/java/com/iqball/app/page/LoginPage.kt b/app/src/main/java/com/iqball/app/page/LoginPage.kt index 053e14d..d2d50d6 100644 --- a/app/src/main/java/com/iqball/app/page/LoginPage.kt +++ b/app/src/main/java/com/iqball/app/page/LoginPage.kt @@ -10,17 +10,17 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import arrow.core.Either import com.iqball.app.api.service.AuthService import com.iqball.app.session.Authentication import kotlinx.coroutines.runBlocking -import kotlinx.datetime.LocalDateTime @Composable -fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { +fun LoginPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) { var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } var errors by remember { mutableStateOf("") } @@ -42,6 +42,15 @@ fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { color = Color.Black ) Spacer(modifier = Modifier.height(16.dp)) + errors?.let { message -> + Text( + text = message, + color = Color.Red, + fontSize = 14.sp, + modifier = Modifier.padding(vertical = 8.dp) + ) + } + Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( value = email, onValueChange = { email = it }, @@ -53,18 +62,26 @@ fun LoginPage(service: AuthService, onLoginSuccess : (Authentication) -> Unit) { value = password, onValueChange = { password = it }, label = { Text("Password") }, + visualTransformation = PasswordVisualTransformation(), modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { runBlocking { - when(val response = service.login(AuthService.LoginRequest(email, password))){ + when (val response = service.login(AuthService.LoginRequest(email, password))) { is Either.Left -> { - errors = response.value.toList().flatMap { entry -> entry.second.map { "${entry.first} : ${it}" } }.joinToString("\n") + errors = response.value.toList() + .flatMap { entry -> entry.second.map { "${entry.first} : ${it}" } } + .joinToString("\n") } - is Either.Right -> onLoginSuccess(Authentication(response.value.token, LocalDateTime.parse(response.value.expirationDate))) + is Either.Right -> onLoginSuccess( + Authentication( + response.value.token, + response.value.expirationDate.toLong() + ) + ) } } }) { diff --git a/app/src/main/java/com/iqball/app/page/RegisterPage.kt b/app/src/main/java/com/iqball/app/page/RegisterPage.kt index 869a777..2e02b03 100644 --- a/app/src/main/java/com/iqball/app/page/RegisterPage.kt +++ b/app/src/main/java/com/iqball/app/page/RegisterPage.kt @@ -1,6 +1,5 @@ package com.iqball.app.page -import android.util.Log import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -13,7 +12,6 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -21,18 +19,16 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import arrow.core.Either import com.iqball.app.api.service.AuthService -import com.iqball.app.api.service.IQBallService import com.iqball.app.session.Authentication import kotlinx.coroutines.runBlocking -import kotlinx.datetime.LocalDateTime -import androidx.compose.ui.text.input.VisualTransformation @Composable -fun RegisterPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) { +fun RegisterPage(service: AuthService, onRegisterSuccess: (Authentication) -> Unit) { var username by remember { mutableStateOf("") } var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } @@ -76,7 +72,8 @@ fun RegisterPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) value = password, onValueChange = { password = it }, label = { Text("Mot de passe") }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + visualTransformation = PasswordVisualTransformation() ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( @@ -90,11 +87,18 @@ fun RegisterPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) when (val response = service.register(AuthService.RegisterRequest(username, email, password))) { is Either.Left -> { - errors = response.value.toList().flatMap { entry -> entry.second.map { "${entry.first} : ${it}" } }.joinToString("\n") + errors = response.value.toList() + .flatMap { entry -> entry.second.map { "${entry.first} : ${it}" } } + .joinToString("\n") } is Either.Right -> { - onLoginSuccess(Authentication(response.value.token,LocalDateTime.parse(response.value.expirationDate))) + onRegisterSuccess( + Authentication( + response.value.token, + response.value.expirationDate + ) + ) } } } diff --git a/app/src/main/java/com/iqball/app/session/Authentication.kt b/app/src/main/java/com/iqball/app/session/Authentication.kt index 1f9aed4..b5dbeaf 100644 --- a/app/src/main/java/com/iqball/app/session/Authentication.kt +++ b/app/src/main/java/com/iqball/app/session/Authentication.kt @@ -1,5 +1,3 @@ package com.iqball.app.session -import kotlinx.datetime.LocalDateTime - -data class Authentication(val token: String, val expirationDate: LocalDateTime) +data class Authentication(val token: String, val expirationDate: Long) From 72577b8505ff5ed66b258c77cb892aee73e1d0c4 Mon Sep 17 00:00:00 2001 From: KaulH Date: Sat, 30 Mar 2024 11:38:35 +0100 Subject: [PATCH 4/5] navigation --- app/build.gradle.kts | 1 + .../main/java/com/iqball/app/MainActivity.kt | 50 +++++++++++++------ .../java/com/iqball/app/page/LoginPage.kt | 10 +++- .../java/com/iqball/app/page/RegisterPage.kt | 10 +++- gradle/libs.versions.toml | 2 + 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0e3ab1c..6c286ef 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -73,6 +73,7 @@ dependencies { implementation(libs.retrofit.adapters.arrow) implementation(libs.arrow.core) + implementation(libs.androidx.navigation.compose) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) diff --git a/app/src/main/java/com/iqball/app/MainActivity.kt b/app/src/main/java/com/iqball/app/MainActivity.kt index 9accff0..5e247fd 100644 --- a/app/src/main/java/com/iqball/app/MainActivity.kt +++ b/app/src/main/java/com/iqball/app/MainActivity.kt @@ -8,9 +8,14 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController import com.google.gson.Gson import com.iqball.app.api.EitherBodyConverter import com.iqball.app.api.EitherCallAdapterFactory @@ -63,22 +68,35 @@ class MainActivity : ComponentActivity() { @Composable fun App(service: IQBallService, sessionState: MutableState) { + val navController = rememberNavController() - val registerPage: @Composable () -> Unit = { - RegisterPage(service = service, onRegisterSuccess = { auth -> - sessionState.value = DataSession(auth) - }) - } - - val loginPage: @Composable () -> Unit = { - LoginPage(service = service, onLoginSuccess = { auth -> - sessionState.value = DataSession(auth) - }) + NavHost(navController = navController, startDestination = "login") { + composable("login") { + LoginPage( + service = service, + onLoginSuccess = { auth -> + sessionState.value = DataSession(auth) + navController.navigate("home") + }, + onNavigateToRegister = { + navController.navigate("register") + } + ) + } + composable("register") { + RegisterPage( + service = service, + onRegisterSuccess = { auth -> + sessionState.value = DataSession(auth) + navController.navigate("home") + }, + onNavigateToLogin = { + navController.navigate("login") + } + ) + } + composable("home") { + HomePage(service = service, session = sessionState.value) + } } - val homePage : @Composable () -> Unit = { HomePage(service, sessionState.value) } - - //registerPage() - val currentPage = remember(sessionState.value.auth) { if (sessionState.value.auth == null) loginPage else homePage } - currentPage() - } \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/LoginPage.kt b/app/src/main/java/com/iqball/app/page/LoginPage.kt index d2d50d6..f1cd62e 100644 --- a/app/src/main/java/com/iqball/app/page/LoginPage.kt +++ b/app/src/main/java/com/iqball/app/page/LoginPage.kt @@ -20,7 +20,11 @@ import kotlinx.coroutines.runBlocking @Composable -fun LoginPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) { +fun LoginPage( + service: AuthService, + onLoginSuccess: (Authentication) -> Unit, + onNavigateToRegister: () -> Unit +) { var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } var errors by remember { mutableStateOf("") } @@ -87,6 +91,10 @@ fun LoginPage(service: AuthService, onLoginSuccess: (Authentication) -> Unit) { }) { Text(text = "Se connecter") } + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { onNavigateToRegister() }) { + Text(text = "Vous n'avez pas de compte ?") + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/iqball/app/page/RegisterPage.kt b/app/src/main/java/com/iqball/app/page/RegisterPage.kt index 2e02b03..ce91d21 100644 --- a/app/src/main/java/com/iqball/app/page/RegisterPage.kt +++ b/app/src/main/java/com/iqball/app/page/RegisterPage.kt @@ -28,7 +28,11 @@ import com.iqball.app.session.Authentication import kotlinx.coroutines.runBlocking @Composable -fun RegisterPage(service: AuthService, onRegisterSuccess: (Authentication) -> Unit) { +fun RegisterPage( + service: AuthService, + onRegisterSuccess: (Authentication) -> Unit, + onNavigateToLogin: () -> Unit +) { var username by remember { mutableStateOf("") } var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } @@ -105,6 +109,10 @@ fun RegisterPage(service: AuthService, onRegisterSuccess: (Authentication) -> Un }) { Text(text = "Créer votre compte") } + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { onNavigateToLogin() }) { + Text(text = "Vous avez déjà un compte ?") + } } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f10c49e..395069b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,7 @@ composeBom = "2023.08.00" retrofit = "2.9.0" retrofit2KotlinxSerializationConverter = "1.0.0" retrofitAdaptersArrow = "1.0.9" +navigationCompose = "2.7.7" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -38,6 +39,7 @@ kotlinx-serialization-json-jvm = { module = "org.jetbrains.kotlinx:kotlinx-seria retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } retrofit-adapters-arrow = { module = "com.github.skydoves:retrofit-adapters-arrow", version.ref = "retrofitAdaptersArrow" } retrofit2-kotlinx-serialization-converter = { module = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter", version.ref = "retrofit2KotlinxSerializationConverter" } +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } From 67669bddae057cb7bc621450a5cb0041b51c3cd2 Mon Sep 17 00:00:00 2001 From: KaulH Date: Sat, 30 Mar 2024 15:45:18 +0100 Subject: [PATCH 5/5] apply suggestions --- .../java/com/iqball/app/page/LoginPage.kt | 31 ++++++++++++------- .../java/com/iqball/app/page/RegisterPage.kt | 31 +++++++++++++------ 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/iqball/app/page/LoginPage.kt b/app/src/main/java/com/iqball/app/page/LoginPage.kt index f1cd62e..9c30099 100644 --- a/app/src/main/java/com/iqball/app/page/LoginPage.kt +++ b/app/src/main/java/com/iqball/app/page/LoginPage.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.foundation.layout.* import androidx.compose.material3.Button import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Surface import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -18,7 +19,6 @@ import com.iqball.app.api.service.AuthService import com.iqball.app.session.Authentication import kotlinx.coroutines.runBlocking - @Composable fun LoginPage( service: AuthService, @@ -45,21 +45,24 @@ fun LoginPage( fontSize = 28.sp, color = Color.Black ) - Spacer(modifier = Modifier.height(16.dp)) - errors?.let { message -> - Text( - text = message, - color = Color.Red, - fontSize = 14.sp, - modifier = Modifier.padding(vertical = 8.dp) - ) - } + + Text( + text = errors, + color = Color.Red, + fontSize = 14.sp, + modifier = Modifier.padding(vertical = 8.dp) + ) + Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( value = email, onValueChange = { email = it }, label = { Text("Email") }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedTextColor = Color.Black, + unfocusedTextColor = Color.Black + ) ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( @@ -67,7 +70,11 @@ fun LoginPage( onValueChange = { password = it }, label = { Text("Password") }, visualTransformation = PasswordVisualTransformation(), - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedTextColor = Color.Black, + unfocusedTextColor = Color.Black + ) ) Spacer(modifier = Modifier.height(16.dp)) diff --git a/app/src/main/java/com/iqball/app/page/RegisterPage.kt b/app/src/main/java/com/iqball/app/page/RegisterPage.kt index ce91d21..898ca43 100644 --- a/app/src/main/java/com/iqball/app/page/RegisterPage.kt +++ b/app/src/main/java/com/iqball/app/page/RegisterPage.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -56,20 +57,22 @@ fun RegisterPage( color = Color.Black ) Spacer(modifier = Modifier.height(16.dp)) - errors?.let { message -> - Text( - text = message, - color = Color.Red, - fontSize = 14.sp, - modifier = Modifier.padding(vertical = 8.dp) - ) - } + Text( + text = errors, + color = Color.Red, + fontSize = 14.sp, + modifier = Modifier.padding(vertical = 8.dp) + ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( value = username, onValueChange = { username = it }, label = { Text("Nom d'utilisateur") }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedTextColor = Color.Black, + unfocusedTextColor = Color.Black + ) ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( @@ -77,6 +80,10 @@ fun RegisterPage( onValueChange = { password = it }, label = { Text("Mot de passe") }, modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedTextColor = Color.Black, + unfocusedTextColor = Color.Black + ), visualTransformation = PasswordVisualTransformation() ) Spacer(modifier = Modifier.height(16.dp)) @@ -84,7 +91,11 @@ fun RegisterPage( value = email, onValueChange = { email = it }, label = { Text("Email") }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedTextColor = Color.Black, + unfocusedTextColor = Color.Black + ) ) Button(onClick = { runBlocking {