feat:登录以后保存用户名密码,方便下次登录

This commit is contained in:
amos
2025-12-18 16:44:30 +08:00
parent bf88aac937
commit 3fcd90aa65
4 changed files with 83 additions and 12 deletions

View File

@@ -14,6 +14,7 @@ import coil.Coil
import coil.ImageLoader
import coil.disk.DiskCache
import coil.memory.MemoryCache
import com.memory.app.data.CredentialsManager
import com.memory.app.data.ThemeManager
import com.memory.app.data.ThemeMode
import com.memory.app.data.model.User
@@ -28,12 +29,14 @@ import okhttp3.OkHttpClient
class MainActivity : ComponentActivity() {
private lateinit var authRepository: AuthRepository
private lateinit var themeManager: ThemeManager
private lateinit var credentialsManager: CredentialsManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
themeManager = ThemeManager(this)
credentialsManager = CredentialsManager(this)
// 配置 Coil 图片加载器
val imageLoader = ImageLoader.Builder(this)
@@ -103,6 +106,8 @@ class MainActivity : ComponentActivity() {
.onSuccess {
isLoggedIn = true
currentUser = it.user
// 登录成功后保存凭据
credentialsManager.saveCredentials(username, password)
}
.onFailure {
error = it.message ?: "登录失败"
@@ -118,6 +123,8 @@ class MainActivity : ComponentActivity() {
.onSuccess {
isLoggedIn = true
currentUser = it.user
// 注册成功后保存凭据
credentialsManager.saveCredentials(username, password)
}
.onFailure {
error = it.message ?: "注册失败"
@@ -126,7 +133,9 @@ class MainActivity : ComponentActivity() {
}
},
isLoading = isLoading,
error = error
error = error,
savedUsername = credentialsManager.getSavedUsername(),
savedPassword = credentialsManager.getSavedPassword()
)
}
true -> {

View File

@@ -0,0 +1,65 @@
package com.memory.app.data
import android.content.Context
import android.util.Base64
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
class CredentialsManager(context: Context) {
private val prefs = context.getSharedPreferences("credentials_prefs", Context.MODE_PRIVATE)
private val usernameKey = "saved_username"
private val passwordKey = "saved_password"
// 简单的加密密钥
private val encryptionKey = "MemoryApp2024Key"
// 简单加密
private fun encrypt(text: String): String {
val key = SecretKeySpec(encryptionKey.toByteArray().copyOf(16), "AES")
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, key)
val encrypted = cipher.doFinal(text.toByteArray())
return Base64.encodeToString(encrypted, Base64.DEFAULT)
}
// 简单解密
private fun decrypt(encrypted: String): String {
val key = SecretKeySpec(encryptionKey.toByteArray().copyOf(16), "AES")
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, key)
val decoded = Base64.decode(encrypted, Base64.DEFAULT)
return String(cipher.doFinal(decoded))
}
// 保存凭据
fun saveCredentials(username: String, password: String) {
prefs.edit()
.putString(usernameKey, username)
.putString(passwordKey, encrypt(password))
.apply()
}
// 获取保存的用户名
fun getSavedUsername(): String {
return prefs.getString(usernameKey, "") ?: ""
}
// 获取保存的密码
fun getSavedPassword(): String {
val encrypted = prefs.getString(passwordKey, null) ?: return ""
return try {
decrypt(encrypted)
} catch (e: Exception) {
""
}
}
// 清除凭据
fun clearCredentials() {
prefs.edit()
.remove(usernameKey)
.remove(passwordKey)
.apply()
}
}

View File

@@ -117,10 +117,12 @@ fun LoginScreen(
onLogin: (String, String) -> Unit,
onRegister: (String, String, String) -> Unit,
isLoading: Boolean = false,
error: String? = null
error: String? = null,
savedUsername: String = "",
savedPassword: String = ""
) {
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var username by remember { mutableStateOf(savedUsername) }
var password by remember { mutableStateOf(savedPassword) }
var nickname by remember { mutableStateOf("") }
var isRegisterMode by remember { mutableStateOf(false) }
var showRegisterDisabledDialog by remember { mutableStateOf(false) }
@@ -324,10 +326,10 @@ fun LoginScreen(
.height(56.dp),
shape = RoundedCornerShape(12.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Slate900,
containerColor = Brand500,
contentColor = Color.White,
disabledContainerColor = Slate400,
disabledContentColor = Color.White
disabledContainerColor = Brand500.copy(alpha = 0.4f),
disabledContentColor = Color.White.copy(alpha = 0.7f)
),
enabled = !isLoading && username.isNotBlank() && password.isNotBlank() &&
(!isRegisterMode || nickname.isNotBlank())

View File

@@ -22,9 +22,7 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@@ -32,7 +30,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import com.memory.app.data.model.User
import com.memory.app.ui.theme.*
import com.memory.app.util.HolidayUtils
import com.memory.app.util.HolidayWithDays
@@ -485,5 +482,3 @@ private fun StatColumn(count: Int, label: String) {
)
}
}