Fiddling with the login and signup screens
This commit is contained in:
parent
ecea0e12d6
commit
45d632f786
7 changed files with 180 additions and 35 deletions
|
@ -64,6 +64,8 @@ dependencies {
|
||||||
implementation(libs.androidx.ui.graphics)
|
implementation(libs.androidx.ui.graphics)
|
||||||
implementation(libs.androidx.ui.tooling.preview)
|
implementation(libs.androidx.ui.tooling.preview)
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
|
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||||
|
implementation(libs.lifecycle.runtime.compose)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -10,13 +9,12 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.DebtPirate"
|
android:theme="@style/Theme.DebtPirate">
|
||||||
tools:targetApi="31">
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/title_activity_main"
|
android:theme="@style/Theme.DebtPirate"
|
||||||
android:theme="@style/Theme.DebtPirate">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,14 @@ import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.activity.viewModels
|
||||||
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 kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import software.makeshift.debtpirate.ui.theme.DebtPirateTheme
|
import software.makeshift.debtpirate.ui.theme.DebtPirateTheme
|
||||||
import software.makeshift.debtpirate.usecases.login.LoginScreen
|
import software.makeshift.debtpirate.usecases.login.LoginScreen
|
||||||
|
import software.makeshift.debtpirate.usecases.login.LoginScreenViewModel
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
object LoginRoute
|
object LoginRoute
|
||||||
|
@ -24,7 +26,11 @@ class MainActivity : ComponentActivity() {
|
||||||
DebtPirateTheme {
|
DebtPirateTheme {
|
||||||
NavHost(navController = navController, startDestination = LoginRoute) {
|
NavHost(navController = navController, startDestination = LoginRoute) {
|
||||||
composable<LoginRoute> {
|
composable<LoginRoute> {
|
||||||
LoginScreen()
|
val viewModel: LoginScreenViewModel by viewModels()
|
||||||
|
LoginScreen(
|
||||||
|
viewModel.loginState,
|
||||||
|
viewModel::updateLoginUsername
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,123 @@
|
||||||
|
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|
||||||
package software.makeshift.debtpirate.usecases.login
|
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.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.Scaffold
|
||||||
|
import androidx.compose.material3.SecondaryTabRow
|
||||||
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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
|
@Composable
|
||||||
fun LoginScreen() {
|
fun LoginScreen(
|
||||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
loginState: StateFlow<LoginState>,
|
||||||
Greeting(modifier = Modifier.padding(innerPadding))
|
updateLoginUsername: (String) -> Unit
|
||||||
}
|
) {
|
||||||
}
|
Scaffold(modifier = Modifier.fillMaxSize()) {
|
||||||
|
Column {
|
||||||
|
Banner(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
@Composable
|
LoginAndSignUpForms(
|
||||||
private fun Greeting(modifier: Modifier = Modifier) {
|
loginState,
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = "Hello from Login!",
|
.weight(3f)
|
||||||
modifier = modifier
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
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<LoginState>,
|
||||||
|
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<LoginState>, onUsernameUpdate: (String) -> Unit, onPasswordUpdate: (String) -> Unit) {
|
||||||
|
// Column {
|
||||||
|
// OutlinedTextField(value = , onValueChange = )
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -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<String?>
|
||||||
|
get() = loginState.map { loginState -> loginState.username }
|
||||||
|
|
||||||
|
fun updateLoginUsername(username: String) {
|
||||||
|
_loginState.update { state ->
|
||||||
|
val (_, password) = state
|
||||||
|
LoginState(username, password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Debt Pirate</string>
|
<string name="app_name">Debt Pirate</string>
|
||||||
<string name="title_activity_main">MainActivity</string>
|
|
||||||
|
<!-- Login Screen -->
|
||||||
|
<string name="loginscreen_logintab_logintitle">Login</string>
|
||||||
|
<string name="loginscreen_logintab_signuptitle">Sign Up</string>
|
||||||
</resources>
|
</resources>
|
|
@ -9,6 +9,8 @@ appcompat = "1.7.0"
|
||||||
material = "1.12.0"
|
material = "1.12.0"
|
||||||
material3 = "1.3.0-beta05"
|
material3 = "1.3.0-beta05"
|
||||||
kotlinxSerializationJson = "1.7.1"
|
kotlinxSerializationJson = "1.7.1"
|
||||||
|
lifecycleRuntimeCompose = "2.8.4"
|
||||||
|
lifecycleViewmodelCompose = "2.8.4"
|
||||||
lifecycleRuntimeKtx = "2.8.4"
|
lifecycleRuntimeKtx = "2.8.4"
|
||||||
activityCompose = "1.9.1"
|
activityCompose = "1.9.1"
|
||||||
composeBom = "2024.06.00"
|
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" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||||
kotlinx-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
|
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-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-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||||
|
|
Loading…
Add table
Reference in a new issue