From cc7a65e016ead762af9f69cdc7efb85c49a7ae0b Mon Sep 17 00:00:00 2001 From: AllenTom Date: Sun, 1 Dec 2024 21:27:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0Google=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/aiosman/ravenow/AppState.kt | 4 +- .../com/aiosman/ravenow/data/DictService.kt | 10 ++ .../aiosman/ravenow/data/api/RiderProAPI.kt | 7 +- .../ravenow/ui/account/ResetPassword.kt | 2 +- .../ravenow/ui/composables/PolicyCheckbox.kt | 2 +- .../com/aiosman/ravenow/ui/login/login.kt | 96 +++++++++++++------ .../com/aiosman/ravenow/ui/login/signup.kt | 49 ++++++---- .../com/aiosman/ravenow/ui/login/userauth.kt | 46 +++++---- .../com/aiosman/ravenow/utils/GoogleLogin.kt | 4 +- 9 files changed, 147 insertions(+), 73 deletions(-) diff --git a/app/src/main/java/com/aiosman/ravenow/AppState.kt b/app/src/main/java/com/aiosman/ravenow/AppState.kt index ba098b1..84b0c5b 100644 --- a/app/src/main/java/com/aiosman/ravenow/AppState.kt +++ b/app/src/main/java/com/aiosman/ravenow/AppState.kt @@ -35,9 +35,11 @@ import kotlin.coroutines.suspendCoroutine object AppState { var UserId: Int? = null - var profile :AccountProfileEntity? = null + var profile: AccountProfileEntity? = null var darkMode = false var appTheme by mutableStateOf(LightThemeColors()) + var googleClientId: String? = null + var enableGoogleLogin: Boolean = false suspend fun initWithAccount(scope: CoroutineScope, context: Context) { val accountService: AccountService = AccountServiceImpl() // 获取用户认证信息 diff --git a/app/src/main/java/com/aiosman/ravenow/data/DictService.kt b/app/src/main/java/com/aiosman/ravenow/data/DictService.kt index 09c8ee0..6a63f79 100644 --- a/app/src/main/java/com/aiosman/ravenow/data/DictService.kt +++ b/app/src/main/java/com/aiosman/ravenow/data/DictService.kt @@ -9,6 +9,11 @@ interface DictService { * 获取字典项 */ suspend fun getDictByKey(key: String): DictItem + + /** + * 获取字典列表 + */ + suspend fun getDistList(keys: List): List } class DictServiceImpl : DictService { @@ -16,4 +21,9 @@ class DictServiceImpl : DictService { val resp = ApiClient.api.getDict(key) return resp.body()?.data ?: throw Exception("failed to get dict") } + + override suspend fun getDistList(keys: List): List { + val resp = ApiClient.api.getDicts(keys.joinToString(",")) + return resp.body()?.list ?: throw Exception("failed to get dict list") + } } \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/ravenow/data/api/RiderProAPI.kt b/app/src/main/java/com/aiosman/ravenow/data/api/RiderProAPI.kt index b0143a9..3dcdde0 100644 --- a/app/src/main/java/com/aiosman/ravenow/data/api/RiderProAPI.kt +++ b/app/src/main/java/com/aiosman/ravenow/data/api/RiderProAPI.kt @@ -131,7 +131,7 @@ data class DictItem( @SerializedName("key") val key: String, @SerializedName("value") - val value: String, + val value: Any, @SerializedName("desc") val desc: String, ) @@ -400,6 +400,11 @@ interface RaveNowAPI { @Query("key") key: String ): Response> + @GET("dicts") + suspend fun getDicts( + @Query("keys") keys: String + ): Response> + @POST("captcha/generate") suspend fun generateCaptcha( @Body body: CaptchaRequestBody diff --git a/app/src/main/java/com/aiosman/ravenow/ui/account/ResetPassword.kt b/app/src/main/java/com/aiosman/ravenow/ui/account/ResetPassword.kt index c187e51..dd550c7 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/account/ResetPassword.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/account/ResetPassword.kt @@ -68,7 +68,7 @@ fun ResetPasswordScreen() { LaunchedEffect(Unit) { try { dictService.getDictByKey(ConstVars.DIC_KEY_RESET_EMAIL_INTERVAL).let { - countDownMax = it.value.toInt() + countDownMax = it.value as? Int ?: 60 } } catch (e: Exception) { countDownMax = 60 diff --git a/app/src/main/java/com/aiosman/ravenow/ui/composables/PolicyCheckbox.kt b/app/src/main/java/com/aiosman/ravenow/ui/composables/PolicyCheckbox.kt index 7ffc4c9..9f09199 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/composables/PolicyCheckbox.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/composables/PolicyCheckbox.kt @@ -56,7 +56,7 @@ fun PolicyCheckbox( scope.launch { try { val resp = dictService.getDictByKey(ConstVars.DICT_KEY_PRIVATE_POLICY_URL) - policyUrl = resp.value + policyUrl = resp.value as String showModal = true } catch (e: Exception) { diff --git a/app/src/main/java/com/aiosman/ravenow/ui/login/login.kt b/app/src/main/java/com/aiosman/ravenow/ui/login/login.kt index d05c09c..4206e01 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/login/login.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/login/login.kt @@ -50,11 +50,14 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.aiosman.ravenow.AppState import com.aiosman.ravenow.AppStore +import com.aiosman.ravenow.ConstVars import com.aiosman.ravenow.data.api.ErrorCode import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.R import com.aiosman.ravenow.data.AccountServiceImpl +import com.aiosman.ravenow.data.DictService +import com.aiosman.ravenow.data.DictServiceImpl import com.aiosman.ravenow.data.ServiceException import com.aiosman.ravenow.data.api.getErrorMessageCode import com.aiosman.ravenow.data.api.showToast @@ -75,18 +78,46 @@ fun LoginPage() { val accountService = AccountServiceImpl() val statusBarController = rememberSystemUiController() val AppColors = LocalAppTheme.current + val dictService: DictService = DictServiceImpl() + var showGoogleLogin by remember { + mutableStateOf(false) + } + suspend fun checkGoogleLoginEnable() { + val result = dictService.getDistList( + listOf( + ConstVars.DICT_KEY_ENABLE_GOOGLE_LOGIN, + ConstVars.DICT_KEY_GOOGLE_LOGIN_CLIENT_ID + ) + ) + val enableDictItem = result.find { it.key == ConstVars.DICT_KEY_ENABLE_GOOGLE_LOGIN } + val clientIdDictItem = result.find { it.key == ConstVars.DICT_KEY_GOOGLE_LOGIN_CLIENT_ID } + if (enableDictItem != null && clientIdDictItem != null) { + AppState.googleClientId = clientIdDictItem.value as? String + showGoogleLogin = enableDictItem.value == true + } else { + showGoogleLogin = false + } + AppState.enableGoogleLogin = showGoogleLogin + } LaunchedEffect(Unit) { statusBarController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode) + checkGoogleLoginEnable() } + fun googleLogin() { + val clientId = AppState.googleClientId + if (clientId == null) { + Toast.makeText(context, "Google login is not enabled", Toast.LENGTH_SHORT).show() + return + } coroutineScope.launch { try { - GoogleLogin(context) { + GoogleLogin(context, clientId) { coroutineScope.launch { try { accountService.regiterUserWithGoogleAccount(it) - }catch (e : ServiceException) { + } catch (e: ServiceException) { when (e.errorType) { ErrorCode.USER_EXIST -> Toast.makeText( @@ -94,6 +125,7 @@ fun LoginPage() { context.getErrorMessageCode(e.errorType.code), Toast.LENGTH_SHORT ).show() + else -> { e.errorType.showToast(context) } @@ -197,23 +229,26 @@ fun LoginPage() { NavigationRoute.EmailSignUp.route, ) } - Spacer(modifier = Modifier.height(16.dp)) - ActionButton( - modifier = Modifier.fillMaxWidth(), - text = stringResource(R.string.sign_in_with_google), - color = AppColors.text, - leading = { - Image( - painter = painterResource(id = R.drawable.rider_pro_google), - contentDescription = "Google", - modifier = Modifier.size(36.dp) - ) - }, - expandText = true, - contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp) - ) { - googleLogin() + if (showGoogleLogin) { + Spacer(modifier = Modifier.height(16.dp)) + ActionButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.sign_in_with_google), + color = AppColors.text, + leading = { + Image( + painter = painterResource(id = R.drawable.rider_pro_google), + contentDescription = "Google", + modifier = Modifier.size(36.dp) + ) + }, + expandText = true, + contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp) + ) { + googleLogin() + } } + Spacer(modifier = Modifier.height(24.dp)) Box( contentAlignment = Alignment.Center, @@ -404,19 +439,20 @@ fun ImageColumn( val totalHeight = imageHeight.value * imageCount // 计算总高度 Column(modifier = modifier) { for (i in 0 until imageCount) { - Box(modifier = Modifier - .width(156.dp) - .height(208.dp) - .scale(1f) - .graphicsLayer { - val translation = if (reverse) { - offset - } else { - offset + Box( + modifier = Modifier + .width(156.dp) + .height(208.dp) + .scale(1f) + .graphicsLayer { + val translation = if (reverse) { + offset + } else { + offset + } + translationY = translation } - translationY = translation - } - .clip(RoundedCornerShape(16.dp)), + .clip(RoundedCornerShape(16.dp)), contentAlignment = Alignment.Center) { Image( painter = painterResource(id = imageList[(currentImage + i) % imageCount]), diff --git a/app/src/main/java/com/aiosman/ravenow/ui/login/signup.kt b/app/src/main/java/com/aiosman/ravenow/ui/login/signup.kt index c9687ad..5beab7b 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/login/signup.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/login/signup.kt @@ -18,7 +18,11 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -51,11 +55,17 @@ fun SignupScreen() { val coroutineScope = rememberCoroutineScope() val accountService: AccountService = AccountServiceImpl() val appColor = LocalAppTheme.current + var enableGoogleLogin by remember { mutableStateOf(AppState.enableGoogleLogin) } fun googleLogin() { + val clientId = AppState.googleClientId + if (clientId == null) { + Toast.makeText(context, "Google client id is not set", Toast.LENGTH_SHORT).show() + return + } coroutineScope.launch { try { - GoogleLogin(context) { + GoogleLogin(context,clientId) { coroutineScope.launch { try { accountService.regiterUserWithGoogleAccount(it) @@ -185,25 +195,28 @@ fun SignupScreen() { // Spacer(modifier = Modifier.width(8.dp)) // } // ) - Spacer(modifier = Modifier.height(16.dp)) - ActionButton( - modifier = Modifier - .width(345.dp) - .height(48.dp), - color = Color.Black, - leading = { - Image( - painter = painterResource(id = R.mipmap.rider_pro_signup_google), - contentDescription = "Google", - modifier = Modifier.size(24.dp) - ) - Spacer(modifier = Modifier.width(8.dp)) - }, - text = stringResource(R.string.sign_in_with_google), - ) { - googleLogin() + if (enableGoogleLogin) { + Spacer(modifier = Modifier.height(16.dp)) + ActionButton( + modifier = Modifier + .width(345.dp) + .height(48.dp), + color = Color.Black, + leading = { + Image( + painter = painterResource(id = R.mipmap.rider_pro_signup_google), + contentDescription = "Google", + modifier = Modifier.size(24.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + }, + text = stringResource(R.string.sign_in_with_google), + ) { + googleLogin() + } } + // Spacer(modifier = Modifier.height(16.dp)) // Box( // modifier = Modifier diff --git a/app/src/main/java/com/aiosman/ravenow/ui/login/userauth.kt b/app/src/main/java/com/aiosman/ravenow/ui/login/userauth.kt index 8ef04a5..c15522f 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/login/userauth.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/login/userauth.kt @@ -148,9 +148,14 @@ fun UserAuthScreen() { fun googleLogin() { + val clientId = AppState.googleClientId + if (clientId == null) { + Toast.makeText(context, "Google login not supported", Toast.LENGTH_SHORT).show() + return + } scope.launch { try { - GoogleLogin(context) { + GoogleLogin(context,clientId) { scope.launch { try { val authResp = accountService.loginUserWithGoogle(it) @@ -293,25 +298,28 @@ fun UserAuthScreen() { ) { onLogin() } - Spacer(modifier = Modifier.height(16.dp)) - Text(stringResource(R.string.or_login_with), color = AppColors.secondaryText) - Spacer(modifier = Modifier.height(16.dp)) - ActionButton( - modifier = Modifier.fillMaxWidth(), - text = stringResource(R.string.sign_in_with_google), - color = AppColors.text, - leading = { - Image( - painter = painterResource(id = R.drawable.rider_pro_google), - contentDescription = "Google", - modifier = Modifier.size(36.dp) - ) - }, - expandText = true, - contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp) - ) { - googleLogin() + if (AppState.enableGoogleLogin) { + Spacer(modifier = Modifier.height(16.dp)) + Text(stringResource(R.string.or_login_with), color = AppColors.secondaryText) + Spacer(modifier = Modifier.height(16.dp)) + ActionButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.sign_in_with_google), + color = AppColors.text, + leading = { + Image( + painter = painterResource(id = R.drawable.rider_pro_google), + contentDescription = "Google", + modifier = Modifier.size(36.dp) + ) + }, + expandText = true, + contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp) + ) { + googleLogin() + } } + } } diff --git a/app/src/main/java/com/aiosman/ravenow/utils/GoogleLogin.kt b/app/src/main/java/com/aiosman/ravenow/utils/GoogleLogin.kt index 8c4808e..e669ab9 100644 --- a/app/src/main/java/com/aiosman/ravenow/utils/GoogleLogin.kt +++ b/app/src/main/java/com/aiosman/ravenow/utils/GoogleLogin.kt @@ -22,10 +22,10 @@ fun handleGoogleSignIn(result: GetCredentialResponse, onLoginWithGoogle: (String } } -suspend fun GoogleLogin(context: Context, onLoginWithGoogle: (String) -> Unit) { +suspend fun GoogleLogin(context: Context,clientId:String, onLoginWithGoogle: (String) -> Unit) { val credentialManager = CredentialManager.create(context) val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() - .setServerClientId("987156664714-3bpf58ldhhr0m474ep48l668ngdn7860.apps.googleusercontent.com") + .setServerClientId(clientId) .setFilterByAuthorizedAccounts(false) .build() val request = GetCredentialRequest.Builder().addCredentialOption(googleIdOption)