auth to server-V24
This commit is contained in:
parent
a400f115a9
commit
acba929b6d
4 changed files with 71 additions and 12 deletions
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.example.login_v3.data.api.api_class.LoginRequest
|
||||
import com.example.login_v3.data.api.api_class.UserInfo
|
||||
import com.example.login_v3.data.repository.basic.AuthRepository
|
||||
import com.example.login_v3.data.repository.basic.TokenManager
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -21,27 +22,28 @@ sealed class LoginUiState {
|
|||
|
||||
@HiltViewModel
|
||||
class AuthViewModel @Inject constructor(
|
||||
private val repository: AuthRepository
|
||||
private val repository: AuthRepository,
|
||||
private val tokenManager: TokenManager // 注入 TokenManager
|
||||
) : ViewModel() {
|
||||
|
||||
// 用於內部修改的私有狀態
|
||||
private val _loginState = MutableStateFlow<LoginUiState>(LoginUiState.Idle)
|
||||
// 暴露給 Compose 觀察的公開狀態
|
||||
val loginState: StateFlow<LoginUiState> = _loginState.asStateFlow()
|
||||
|
||||
fun login(username: String, password: String) {
|
||||
viewModelScope.launch {
|
||||
_loginState.value = LoginUiState.Loading
|
||||
|
||||
try {
|
||||
val request = LoginRequest(username = username, password = password)
|
||||
val response = repository.login(request)
|
||||
|
||||
if (response.isSuccessful && response.body() != null) {
|
||||
// 登入成功,儲存 User 資訊
|
||||
_loginState.value = LoginUiState.Success(response.body()!!.user)
|
||||
val loginResponse = response.body()!!
|
||||
|
||||
// 提示:通常這裡還會處理 Token 持久化(儲存在 DataStore 或 EncryptedSharedPreferences)
|
||||
// 1. 先把 Token 存入 DataStore
|
||||
tokenManager.saveAuthData(loginResponse.access_token)
|
||||
|
||||
// 2. 更新 UI 狀態
|
||||
_loginState.value = LoginUiState.Success(loginResponse.user)
|
||||
} else {
|
||||
_loginState.value = LoginUiState.Error("登入失敗:${response.code()}")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.datastore.core.DataStore
|
|||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.example.login_v3.data.local.UserPreferences.UserPreferencesRepository
|
||||
import com.example.login_v3.data.repository.basic.TokenManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -21,12 +22,24 @@ private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(na
|
|||
// 修正 2: 移除 private,讓 Hilt 可以訪問這個模組
|
||||
object DataStoreModule {
|
||||
|
||||
|
||||
//data store instance
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDataStore(@ApplicationContext context: Context): DataStore<Preferences> {
|
||||
return context.dataStore
|
||||
}
|
||||
|
||||
//UserPreferencesRepository
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUserPreferencesRepository(
|
||||
@ApplicationContext context: Context
|
||||
): UserPreferencesRepository {
|
||||
return UserPreferencesRepository(context.dataStore)
|
||||
fun provideUserPreferencesRepository(dataStore: DataStore<Preferences>): UserPreferencesRepository {
|
||||
return UserPreferencesRepository(dataStore)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTokenManager(dataStore: DataStore<Preferences>): TokenManager {
|
||||
return TokenManager(dataStore)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.example.login_v3.data.repository.basic
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
class TokenManager @Inject constructor(
|
||||
private val dataStore: DataStore<Preferences>
|
||||
) {
|
||||
companion object {
|
||||
// 建議 Key 名稱與變數名稱一致
|
||||
private val ACCESS_TOKEN = stringPreferencesKey("access_token")
|
||||
private val IS_LOGIN = booleanPreferencesKey("is_login")
|
||||
}
|
||||
|
||||
// 1.2.1 版本依然使用 suspend edit
|
||||
suspend fun saveAuthData(token: String) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences[ACCESS_TOKEN] = token
|
||||
preferences[IS_LOGIN] = true
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 Flow 讀取資料
|
||||
val accessToken: Flow<String?> = dataStore.data.map { preferences ->
|
||||
preferences[ACCESS_TOKEN]
|
||||
}
|
||||
|
||||
val isLogin: Flow<Boolean> = dataStore.data.map { preferences ->
|
||||
preferences[IS_LOGIN] ?: false
|
||||
}
|
||||
|
||||
suspend fun clearAuthData() {
|
||||
dataStore.edit { preferences ->
|
||||
preferences.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ fun AppNavGraph(
|
|||
|
||||
AppScreen.Login -> LoginScreen(
|
||||
paddingValues = paddingValues,
|
||||
onLoginSuccess = { appViewModel.onLoginSuccess() }
|
||||
onLoginSuccess = { appViewModel.goTo(AppScreen.ScreensTab) }
|
||||
)
|
||||
|
||||
AppScreen.Register -> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue