Separate screen code into different files

pull/1/head
Lonami Exo 2022-10-11 20:10:31 +02:00
parent ec3ca82d59
commit aeaf831edb
4 changed files with 243 additions and 199 deletions

View File

@ -3,28 +3,11 @@ package dev.lonami.talaria
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import dev.lonami.talaria.data.DialogSource
import dev.lonami.talaria.data.MessageSource
import dev.lonami.talaria.model.Dialog
import dev.lonami.talaria.model.Message
import dev.lonami.talaria.ui.LoginScreen
import dev.lonami.talaria.ui.theme.TalariaTheme
class MainActivity : ComponentActivity() {
@ -37,186 +20,9 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Login()
LoginScreen()
}
}
}
}
}
enum class LoginStage {
ASK_PHONE,
ASK_CODE,
}
fun isPhoneValid(phone: String): Boolean = phone.trim('+', ' ').isNotEmpty()
fun isLoginCodeValid(code: String): Boolean = code.trim().count { it.isDigit() } == 5
@Composable
fun PhoneInput(phone: String, onPhoneChanged: (String) -> Unit, onSendCode: () -> Unit) {
val focusManager = LocalFocusManager.current
Text(stringResource(R.string.enter_phone))
TextField(
phone,
label = { Text(stringResource(R.string.phone_international)) },
placeholder = { Text(stringResource(R.string.phone_example)) },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Phone,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
modifier = Modifier.fillMaxWidth(),
onValueChange = onPhoneChanged
)
Spacer(Modifier.height(16.dp))
Button(
enabled = isPhoneValid(phone),
modifier = Modifier.fillMaxWidth(),
onClick = onSendCode
) {
Text(stringResource(R.string.send_otp))
}
}
@Composable
fun OtpInput(otp: String, onOtpChanged: (String) -> Unit, onConfirmOtp: () -> Unit) {
val focusManager = LocalFocusManager.current
Text(stringResource(R.string.enter_otp))
TextField(
otp,
label = { Text(stringResource(R.string.otp)) },
placeholder = { Text(stringResource(R.string.otp_example)) },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
modifier = Modifier.fillMaxWidth(),
onValueChange = onOtpChanged
)
Spacer(Modifier.height(16.dp))
Button(
enabled = isLoginCodeValid(otp),
modifier = Modifier.fillMaxWidth(),
onClick = onConfirmOtp
) {
Text(stringResource(R.string.do_login))
}
}
@Composable
fun DialogCard(dialog: Dialog) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp, 16.dp)
) {
Row {
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
contentDescription = stringResource(R.string.profile_photo),
)
Column(modifier = Modifier.weight(1.0f)) {
Text(dialog.title, fontWeight = FontWeight.Bold)
Text(dialog.lastMessage)
}
Switch(dialog.pinned, enabled = false, onCheckedChange = null)
}
}
}
@Composable
fun DialogList(dialogs: List<Dialog>) {
LazyColumn {
items(dialogs.size) { DialogCard(dialogs[it]) }
}
}
@Composable
fun MessageCard(message: Message) {
Card(
elevation = 4.dp,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Column(modifier = Modifier
.fillMaxWidth()
.padding(8.dp)) {
Text(message.sender, fontWeight = FontWeight.Bold)
Text(message.text)
}
}
}
@Composable
fun MessageList(messages: List<Message>) {
LazyColumn {
items(messages.size) { MessageCard(messages[it]) }
}
}
@Composable
fun Login() {
var stage by remember { mutableStateOf(LoginStage.ASK_PHONE) }
var phone by remember { mutableStateOf("") }
var otp by remember { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center
) {
Text(
stringResource(R.string.welcome_to, stringResource(R.string.app_name)),
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
.padding(16.dp)
)
when (stage) {
LoginStage.ASK_PHONE -> PhoneInput(
phone,
onPhoneChanged = { phone = it },
onSendCode = { stage = LoginStage.ASK_CODE })
LoginStage.ASK_CODE -> OtpInput(otp, onOtpChanged = { otp = it }, onConfirmOtp = {
})
}
}
}
@Preview(showBackground = true)
@Composable
fun LoginPreview() {
TalariaTheme {
Login()
}
}
@Preview
@Composable
fun DialogPreview() {
TalariaTheme {
DialogList(
DialogSource.loadDialogs()
)
}
}
@Preview
@Composable
fun ChatPreview() {
TalariaTheme {
MessageList(
MessageSource.loadMessages()
)
}
}

