更新Google登录

This commit is contained in:
2024-12-01 21:27:39 +08:00
parent 784427cfba
commit cc7a65e016
9 changed files with 147 additions and 73 deletions

View File

@@ -38,6 +38,8 @@ object AppState {
var profile: AccountProfileEntity? = null var profile: AccountProfileEntity? = null
var darkMode = false var darkMode = false
var appTheme by mutableStateOf<AppThemeData>(LightThemeColors()) var appTheme by mutableStateOf<AppThemeData>(LightThemeColors())
var googleClientId: String? = null
var enableGoogleLogin: Boolean = false
suspend fun initWithAccount(scope: CoroutineScope, context: Context) { suspend fun initWithAccount(scope: CoroutineScope, context: Context) {
val accountService: AccountService = AccountServiceImpl() val accountService: AccountService = AccountServiceImpl()
// 获取用户认证信息 // 获取用户认证信息

View File

@@ -9,6 +9,11 @@ interface DictService {
* 获取字典项 * 获取字典项
*/ */
suspend fun getDictByKey(key: String): DictItem suspend fun getDictByKey(key: String): DictItem
/**
* 获取字典列表
*/
suspend fun getDistList(keys: List<String>): List<DictItem>
} }
class DictServiceImpl : DictService { class DictServiceImpl : DictService {
@@ -16,4 +21,9 @@ class DictServiceImpl : DictService {
val resp = ApiClient.api.getDict(key) val resp = ApiClient.api.getDict(key)
return resp.body()?.data ?: throw Exception("failed to get dict") return resp.body()?.data ?: throw Exception("failed to get dict")
} }
override suspend fun getDistList(keys: List<String>): List<DictItem> {
val resp = ApiClient.api.getDicts(keys.joinToString(","))
return resp.body()?.list ?: throw Exception("failed to get dict list")
}
} }

View File

@@ -131,7 +131,7 @@ data class DictItem(
@SerializedName("key") @SerializedName("key")
val key: String, val key: String,
@SerializedName("value") @SerializedName("value")
val value: String, val value: Any,
@SerializedName("desc") @SerializedName("desc")
val desc: String, val desc: String,
) )
@@ -400,6 +400,11 @@ interface RaveNowAPI {
@Query("key") key: String @Query("key") key: String
): Response<DataContainer<DictItem>> ): Response<DataContainer<DictItem>>
@GET("dicts")
suspend fun getDicts(
@Query("keys") keys: String
): Response<ListContainer<DictItem>>
@POST("captcha/generate") @POST("captcha/generate")
suspend fun generateCaptcha( suspend fun generateCaptcha(
@Body body: CaptchaRequestBody @Body body: CaptchaRequestBody

View File

@@ -68,7 +68,7 @@ fun ResetPasswordScreen() {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
try { try {
dictService.getDictByKey(ConstVars.DIC_KEY_RESET_EMAIL_INTERVAL).let { dictService.getDictByKey(ConstVars.DIC_KEY_RESET_EMAIL_INTERVAL).let {
countDownMax = it.value.toInt() countDownMax = it.value as? Int ?: 60
} }
} catch (e: Exception) { } catch (e: Exception) {
countDownMax = 60 countDownMax = 60

View File

@@ -56,7 +56,7 @@ fun PolicyCheckbox(
scope.launch { scope.launch {
try { try {
val resp = dictService.getDictByKey(ConstVars.DICT_KEY_PRIVATE_POLICY_URL) val resp = dictService.getDictByKey(ConstVars.DICT_KEY_PRIVATE_POLICY_URL)
policyUrl = resp.value policyUrl = resp.value as String
showModal = true showModal = true
} catch (e: Exception) { } catch (e: Exception) {

View File

@@ -50,11 +50,14 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.AppState import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.AppStore import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.ConstVars
import com.aiosman.ravenow.data.api.ErrorCode import com.aiosman.ravenow.data.api.ErrorCode
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.data.AccountServiceImpl 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.ServiceException
import com.aiosman.ravenow.data.api.getErrorMessageCode import com.aiosman.ravenow.data.api.getErrorMessageCode
import com.aiosman.ravenow.data.api.showToast import com.aiosman.ravenow.data.api.showToast
@@ -75,14 +78,42 @@ fun LoginPage() {
val accountService = AccountServiceImpl() val accountService = AccountServiceImpl()
val statusBarController = rememberSystemUiController() val statusBarController = rememberSystemUiController()
val AppColors = LocalAppTheme.current 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) { LaunchedEffect(Unit) {
statusBarController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode) statusBarController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode)
checkGoogleLoginEnable()
} }
fun googleLogin() { fun googleLogin() {
val clientId = AppState.googleClientId
if (clientId == null) {
Toast.makeText(context, "Google login is not enabled", Toast.LENGTH_SHORT).show()
return
}
coroutineScope.launch { coroutineScope.launch {
try { try {
GoogleLogin(context) { GoogleLogin(context, clientId) {
coroutineScope.launch { coroutineScope.launch {
try { try {
accountService.regiterUserWithGoogleAccount(it) accountService.regiterUserWithGoogleAccount(it)
@@ -94,6 +125,7 @@ fun LoginPage() {
context.getErrorMessageCode(e.errorType.code), context.getErrorMessageCode(e.errorType.code),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
else -> { else -> {
e.errorType.showToast(context) e.errorType.showToast(context)
} }
@@ -197,6 +229,7 @@ fun LoginPage() {
NavigationRoute.EmailSignUp.route, NavigationRoute.EmailSignUp.route,
) )
} }
if (showGoogleLogin) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
ActionButton( ActionButton(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -214,6 +247,8 @@ fun LoginPage() {
) { ) {
googleLogin() googleLogin()
} }
}
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Box( Box(
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
@@ -404,7 +439,8 @@ fun ImageColumn(
val totalHeight = imageHeight.value * imageCount // 计算总高度 val totalHeight = imageHeight.value * imageCount // 计算总高度
Column(modifier = modifier) { Column(modifier = modifier) {
for (i in 0 until imageCount) { for (i in 0 until imageCount) {
Box(modifier = Modifier Box(
modifier = Modifier
.width(156.dp) .width(156.dp)
.height(208.dp) .height(208.dp)
.scale(1f) .scale(1f)

View File

@@ -18,7 +18,11 @@ import androidx.compose.foundation.layout.width
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable 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.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -51,11 +55,17 @@ fun SignupScreen() {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val accountService: AccountService = AccountServiceImpl() val accountService: AccountService = AccountServiceImpl()
val appColor = LocalAppTheme.current val appColor = LocalAppTheme.current
var enableGoogleLogin by remember { mutableStateOf(AppState.enableGoogleLogin) }
fun googleLogin() { 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 { coroutineScope.launch {
try { try {
GoogleLogin(context) { GoogleLogin(context,clientId) {
coroutineScope.launch { coroutineScope.launch {
try { try {
accountService.regiterUserWithGoogleAccount(it) accountService.regiterUserWithGoogleAccount(it)
@@ -185,6 +195,7 @@ fun SignupScreen() {
// Spacer(modifier = Modifier.width(8.dp)) // Spacer(modifier = Modifier.width(8.dp))
// } // }
// ) // )
if (enableGoogleLogin) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
ActionButton( ActionButton(
modifier = Modifier modifier = Modifier
@@ -204,6 +215,8 @@ fun SignupScreen() {
googleLogin() googleLogin()
} }
}
// Spacer(modifier = Modifier.height(16.dp)) // Spacer(modifier = Modifier.height(16.dp))
// Box( // Box(
// modifier = Modifier // modifier = Modifier

View File

@@ -148,9 +148,14 @@ fun UserAuthScreen() {
fun googleLogin() { fun googleLogin() {
val clientId = AppState.googleClientId
if (clientId == null) {
Toast.makeText(context, "Google login not supported", Toast.LENGTH_SHORT).show()
return
}
scope.launch { scope.launch {
try { try {
GoogleLogin(context) { GoogleLogin(context,clientId) {
scope.launch { scope.launch {
try { try {
val authResp = accountService.loginUserWithGoogle(it) val authResp = accountService.loginUserWithGoogle(it)
@@ -293,6 +298,7 @@ fun UserAuthScreen() {
) { ) {
onLogin() onLogin()
} }
if (AppState.enableGoogleLogin) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
Text(stringResource(R.string.or_login_with), color = AppColors.secondaryText) Text(stringResource(R.string.or_login_with), color = AppColors.secondaryText)
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@@ -316,6 +322,8 @@ fun UserAuthScreen() {
} }
}
} }

View File

@@ -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 credentialManager = CredentialManager.create(context)
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId("987156664714-3bpf58ldhhr0m474ep48l668ngdn7860.apps.googleusercontent.com") .setServerClientId(clientId)
.setFilterByAuthorizedAccounts(false) .setFilterByAuthorizedAccounts(false)
.build() .build()
val request = GetCredentialRequest.Builder().addCredentialOption(googleIdOption) val request = GetCredentialRequest.Builder().addCredentialOption(googleIdOption)