From 45d632f7868ee7c8d7b203aae3e6f107eff43b55 Mon Sep 17 00:00:00 2001 From: "Z. Charles Dziura" Date: Sat, 17 Aug 2024 21:48:49 -0400 Subject: [PATCH] Fiddling with the login and signup screens --- app/app/build.gradle.kts | 2 + app/app/src/main/AndroidManifest.xml | 44 +++---- .../makeshift/debtpirate/MainActivity.kt | 8 +- .../debtpirate/usecases/login/LoginScreen.kt | 120 ++++++++++++++++-- .../usecases/login/LoginViewModel.kt | 32 +++++ app/app/src/main/res/values/strings.xml | 5 +- app/gradle/libs.versions.toml | 4 + 7 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginViewModel.kt diff --git a/app/app/build.gradle.kts b/app/app/build.gradle.kts index 28807c5..d45b897 100644 --- a/app/app/build.gradle.kts +++ b/app/app/build.gradle.kts @@ -64,6 +64,8 @@ dependencies { implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.lifecycle.viewmodel.compose) + implementation(libs.lifecycle.runtime.compose) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/app/src/main/AndroidManifest.xml b/app/app/src/main/AndroidManifest.xml index e60914e..b2712bc 100644 --- a/app/app/src/main/AndroidManifest.xml +++ b/app/app/src/main/AndroidManifest.xml @@ -1,28 +1,26 @@ - + - - - - + + + + - - - - + + + + \ No newline at end of file diff --git a/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt b/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt index 26ee1b1..a28d08c 100644 --- a/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt +++ b/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt @@ -4,12 +4,14 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import kotlinx.serialization.Serializable import software.makeshift.debtpirate.ui.theme.DebtPirateTheme import software.makeshift.debtpirate.usecases.login.LoginScreen +import software.makeshift.debtpirate.usecases.login.LoginScreenViewModel @Serializable object LoginRoute @@ -24,7 +26,11 @@ class MainActivity : ComponentActivity() { DebtPirateTheme { NavHost(navController = navController, startDestination = LoginRoute) { composable { - LoginScreen() + val viewModel: LoginScreenViewModel by viewModels() + LoginScreen( + viewModel.loginState, + viewModel::updateLoginUsername + ) } } } diff --git a/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginScreen.kt b/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginScreen.kt index 5dd607f..9e8f9d2 100644 --- a/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginScreen.kt +++ b/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginScreen.kt @@ -1,23 +1,123 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + package software.makeshift.debtpirate.usecases.login +import android.annotation.SuppressLint +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.SecondaryTabRow +import androidx.compose.material3.Tab import androidx.compose.material3.Text import androidx.compose.runtime.Composable +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.unit.dp +import kotlinx.coroutines.flow.StateFlow +import software.makeshift.debtpirate.R +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -fun LoginScreen() { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - Greeting(modifier = Modifier.padding(innerPadding)) +fun LoginScreen( + loginState: StateFlow, + updateLoginUsername: (String) -> Unit +) { + Scaffold(modifier = Modifier.fillMaxSize()) { + Column { + Banner( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + ) + + LoginAndSignUpForms( + loginState, + modifier = Modifier + .weight(3f) + ) + } } } @Composable -private fun Greeting(modifier: Modifier = Modifier) { - Text( - text = "Hello from Login!", - modifier = modifier - ) -} \ No newline at end of file +private fun Banner(modifier: Modifier = Modifier) { + Box(modifier = modifier.background(Color.Green)) { + Text( + text = "Hello from Login! I'm in a box!", + modifier = Modifier.align(Alignment.Center) + ) + } +} + +@Composable +private fun LoginAndSignUpForms( + loginTabState: StateFlow, + modifier: Modifier = Modifier +) { + Column(modifier = modifier) { + val pagerState = rememberPagerState(initialPage = 0) { 2 } + + SecondaryTabRow( + selectedTabIndex = pagerState.currentPage, + modifier = Modifier.height(48.dp) + ) { + val tabTextStyle = MaterialTheme.typography.titleLarge + Tab( + selected = pagerState.currentPage == 0, + onClick = { pagerState.requestScrollToPage(0) }, + modifier = Modifier.fillMaxHeight() + ) { + Text( + text = stringResource(id = R.string.loginscreen_logintab_logintitle), + style = tabTextStyle, + modifier = Modifier.fillMaxHeight() + ) + } + Tab( + selected = pagerState.currentPage == 1, + onClick = { pagerState.requestScrollToPage(1) }, + modifier = Modifier.fillMaxHeight() + ) { + Text( + text = stringResource(id = R.string.loginscreen_logintab_signuptitle), + style = tabTextStyle, + modifier = Modifier.fillMaxHeight() + ) + } + } + + HorizontalPager( + state = pagerState, + userScrollEnabled = false, + modifier = Modifier.fillMaxSize() + ) { page -> + when (page) { + 0 -> { + Text("Page 1!") + } + + 1 -> { + Text("Page 2!") + } + } + } + } +} + +//@Composable +//private fun LoginForm(state: StateFlow, onUsernameUpdate: (String) -> Unit, onPasswordUpdate: (String) -> Unit) { +// Column { +// OutlinedTextField(value = , onValueChange = ) +// } +//} \ No newline at end of file diff --git a/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginViewModel.kt b/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginViewModel.kt new file mode 100644 index 0000000..72f020a --- /dev/null +++ b/app/app/src/main/java/software/makeshift/debtpirate/usecases/login/LoginViewModel.kt @@ -0,0 +1,32 @@ +package software.makeshift.debtpirate.usecases.login + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.update + +data class LoginState(val username: String? = null, val password: String? = null) + +data class SignUpState( + val username: String? = null, + val password: String? = null, + val passwordConfirmed: String? = null, + val email: String? = null +) + +class LoginScreenViewModel : ViewModel() { + private val _loginState = MutableStateFlow(LoginState()) + val loginState = _loginState.asStateFlow() + + val loginUsername: Flow + get() = loginState.map { loginState -> loginState.username } + + fun updateLoginUsername(username: String) { + _loginState.update { state -> + val (_, password) = state + LoginState(username, password) + } + } +} \ 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 ff01224..0265931 100644 --- a/app/app/src/main/res/values/strings.xml +++ b/app/app/src/main/res/values/strings.xml @@ -1,4 +1,7 @@ Debt Pirate - MainActivity + + + Login + Sign Up \ No newline at end of file diff --git a/app/gradle/libs.versions.toml b/app/gradle/libs.versions.toml index 421e9cd..bc84319 100644 --- a/app/gradle/libs.versions.toml +++ b/app/gradle/libs.versions.toml @@ -9,6 +9,8 @@ appcompat = "1.7.0" material = "1.12.0" material3 = "1.3.0-beta05" kotlinxSerializationJson = "1.7.1" +lifecycleRuntimeCompose = "2.8.4" +lifecycleViewmodelCompose = "2.8.4" lifecycleRuntimeKtx = "2.8.4" activityCompose = "1.9.1" composeBom = "2024.06.00" @@ -23,6 +25,8 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version material = { group = "com.google.android.material", name = "material", version.ref = "material" } material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } kotlinx-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" } +androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }