diff --git a/app/app/build.gradle.kts b/app/app/build.gradle.kts index d41f3e7..32681a4 100644 --- a/app/app/build.gradle.kts +++ b/app/app/build.gradle.kts @@ -31,7 +31,7 @@ android { ) } debug { - buildConfigField("String", "API_BASE_URL", "\"http://localhost:42069\"") + buildConfigField("String", "API_BASE_URL", "\"http://10.0.2.2:42069\"") } } compileOptions { diff --git a/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/AuthScreen.kt b/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/AuthScreen.kt index deddf2b..ffd6350 100644 --- a/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/AuthScreen.kt +++ b/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/AuthScreen.kt @@ -8,16 +8,33 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row 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.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Key +import androidx.compose.material.icons.outlined.Mail +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material3.Button +import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import software.patchwork.debtpirate.R @@ -28,48 +45,143 @@ fun AuthScreen( ) { Scaffold( modifier = Modifier.fillMaxSize() - ) { innerPadding -> + ) { Column { AuthScreenTopAppBar( - innerPadding, modifier = Modifier .fillMaxWidth() .weight(1f) ) - val displayName = viewModel.displayName.collectAsState() - val emailAddress = viewModel.emailAddress.collectAsState() - SignUpScreen( - displayName, - onDisplayNameUpdate = viewModel::updateDisplayName, - emailAddress, - onEmailAddressUpdate = viewModel::updateEmailAddress, + Column( modifier = Modifier .weight(3f) .padding(16.dp) - ) + ) { + val displayName = viewModel.displayName.collectAsState() + val emailAddress = viewModel.emailAddress.collectAsState() + RegistrationScreen( + displayName, + onDisplayNameUpdate = viewModel::updateDisplayName, + emailAddress, + onEmailAddressUpdate = viewModel::updateEmailAddress + ) + + Separator(modifier = Modifier.padding(PaddingValues(top = 24.dp, bottom = 24.dp))) + + PassKeyButton() + } } } } @Composable -private fun AuthScreenTopAppBar(innerPadding: PaddingValues, modifier: Modifier = Modifier) { +private fun AuthScreenTopAppBar(modifier: Modifier = Modifier) { Box(modifier = modifier.background(Color.Green)) { Text( text = "Hello from Login! I'm in a box!", modifier = Modifier.align(Alignment.Center) ) + } +} - Row( +@Composable +private fun Separator(modifier: Modifier = Modifier) { + Row(modifier = modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { + Box( modifier = Modifier - .align(Alignment.TopEnd) - .padding(innerPadding) - .padding(16.dp) + .height(2.dp) + .weight(4.5f) + .background(Color.LightGray) + ) {} + + Text( + text = "OR", + style = TextStyle( + textAlign = TextAlign.Center, + color = Color.Gray + ), + modifier = Modifier.weight(1f) ) - { - OutlinedButton(onClick = { /*TODO*/ }) { - Text(stringResource(id = R.string.login_screen__sign_in)) - } + + Box( + modifier = Modifier + .height(2.dp) + .weight(4.5f) + .background(Color.LightGray) + ) {} + } +} + +@Composable +private fun RegistrationScreen( + displayName: State, + onDisplayNameUpdate: (String) -> Unit, + emailAddress: State, + onEmailAddressUpdate: (String) -> Unit, + modifier: Modifier = Modifier +) { + Column(modifier.verticalScroll(rememberScrollState())) + { + OutlinedTextField( + value = displayName.value, + label = { Text(stringResource(id = R.string.auth_screen__display_name)) }, + placeholder = { Text(stringResource(id = R.string.auth_screen__display_name)) }, + leadingIcon = { Icon(Icons.Outlined.Person, "person") }, + singleLine = true, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Words, + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next + ), + onValueChange = onDisplayNameUpdate, + modifier = Modifier.fillMaxWidth() + ) + + OutlinedTextField( + value = emailAddress.value, + label = { Text(stringResource(id = R.string.auth_screen__email)) }, + placeholder = { Text(stringResource(id = R.string.auth_screen__email)) }, + leadingIcon = { Icon(Icons.Outlined.Mail, "email") }, + singleLine = true, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Unspecified, + keyboardType = KeyboardType.Email, + imeAction = ImeAction.Next + ), + onValueChange = onEmailAddressUpdate, + modifier = Modifier + .fillMaxWidth() + .padding(PaddingValues(top = 8.dp)) + ) + + Button( + onClick = { /*TODO*/ }, + modifier = Modifier + .padding(PaddingValues(top = 16.dp)) + .fillMaxWidth() + ) { + Text(stringResource(id = R.string.auth_screen__register)) + } + } +} + +@Composable +private fun PassKeyButton() { + OutlinedButton( + onClick = { /*TODO*/ }, + modifier = Modifier + .fillMaxWidth() + ) { + Box(modifier = Modifier.fillMaxWidth()) { + Icon(Icons.Outlined.Key, "passkey") + Text( + stringResource(id = R.string.auth_screen__sign_in), + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + ) } } } \ No newline at end of file diff --git a/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/SignInScreen.kt b/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/SignInScreen.kt deleted file mode 100644 index 1beb754..0000000 --- a/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/SignInScreen.kt +++ /dev/null @@ -1,124 +0,0 @@ -package software.patchwork.debtpirate.screens.auth - -import android.util.Log -import androidx.compose.foundation.interaction.FocusInteraction -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Lock -import androidx.compose.material.icons.outlined.Person -import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.LinkAnnotation -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.TextLinkStyles -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardCapitalization -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.withLink -import androidx.compose.ui.unit.dp -import kotlinx.coroutines.flow.StateFlow -import software.patchwork.debtpirate.R - -@Composable -internal fun SignInScreen( - usernameState: StateFlow, - passwordState: StateFlow, - onUsernameUpdate: (String) -> Unit, - onPasswordUpdate: (String) -> Unit, - modifier: Modifier = Modifier, -) { - Column( - modifier.verticalScroll(rememberScrollState()) - ) { - val username = usernameState.collectAsState() - OutlinedTextField( - value = username.value, - label = { Text(stringResource(id = R.string.login_screen__username)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__username)) }, - leadingIcon = { Icon(Icons.Outlined.Person, "person") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Unspecified, - keyboardType = KeyboardType.Email, - imeAction = ImeAction.Next - ), - onValueChange = onUsernameUpdate, - interactionSource = remember { MutableInteractionSource() }.also { source -> - LaunchedEffect(source) { - source.interactions.collect { interaction -> - when (interaction) { - is FocusInteraction -> Log.v( - "LoginScreen::LoginForm::usernameTextField", - "Clicked!" - ) - } - } - } - }, - modifier = Modifier - .fillMaxWidth() - ) - - val password = passwordState.collectAsState() - OutlinedTextField( - value = password.value, - label = { Text(stringResource(id = R.string.login_screen__password)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__password)) }, - leadingIcon = { Icon(Icons.Outlined.Lock, "password") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Unspecified, - keyboardType = KeyboardType.Password, - imeAction = ImeAction.Send - ), - visualTransformation = PasswordVisualTransformation(), - onValueChange = onPasswordUpdate, - modifier = Modifier - .fillMaxWidth() - .padding(PaddingValues(top = 8.dp)) - ) - - Text( - text = buildAnnotatedString { - withLink( - LinkAnnotation.Url( - "", TextLinkStyles( - style = SpanStyle( - color = Color.Gray - ) - ) - ) - ) { - append(stringResource(id = R.string.login_screen__forgot_password)) - } - }, - modifier = Modifier.padding(PaddingValues(top = 16.dp)) - ) - Button( - onClick = { /*TODO*/ }, - modifier = Modifier - .padding(PaddingValues(top = 32.dp)) - .fillMaxWidth() - ) { - Text(stringResource(id = R.string.login_screen__sign_in)) - } - } -} \ No newline at end of file diff --git a/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/SignUpScreen.kt b/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/SignUpScreen.kt deleted file mode 100644 index 9472e26..0000000 --- a/app/app/src/main/java/software/patchwork/debtpirate/screens/auth/SignUpScreen.kt +++ /dev/null @@ -1,78 +0,0 @@ -package software.patchwork.debtpirate.screens.auth - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Mail -import androidx.compose.material.icons.outlined.Person -import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardCapitalization -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.unit.dp -import software.patchwork.debtpirate.R - -@Composable -internal fun SignUpScreen( - displayName: State, - onDisplayNameUpdate: (String) -> Unit, - emailAddress: State, - onEmailAddressUpdate: (String) -> Unit, - modifier: Modifier = Modifier -) { - Column(modifier.verticalScroll(rememberScrollState())) - { - OutlinedTextField( - value = displayName.value, - label = { Text(stringResource(id = R.string.login_screen__display_name)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__display_name)) }, - leadingIcon = { Icon(Icons.Outlined.Person, "person") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Words, - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ), - onValueChange = onDisplayNameUpdate, - modifier = Modifier.fillMaxWidth() - ) - - OutlinedTextField( - value = emailAddress.value, - label = { Text(stringResource(id = R.string.login_screen__email)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__email)) }, - leadingIcon = { Icon(Icons.Outlined.Mail, "email") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Unspecified, - keyboardType = KeyboardType.Email, - imeAction = ImeAction.Next - ), - onValueChange = onEmailAddressUpdate, - modifier = Modifier - .fillMaxWidth() - .padding(PaddingValues(top = 8.dp)) - ) - - Button( - onClick = { /*TODO*/ }, - modifier = Modifier - .padding(PaddingValues(top = 32.dp)) - .fillMaxWidth() - ) { - Text(stringResource(id = R.string.login_screen__signup)) - } - } -} \ No newline at end of file diff --git a/app/app/src/main/res/values/strings.xml b/app/app/src/main/res/values/strings.xml index 591842d..aac59a8 100644 --- a/app/app/src/main/res/values/strings.xml +++ b/app/app/src/main/res/values/strings.xml @@ -1,14 +1,10 @@ Debt Pirate - - Sign In - Sign Up - Username - Email Address - Password - Confirm Password - Display Name - Forgot Password? + + Register + Sign in with a Passkey + Email Address + Display Name \ No newline at end of file diff --git a/app/gradle/libs.versions.toml b/app/gradle/libs.versions.toml index 7087d97..69a3dc1 100644 --- a/app/gradle/libs.versions.toml +++ b/app/gradle/libs.versions.toml @@ -30,7 +30,7 @@ androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-co androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" } -androidx-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended-android", version.ref = "iconsExtended" } +androidx-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version.ref = "iconsExtended" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } androidx-navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "navigation" } androidx-ui = { group = "androidx.compose.ui", name = "ui" }