diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/co.touchlab-sqliter-driver-1.3.1-appleMain-cinterop/co.touchlab_sqliter-driver-cinterop-sqlite3-jZj4Kg.klib b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/co.touchlab-sqliter-driver-1.3.1-appleMain-cinterop/co.touchlab_sqliter-driver-cinterop-sqlite3-jZj4Kg.klib
index 92b485ff0..b53519622 100644
Binary files a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/co.touchlab-sqliter-driver-1.3.1-appleMain-cinterop/co.touchlab_sqliter-driver-cinterop-sqlite3-jZj4Kg.klib and b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/co.touchlab-sqliter-driver-1.3.1-appleMain-cinterop/co.touchlab_sqliter-driver-cinterop-sqlite3-jZj4Kg.klib differ
diff --git a/composeApp/src/commonMain/composeResources/values-es/strings.xml b/composeApp/src/commonMain/composeResources/values-es/strings.xml
index 34f642587..6cfe1635f 100644
--- a/composeApp/src/commonMain/composeResources/values-es/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values-es/strings.xml
@@ -296,4 +296,7 @@
Eliminar Scope
Habla con MoreStuff IA.
+
+ Reenviar código
+ Podrás reenviar el código en %s segundos
\ No newline at end of file
diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 116100390..6a92700a7 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -311,4 +311,8 @@
The email address is invalid or does not exist.
An error occurred. Please try again.
Chat with MoreStuff AI.
+
+
+ Resend code
+ You can resend the code in %s seconds
diff --git a/composeApp/src/commonMain/kotlin/io/middlepoint/morestuff/shared/ui/screen/onboarding/OnBoardingSignInEmailScreen.kt b/composeApp/src/commonMain/kotlin/io/middlepoint/morestuff/shared/ui/screen/onboarding/OnBoardingSignInEmailScreen.kt
index bc706db87..8fa830799 100644
--- a/composeApp/src/commonMain/kotlin/io/middlepoint/morestuff/shared/ui/screen/onboarding/OnBoardingSignInEmailScreen.kt
+++ b/composeApp/src/commonMain/kotlin/io/middlepoint/morestuff/shared/ui/screen/onboarding/OnBoardingSignInEmailScreen.kt
@@ -1,24 +1,31 @@
package io.middlepoint.morestuff.shared.ui.screen.onboarding
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Email
import androidx.compose.material.icons.filled.VpnKey
import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
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
@@ -26,6 +33,7 @@ import androidx.compose.runtime.rememberCoroutineScope
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.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
@@ -35,6 +43,8 @@ import io.github.jan.supabase.SupabaseClient
import io.github.jan.supabase.auth.OtpType
import io.github.jan.supabase.auth.auth
import io.github.jan.supabase.auth.providers.builtin.OTP
+import io.middlepoint.morestuff.shared.ui.theme.onBoardingBrush
+import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import morestuff.composeapp.generated.resources.Res
import morestuff.composeapp.generated.resources.`continue`
@@ -43,8 +53,12 @@ import morestuff.composeapp.generated.resources.enter_code_sent_to_email
import morestuff.composeapp.generated.resources.enter_your_email
import morestuff.composeapp.generated.resources.error_generic
import morestuff.composeapp.generated.resources.error_invalid_email
+import morestuff.composeapp.generated.resources.ms_sign_in
+import morestuff.composeapp.generated.resources.resend_code
+import morestuff.composeapp.generated.resources.seconds_to_resend
import morestuff.composeapp.generated.resources.six_digit_code_label
import morestuff.composeapp.generated.resources.verify
+import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.koinInject
import org.koin.core.parameter.parametersOf
@@ -65,6 +79,11 @@ fun SignInEmailScreen(
var otpCode by remember { mutableStateOf("") }
var isLoading by remember { mutableStateOf(false) }
+ var canResendOtp by remember { mutableStateOf(false) }
+ var secondsRemaining by remember { mutableStateOf(60) }
+ var hasResentOtp by remember { mutableStateOf(false) }
+
+
val sendOtpToEmail: (String, () -> Unit, (String) -> Unit) -> Unit = { email, onSent, onError ->
scope.launch {
isLoading = true
@@ -73,6 +92,8 @@ fun SignInEmailScreen(
this.email = email
}
onSent()
+ secondsRemaining = 60
+ canResendOtp = false
} catch (e: Exception) {
logger.e(e) { "Error sending otp to email" }
emailError = when {
@@ -109,23 +130,48 @@ fun SignInEmailScreen(
}
}
+ LaunchedEffect(isEmailSent) {
+ if (isEmailSent && !hasResentOtp) {
+ secondsRemaining = 60
+ canResendOtp = false
+ while (secondsRemaining > 0) {
+ delay(1000)
+ secondsRemaining--
+ }
+ canResendOtp = true
+ }
+ }
+
+ val background = remember { onBoardingBrush }
+
Box(
modifier = Modifier
.fillMaxSize()
+ .background(background)
.imePadding()
) {
Column(
modifier = Modifier
.fillMaxSize()
- .padding(32.dp),
+ .windowInsetsPadding(WindowInsets.safeDrawing)
+ .padding(horizontal = 32.dp)
+ .padding(bottom = 150.dp),
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center
+ verticalArrangement = Arrangement.SpaceBetween
) {
+ Spacer(modifier = Modifier.weight(0.4f))
+ Icon(
+ painter = painterResource(Res.drawable.ms_sign_in),
+ tint = Color.Unspecified,
+ contentDescription = "signIn",
+ )
+ //Spacer(modifier = Modifier.height(32.dp))
+ Spacer(modifier = Modifier.weight(0.6f))
Text(
text = if (!isEmailSent) stringResource(Res.string.enter_your_email)
else stringResource(Res.string.enter_code_sent_to_email, email.text),
style = MaterialTheme.typography.titleMedium,
- color = MaterialTheme.colorScheme.onSurface
+ color = Color.White
)
Spacer(modifier = Modifier.height(16.dp))
@@ -137,12 +183,12 @@ fun SignInEmailScreen(
emailError = null
}
},
- label = { Text(stringResource(Res.string.email_label)) },
+ label = { Text(text = stringResource(Res.string.email_label), color = Color.White) },
leadingIcon = {
Icon(
imageVector = Icons.Default.Email,
contentDescription = null,
- tint = MaterialTheme.colorScheme.primary
+ tint = Color.White
)
},
singleLine = true,
@@ -170,12 +216,17 @@ fun SignInEmailScreen(
OutlinedTextField(
value = otpCode,
onValueChange = { if (it.length <= 6) otpCode = it },
- label = { Text(stringResource(Res.string.six_digit_code_label)) },
+ label = {
+ Text(
+ text = stringResource(Res.string.six_digit_code_label),
+ color = Color.White
+ )
+ },
leadingIcon = {
Icon(
imageVector = Icons.Default.VpnKey,
contentDescription = null,
- tint = MaterialTheme.colorScheme.primary
+ tint = Color.White
)
},
singleLine = true,
@@ -186,6 +237,45 @@ fun SignInEmailScreen(
),
modifier = Modifier.fillMaxWidth()
)
+
+
+ Spacer(modifier = Modifier.height(8.dp))
+ if (!hasResentOtp) {
+ if (!canResendOtp) {
+ Text(
+ text = stringResource(Res.string.seconds_to_resend).replace(
+ "%s",
+ "$secondsRemaining"
+ ),
+ color = Color.White.copy(alpha = 0.7f),
+ style = MaterialTheme.typography.bodySmall
+ )
+ } else {
+ TextButton(
+ onClick = {
+ sendOtpToEmail(
+ email.text,
+ {
+ hasResentOtp = true
+ canResendOtp = false
+ },
+ {}
+ )
+ },
+ enabled = !isLoading,
+ colors = ButtonDefaults.outlinedButtonColors(
+ contentColor = Color.White,
+ containerColor = Color(0xFF393AC5),
+ disabledContainerColor = Color(0xFF393AC5).copy(alpha = 0.5f)
+ ),
+ ) {
+ Text(
+ text = stringResource(Res.string.resend_code),
+ color = Color.White
+ )
+ }
+ }
+ }
}
Spacer(modifier = Modifier.height(24.dp))
@@ -199,10 +289,15 @@ fun SignInEmailScreen(
{}
)
},
+ colors = ButtonDefaults.outlinedButtonColors(
+ contentColor = Color.White,
+ containerColor = Color(0xFF393AC5),
+ disabledContainerColor = Color(0xFF393AC5).copy(alpha = 0.5f)
+ ),
enabled = isValidEmail(email.text) && !isLoading,
modifier = Modifier.fillMaxWidth()
) {
- Text(stringResource(Res.string.`continue`))
+ Text(text = stringResource(Res.string.`continue`), color = Color.White)
}
} else {
Button(
@@ -212,10 +307,15 @@ fun SignInEmailScreen(
otpCode
) { }
},
+ colors = ButtonDefaults.outlinedButtonColors(
+ contentColor = Color.White,
+ containerColor = Color(0xFF393AC5),
+ disabledContainerColor = Color(0xFF393AC5).copy(alpha = 0.5f)
+ ),
enabled = otpCode.length == 6 && !isLoading,
modifier = Modifier.fillMaxWidth()
) {
- Text(stringResource(Res.string.verify))
+ Text(text = stringResource(Res.string.verify), color = Color.White)
}
}
}