View File

@ -0,0 +1,52 @@
package dev.lonami.talaria.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Card
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import dev.lonami.talaria.data.MessageSource
import dev.lonami.talaria.model.Message
import dev.lonami.talaria.ui.theme.TalariaTheme
@Composable
fun MessageCard(message: Message) {
Card(
elevation = 4.dp,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Text(message.sender, fontWeight = FontWeight.Bold)
Text(message.text)
}
}
}
@Composable
fun MessageList(messages: List<Message>) {
LazyColumn {
items(messages.size) { MessageCard(messages[it]) }
}
}
@Preview
@Composable
fun ChatPreview() {
TalariaTheme {
MessageList(
MessageSource.loadMessages()
)
}
}

View File

@ -0,0 +1,60 @@
package dev.lonami.talaria.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Card
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import dev.lonami.talaria.R
import dev.lonami.talaria.data.DialogSource
import dev.lonami.talaria.model.Dialog
import dev.lonami.talaria.ui.theme.TalariaTheme
@Composable
fun DialogCard(dialog: Dialog) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp, 16.dp)
) {
Row {
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
contentDescription = stringResource(R.string.profile_photo),
)
Column(modifier = Modifier.weight(1.0f)) {
Text(dialog.title, fontWeight = FontWeight.Bold)
Text(dialog.lastMessage)
}
Switch(dialog.pinned, enabled = false, onCheckedChange = null)
}
}
}
@Composable
fun DialogList(dialogs: List<Dialog>) {
LazyColumn {
items(dialogs.size) { DialogCard(dialogs[it]) }
}
}
@Preview
@Composable
fun DialogPreview() {
TalariaTheme {
DialogList(
DialogSource.loadDialogs()
)
}
}

View File

@ -0,0 +1,126 @@
package dev.lonami.talaria.ui
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import dev.lonami.talaria.R
import dev.lonami.talaria.ui.theme.TalariaTheme
enum class LoginStage {
ASK_PHONE,
ASK_CODE,
}
fun isPhoneValid(phone: String): Boolean = phone.trim('+', ' ').isNotEmpty()
fun isLoginCodeValid(code: String): Boolean = code.trim().count { it.isDigit() } == 5
@Composable
fun PhoneInput(phone: String, onPhoneChanged: (String) -> Unit, onSendCode: () -> Unit) {
val focusManager = LocalFocusManager.current
Text(stringResource(R.string.enter_phone))
TextField(
phone,
label = { Text(stringResource(R.string.phone_international)) },
placeholder = { Text(stringResource(R.string.phone_example)) },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Phone,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
modifier = Modifier.fillMaxWidth(),
onValueChange = onPhoneChanged
)
Spacer(Modifier.height(16.dp))
Button(
enabled = isPhoneValid(phone),
modifier = Modifier.fillMaxWidth(),
onClick = onSendCode
) {
Text(stringResource(R.string.send_otp))
}
}
@Composable
fun OtpInput(otp: String, onOtpChanged: (String) -> Unit, onConfirmOtp: () -> Unit) {
val focusManager = LocalFocusManager.current
Text(stringResource(R.string.enter_otp))
TextField(
otp,
label = { Text(stringResource(R.string.otp)) },
placeholder = { Text(stringResource(R.string.otp_example)) },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
modifier = Modifier.fillMaxWidth(),
onValueChange = onOtpChanged
)
Spacer(Modifier.height(16.dp))
Button(
enabled = isLoginCodeValid(otp),
modifier = Modifier.fillMaxWidth(),
onClick = onConfirmOtp
) {
Text(stringResource(R.string.do_login))
}
}
@Composable
fun LoginScreen() {
var stage by remember { mutableStateOf(LoginStage.ASK_PHONE) }
var phone by remember { mutableStateOf("") }
var otp by remember { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center
) {
Text(
stringResource(R.string.welcome_to, stringResource(R.string.app_name)),
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
.padding(16.dp)
)
when (stage) {
LoginStage.ASK_PHONE -> PhoneInput(
phone,
onPhoneChanged = { phone = it },
onSendCode = { stage = LoginStage.ASK_CODE })
LoginStage.ASK_CODE -> OtpInput(otp, onOtpChanged = { otp = it }, onConfirmOtp = {
})
}
}
}
@Preview(showBackground = true)
@Composable
fun LoginPreview() {
TalariaTheme {
LoginScreen()
}
}