From d481222569d34f330dbae37376732f1b9eb5b8ed Mon Sep 17 00:00:00 2001 From: LTFan Date: Sun, 21 Jan 2024 00:06:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=AA=8C=E8=AF=81=E7=A0=81=E4=BA=A4?= =?UTF-8?q?=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build-number.properties | 2 +- .../data/components/root/SignInComponent.kt | 45 ++++++++++-- .../commonMain/kotlin/ui/pages/root/SignIn.kt | 72 ++++++++++++------- 3 files changed, 90 insertions(+), 29 deletions(-) diff --git a/build-number.properties b/build-number.properties index a7f9677..77d4f34 100644 --- a/build-number.properties +++ b/build-number.properties @@ -15,4 +15,4 @@ # You should have received a copy of the GNU General Public License along # with Fhraise. If not, see . # -buildNumber=19 +buildNumber=20 diff --git a/composeApp/src/commonMain/kotlin/data/components/root/SignInComponent.kt b/composeApp/src/commonMain/kotlin/data/components/root/SignInComponent.kt index d73d7b4..f9b95c2 100644 --- a/composeApp/src/commonMain/kotlin/data/components/root/SignInComponent.kt +++ b/composeApp/src/commonMain/kotlin/data/components/root/SignInComponent.kt @@ -56,8 +56,9 @@ interface SignInComponent { interface PhoneNumberVerifyCodeState : ComponentState, KeyboardNextState, KeyboardDoneState { var phoneNumber: String - var verifyCode: String + val phoneNumberVerified: Boolean var canInputVerifyCode: Boolean + var verifyCode: String fun switchCanInputVerifyCode() { canInputVerifyCode = !canInputVerifyCode @@ -84,6 +85,8 @@ interface SignInComponent { showMoreSignInOptions = !showMoreSignInOptions } + fun nextOrSubmit() + val onGuestSignIn: () -> Unit val onUsernameSignIn: () -> Unit val onFaceSignIn: () -> Unit @@ -132,9 +135,35 @@ class AppSignInComponent( override val onSignUp: () -> Unit, override val onAdminSignIn: () -> Unit, ) : ComponentState(), SignInComponent.ComponentState.SignIn { - override var phoneNumber by mutableStateOf(phoneNumber) + private val phoneNumberRegex = + Regex("^1(3(([0-3]|[5-9])[0-9]{8}|4[0-8][0-9]{7})|(45|5([0-2]|[5-6]|[8-9])|6(2|[5-7])|7([0-1]|[5-8])|8[0-9]|9([0-3]|[5-9]))[0-9]{8})$") + + private var _phoneNumber by mutableStateOf(phoneNumber) + override var phoneNumber: String + get() = _phoneNumber + set(value) { + canInputVerifyCode = false + _phoneNumber = value + } + + override val phoneNumberVerified: Boolean + get() = phoneNumberRegex.matches(phoneNumber) + + private var _canInputVerifyCode by mutableStateOf(canInputVerifyCode) + override var canInputVerifyCode: Boolean + get() = _canInputVerifyCode + set(value) { + if (!phoneNumberVerified) { + _canInputVerifyCode = false + return + } + _canInputVerifyCode = value + if (!value) { + verifyCode = "" + } + } + override var verifyCode by mutableStateOf(verifyCode) - override var canInputVerifyCode by mutableStateOf(canInputVerifyCode) override var showMoreSignInOptions by mutableStateOf(showMoreSignInOptions) override fun submit() { @@ -142,7 +171,15 @@ class AppSignInComponent( } override val onNext: KeyboardActionScope.() -> Unit = { - // TODO + this@SignIn.canInputVerifyCode = true + } + + override fun nextOrSubmit() { + if (canInputVerifyCode) { + submit() + } else { + canInputVerifyCode = true + } } override val onDone: KeyboardActionScope.() -> Unit = { diff --git a/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt b/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt index 6ba69a7..c3305e6 100644 --- a/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt +++ b/composeApp/src/commonMain/kotlin/ui/pages/root/SignIn.kt @@ -18,10 +18,8 @@ package ui.pages.root -import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.* import androidx.compose.animation.core.* -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideOutHorizontally import androidx.compose.foundation.ScrollState import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -60,7 +58,7 @@ import ui.modifiers.applyBrush import kotlin.math.max import kotlin.math.roundToInt -@OptIn(ExperimentalMaterial3Api::class, ExperimentalResourceApi::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalResourceApi::class, ExperimentalAnimationApi::class) @Composable fun SignIn(component: SignInComponent) { val colorMode by component.colorMode @@ -139,30 +137,45 @@ fun SignIn(component: SignInComponent) { }, content = { Column(modifier = Modifier.fillMaxWidth()) { - Card( - modifier = Modifier.fillMaxWidth(), - ) { - if (state is SignInComponent.ComponentState.SignIn) { - Spacer(modifier = Modifier.height(16.dp)) - state.PhoneNumber() + Spacer(modifier = Modifier.height(16.dp)) + if (state is SignInComponent.ComponentState.SignIn) { + state.PhoneNumber() + AnimatedVisibility(visible = state.canInputVerifyCode) { Spacer(modifier = Modifier.height(16.dp)) state.VerifyCode() - Spacer(modifier = Modifier.height(16.dp)) } - } - Spacer(modifier = Modifier.height(24.dp)) - Box( - modifier = Modifier.fillMaxWidth().padding(horizontal = 32.dp), - contentAlignment = Alignment.Center, - ) { - Button( - onClick = state::submit, - shape = MaterialTheme.shapes.large, + Spacer(modifier = Modifier.height(32.dp)) + Box( + modifier = Modifier.fillMaxWidth().padding(horizontal = 32.dp), + contentAlignment = Alignment.Center, ) { - Icon( - imageVector = Icons.Default.ArrowForward, - contentDescription = "登录", - ) + Button( + onClick = state::nextOrSubmit, + shape = MaterialTheme.shapes.large, + ) { + AnimatedContent( + targetState = state.canInputVerifyCode, + transitionSpec = { + if (targetState) { + fadeIn() + slideInHorizontally { it } togetherWith fadeOut() + slideOutHorizontally { -it } + } else { + fadeIn() + slideInHorizontally { -it } togetherWith fadeOut() + slideOutHorizontally { it } + } + }, + ) { targetState -> + if (targetState) { + Icon( + imageVector = Icons.Default.ArrowForward, + contentDescription = "登录", + ) + } else { + Icon( + imageVector = Icons.Default.Send, + contentDescription = "发送验证码", + ) + } + } + } } } } @@ -617,6 +630,17 @@ fun SignInComponent.ComponentState.PhoneNumberVerifyCodeState.PhoneNumber() { onValueChange = ::phoneNumber::set, modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), label = { Text(text = "手机号") }, + prefix = { Text(text = "+86") }, + supportingText = { + AnimatedVisibility( + visible = !phoneNumberVerified, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically(), + ) { + Text(text = "手机号格式不正确") + } + }, + isError = !phoneNumberVerified, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Phone, imeAction = ImeAction.Next ),