Talaria/app/src/main/java/dev/lonami/talaria/MainActivity.kt

223 lines
6.3 KiB
Kotlin

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.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.theme.TalariaTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TalariaTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Login()
}
}
}
}
}
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()
)
}
}