You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
375 lines
14 KiB
375 lines
14 KiB
package com.gyf.csams.account.ui
|
|
|
|
import android.content.Intent
|
|
import android.os.Bundle
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.compose.setContent
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.material.*
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.livedata.observeAsState
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.text.buildAnnotatedString
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
|
import androidx.compose.ui.text.withStyle
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import androidx.navigation.compose.NavHost
|
|
import androidx.navigation.compose.composable
|
|
import androidx.navigation.compose.navigate
|
|
import com.gyf.csams.BuildConfig
|
|
import com.gyf.csams.account.model.AccountViewModel
|
|
import com.gyf.csams.account.model.DialogMessage
|
|
import com.gyf.csams.uikit.AnimationText
|
|
import com.gyf.csams.uikit.BaseTextField
|
|
import com.gyf.csams.uikit.Body
|
|
import com.orhanobut.logger.Logger
|
|
|
|
|
|
enum class AccountRoute {
|
|
login,
|
|
register
|
|
}
|
|
|
|
class AccountActivity : ComponentActivity() {
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
|
|
setContent {
|
|
Body { nav, scaffoldState ->
|
|
NavHost(navController = nav, startDestination = AccountRoute.login.name) {
|
|
composable(AccountRoute.login.name) {
|
|
Account(
|
|
scaffoldState = scaffoldState,
|
|
route = AccountRoute.login
|
|
) { isValidForm: Boolean, accountViewModel: AccountViewModel ->
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
|
|
OutlinedButton(
|
|
onClick = { accountViewModel.login() },
|
|
enabled = isValidForm,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(bottom = 10.dp)
|
|
) {
|
|
|
|
Text(text = accountViewModel.loginDesc)
|
|
}
|
|
|
|
val finishLogin: Boolean? by accountViewModel.finishLogin.observeAsState()
|
|
if (finishLogin == true) {
|
|
finish()
|
|
}
|
|
|
|
OutlinedButton(
|
|
onClick = { nav.navigate(AccountRoute.register.name) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
colors = ButtonDefaults.outlinedButtonColors(
|
|
contentColor = MaterialTheme.colors.onBackground
|
|
)
|
|
) {
|
|
Text(text = accountViewModel.goRegister)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
composable(AccountRoute.register.name) {
|
|
Account(
|
|
scaffoldState = scaffoldState,
|
|
route = AccountRoute.register
|
|
) { isValidForm: Boolean, accountViewModel: AccountViewModel ->
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
|
|
OutlinedButton(
|
|
onClick = { accountViewModel.register() },
|
|
enabled = isValidForm,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(bottom = 10.dp)
|
|
) {
|
|
Text(text = accountViewModel.regBtnDesc)
|
|
}
|
|
|
|
OutlinedButton(
|
|
onClick = { nav.navigate(AccountRoute.login.name) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
colors = ButtonDefaults.outlinedButtonColors(
|
|
contentColor = MaterialTheme.colors.onBackground
|
|
)
|
|
) {
|
|
Text(text = accountViewModel.backLogin)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 帐号表单
|
|
*
|
|
* @param accountViewModel
|
|
* @param Action 表单操作区域
|
|
*/
|
|
@Composable
|
|
private fun Account(
|
|
accountViewModel: AccountViewModel = viewModel(),
|
|
scaffoldState: ScaffoldState,
|
|
route: AccountRoute,
|
|
Action: @Composable (isValidForm: Boolean, accountViewModel: AccountViewModel) -> Unit
|
|
) {
|
|
accountViewModel.route = route
|
|
Row(
|
|
horizontalArrangement = Arrangement.Center,
|
|
verticalAlignment = Alignment.CenterVertically,
|
|
modifier = Modifier.fillMaxSize()
|
|
) {
|
|
Column(modifier = Modifier.width(IntrinsicSize.Min)) {
|
|
Text(buildAnnotatedString {
|
|
withStyle(
|
|
style = MaterialTheme.typography.subtitle1.toSpanStyle()
|
|
.copy(color = MaterialTheme.colors.primary)
|
|
) {
|
|
append(accountViewModel.name.formValue.value ?: "")
|
|
}
|
|
withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) {
|
|
append(accountViewModel.welcomeStart)
|
|
}
|
|
withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) {
|
|
append(accountViewModel.welcomeEnd)
|
|
}
|
|
withStyle(
|
|
style = MaterialTheme.typography.subtitle2.toSpanStyle()
|
|
.copy(color = MaterialTheme.colors.secondary)
|
|
) {
|
|
append(BuildConfig.foreground_app_name)
|
|
}
|
|
})
|
|
|
|
StudentId(checkRepeat = route == AccountRoute.register)
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
|
|
|
|
if (route == AccountRoute.register) Name() else Password()
|
|
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
PasswordTip()
|
|
val isValidForm: Boolean by accountViewModel.isValidForm.observeAsState(false)
|
|
Action(isValidForm = isValidForm, accountViewModel = accountViewModel)
|
|
|
|
val snackBarMsg: String by accountViewModel.snackBarMsg.observeAsState("")
|
|
|
|
if (snackBarMsg != "") {
|
|
LaunchedEffect(scaffoldState) {
|
|
scaffoldState.snackbarHostState.showSnackbar(
|
|
message = snackBarMsg
|
|
)
|
|
accountViewModel.resetRegisterResMsg()
|
|
}
|
|
}
|
|
|
|
RegisterDialog()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 学号
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun StudentId(accountViewModel: AccountViewModel = viewModel(), checkRepeat: Boolean) {
|
|
Column {
|
|
|
|
|
|
val isValidStudentId: Boolean by accountViewModel.isValidStudentId.observeAsState(false)
|
|
BaseTextField(
|
|
form = accountViewModel.studentId, keyboardOptions = KeyboardOptions.Default.copy(
|
|
keyboardType = KeyboardType.Number,
|
|
imeAction = ImeAction.Done
|
|
), isError = !isValidStudentId
|
|
)
|
|
if (isValidStudentId) {
|
|
if (checkRepeat) {
|
|
val isRepeat: Boolean? by accountViewModel.isRepeat.observeAsState(null)
|
|
Logger.i("isRepeat=$isRepeat")
|
|
when (isRepeat) {
|
|
null -> AnimationText(text = accountViewModel.checkRegTip)
|
|
true ->
|
|
Text(buildAnnotatedString {
|
|
append(accountViewModel.studentId.formDesc)
|
|
withStyle(
|
|
style = MaterialTheme.typography.body1.toSpanStyle().copy(
|
|
color = MaterialTheme.colors.error
|
|
)
|
|
) {
|
|
append(accountViewModel.studentId.formValue.value ?: "")
|
|
}
|
|
append(accountViewModel.registered)
|
|
})
|
|
false ->
|
|
Text(buildAnnotatedString {
|
|
append(accountViewModel.studentId.formDesc)
|
|
withStyle(
|
|
style = MaterialTheme.typography.body1.toSpanStyle().copy(
|
|
color = MaterialTheme.colors.primary
|
|
)
|
|
) {
|
|
append(accountViewModel.studentId.formValue.value ?: "")
|
|
}
|
|
append(accountViewModel.canRegister)
|
|
})
|
|
}
|
|
}
|
|
} else {
|
|
Text(
|
|
text = accountViewModel.studentIdFormat,
|
|
color = MaterialTheme.colors.error,
|
|
style = MaterialTheme.typography.body1
|
|
)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注册弹窗
|
|
*
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun RegisterDialog(accountViewModel: AccountViewModel = viewModel()) {
|
|
val dialogMsg: DialogMessage? by accountViewModel.dialogMsg.observeAsState(null)
|
|
|
|
val message = dialogMsg?.userResDto?.password
|
|
if (message?.isNotEmpty() == true) {
|
|
PasswordDialog(message = message)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 密码弹窗
|
|
*
|
|
* @param accountViewModel
|
|
* @param message
|
|
*/
|
|
@Composable
|
|
private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), message: String) {
|
|
val context = LocalContext.current
|
|
val button: @Composable () -> Unit = {
|
|
Row(
|
|
horizontalArrangement = Arrangement.Center, modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(bottom = 10.dp)
|
|
) {
|
|
OutlinedButton(
|
|
onClick = { accountViewModel.resetDialogMsg() },
|
|
modifier = Modifier.padding(end = 10.dp)
|
|
) {
|
|
Text(text = accountViewModel.confirmDesc)
|
|
}
|
|
OutlinedButton(
|
|
onClick = {
|
|
context.startActivity(Intent(context, AccountActivity::class.java))
|
|
},
|
|
colors = ButtonDefaults.outlinedButtonColors(
|
|
contentColor = MaterialTheme.colors.onBackground
|
|
)
|
|
) {
|
|
Text(text = accountViewModel.backLogin)
|
|
}
|
|
}
|
|
}
|
|
AlertDialog(onDismissRequest = { accountViewModel.resetDialogMsg() },
|
|
buttons = button,
|
|
title = { Text(text = accountViewModel.title) },
|
|
text = {
|
|
Text(buildAnnotatedString {
|
|
append(accountViewModel.passwordDialogStart)
|
|
withStyle(
|
|
style = MaterialTheme.typography.body1.toSpanStyle()
|
|
.copy(color = MaterialTheme.colors.secondary)
|
|
) {
|
|
append(message)
|
|
}
|
|
append(accountViewModel.passwordDialogEnd)
|
|
})
|
|
})
|
|
}
|
|
|
|
|
|
/**
|
|
* 姓名文本框
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun Name(accountViewModel: AccountViewModel = viewModel()) {
|
|
Column {
|
|
|
|
val isValidName: Boolean by accountViewModel.isValidName.observeAsState(false)
|
|
BaseTextField(form = accountViewModel.name, isError = !isValidName)
|
|
|
|
if (!isValidName) {
|
|
Text(
|
|
text = accountViewModel.nameFormat,
|
|
color = MaterialTheme.colors.error
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* 密码框
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun Password(accountViewModel: AccountViewModel = viewModel()) {
|
|
Column {
|
|
val isValidPwd: Boolean by accountViewModel.isValidPwd.observeAsState(false)
|
|
|
|
BaseTextField(
|
|
form = accountViewModel.password, isError = !isValidPwd,
|
|
keyboardOptions = KeyboardOptions.Default.copy(
|
|
imeAction = ImeAction.Done,
|
|
keyboardType = KeyboardType.Number,
|
|
), visualTransformation = PasswordVisualTransformation()
|
|
)
|
|
|
|
|
|
if (!isValidPwd) {
|
|
Text(
|
|
text = accountViewModel.passwordFormat,
|
|
color = MaterialTheme.colors.error
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 提示自动生成密码
|
|
*
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun PasswordTip(accountViewModel: AccountViewModel = viewModel()) {
|
|
if (accountViewModel.isValidForm.value == true) {
|
|
Text(
|
|
text = accountViewModel.passwordTip, color = MaterialTheme.colors.primary,
|
|
modifier = Modifier.fillMaxWidth()
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|