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) { 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) { 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() ) } }