Create login module
This commit is contained in:
parent
94d031ffce
commit
a18d272462
13 changed files with 224 additions and 37 deletions
|
|
@ -47,6 +47,7 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":libraries:ui:theme")
|
implementation project(":libraries:ui:theme")
|
||||||
|
implementation project(":libraries:ui:screens:login")
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.9.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
implementation "androidx.compose.ui:ui:$compose_version"
|
implementation "androidx.compose.ui:ui:$compose_version"
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,10 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.ElementX"
|
android:theme="@style/Theme.ElementX"
|
||||||
tools:targetApi="31">
|
tools:targetApi="33">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true">
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@style/Theme.ElementX">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,16 @@
|
||||||
package io.element.android.x
|
package io.element.android.x
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import io.element.android.x.ui.screen.login.LoginActivity
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import io.element.android.x.ui.theme.ElementXTheme
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContent {
|
// Just start the LoginActivity for now.
|
||||||
ElementXTheme {
|
// TODO if a session exist, start the room list
|
||||||
// A surface container using the 'background' color from the theme
|
startActivity(Intent(this, LoginActivity::class.java))
|
||||||
Surface(
|
finish()
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
color = MaterialTheme.colorScheme.background
|
|
||||||
) {
|
|
||||||
Greeting("Android")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Greeting(name: String) {
|
|
||||||
Text(text = "Hello $name!")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
fun DefaultPreview() {
|
|
||||||
ElementXTheme {
|
|
||||||
Greeting("Android")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
57
libraries/ui/screens/login/build.gradle
Normal file
57
libraries/ui/screens/login/build.gradle
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'org.jetbrains.kotlin.android'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace 'io.element.android.x.ui.screen.login'
|
||||||
|
compileSdk 33
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk 29
|
||||||
|
targetSdk 33
|
||||||
|
|
||||||
|
consumerProguardFiles "consumer-rules.pro"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
buildFeatures {
|
||||||
|
compose true
|
||||||
|
}
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion compose_version
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(":libraries:ui:theme")
|
||||||
|
|
||||||
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||||
|
|
||||||
|
implementation 'com.google.android.material:material:1.6.1'
|
||||||
|
|
||||||
|
implementation "androidx.compose.ui:ui:$compose_version"
|
||||||
|
implementation 'androidx.compose.material3:material3:1.0.0-rc01'
|
||||||
|
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
||||||
|
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
|
||||||
|
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
|
||||||
|
|
||||||
|
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
|
||||||
|
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
|
||||||
|
implementation 'androidx.activity:activity-compose:1.6.0'
|
||||||
|
|
||||||
|
implementation 'androidx.fragment:fragment-ktx:1.5.3'
|
||||||
|
}
|
||||||
8
libraries/ui/screens/login/src/main/AndroidManifest.xml
Normal file
8
libraries/ui/screens/login/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity android:name="LoginActivity" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
|
sealed interface LoginActions {
|
||||||
|
data class SetLogin(val login: String) : LoginActions
|
||||||
|
data class SetPassword(val password: String) : LoginActions
|
||||||
|
object Submit : LoginActions
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.element.android.x.ui.theme.ElementXTheme
|
||||||
|
import io.element.android.x.ui.theme.components.VectorButton
|
||||||
|
import io.element.android.x.ui.theme.components.VectorTextField
|
||||||
|
|
||||||
|
class LoginActivity : ComponentActivity() {
|
||||||
|
|
||||||
|
private val viewModel: LoginViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
ElementXTheme {
|
||||||
|
// A surface container using the 'background' color from the theme
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp),
|
||||||
|
color = MaterialTheme.colorScheme.background
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
val state = viewModel.state.collectAsState().value
|
||||||
|
VectorTextField(
|
||||||
|
value = state.login,
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.handle(LoginActions.SetLogin(it))
|
||||||
|
})
|
||||||
|
VectorTextField(
|
||||||
|
value = state.password,
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.handle(LoginActions.SetPassword(it))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
VectorButton(
|
||||||
|
text = "Submit",
|
||||||
|
onClick = {
|
||||||
|
viewModel.handle(LoginActions.Submit)
|
||||||
|
},
|
||||||
|
enabled = state.submitEnabled,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
||||||
|
class LoginViewModel : ViewModel() {
|
||||||
|
|
||||||
|
private val _state = MutableStateFlow(LoginViewState())
|
||||||
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
fun handle(action: LoginActions) {
|
||||||
|
when (action) {
|
||||||
|
is LoginActions.SetLogin -> handleSetName(action)
|
||||||
|
is LoginActions.SetPassword -> handleSetPassword(action)
|
||||||
|
LoginActions.Submit -> handleSubmit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSubmit() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSetPassword(action: LoginActions.SetPassword) {
|
||||||
|
_state.value = _state.value.copy(
|
||||||
|
password = action.password,
|
||||||
|
submitEnabled = _state.value.login.isNotEmpty() && action.password.isNotEmpty()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSetName(action: LoginActions.SetLogin) {
|
||||||
|
_state.value = _state.value.copy(
|
||||||
|
login = action.login,
|
||||||
|
submitEnabled = action.login.isNotEmpty() && _state.value.password.isNotEmpty()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
|
data class LoginViewState(
|
||||||
|
val login: String = "",
|
||||||
|
val password: String = "",
|
||||||
|
val submitEnabled: Boolean = false,
|
||||||
|
)
|
||||||
|
|
@ -45,4 +45,6 @@ dependencies {
|
||||||
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
||||||
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
|
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
|
||||||
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
|
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
|
||||||
|
|
||||||
|
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.element.android.x.ui.theme.components
|
||||||
|
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun VectorButton(text: String, enabled: Boolean, onClick: () -> Unit) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
enabled = enabled,
|
||||||
|
) {
|
||||||
|
Text(text = text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.element.android.x.ui.theme.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun VectorTextField(value: String, onValueChange: (String) -> Unit) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -15,3 +15,4 @@ dependencyResolutionManagement {
|
||||||
rootProject.name = "ElementX"
|
rootProject.name = "ElementX"
|
||||||
include ':app'
|
include ':app'
|
||||||
include ':libraries:ui:theme'
|
include ':libraries:ui:theme'
|
||||||
|
include ':libraries:ui:screens:login'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue