diff --git a/app/src/main/java/com/example/login_v3/auth/login/Login_Page_ViewModel.kt b/app/src/main/java/com/example/login_v3/auth/login/Login_Page_ViewModel.kt index fcb8e9e..b4220c5 100644 --- a/app/src/main/java/com/example/login_v3/auth/login/Login_Page_ViewModel.kt +++ b/app/src/main/java/com/example/login_v3/auth/login/Login_Page_ViewModel.kt @@ -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.Idle) - // 暴露給 Compose 觀察的公開狀態 val loginState: StateFlow = _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()}") } diff --git a/app/src/main/java/com/example/login_v3/data/di/DataStoreModule.kt b/app/src/main/java/com/example/login_v3/data/di/DataStoreModule.kt index ba09bea..ffaeacc 100644 --- a/app/src/main/java/com/example/login_v3/data/di/DataStoreModule.kt +++ b/app/src/main/java/com/example/login_v3/data/di/DataStoreModule.kt @@ -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 by preferencesDataStore(na // 修正 2: 移除 private,讓 Hilt 可以訪問這個模組 object DataStoreModule { + + //data store instance + @Provides + @Singleton + fun provideDataStore(@ApplicationContext context: Context): DataStore { + return context.dataStore + } + //UserPreferencesRepository @Provides @Singleton - fun provideUserPreferencesRepository( - @ApplicationContext context: Context - ): UserPreferencesRepository { - return UserPreferencesRepository(context.dataStore) + fun provideUserPreferencesRepository(dataStore: DataStore): UserPreferencesRepository { + return UserPreferencesRepository(dataStore) + } + + @Provides + @Singleton + fun provideTokenManager(dataStore: DataStore): TokenManager { + return TokenManager(dataStore) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/login_v3/data/repository/basic/Token_Manager.kt b/app/src/main/java/com/example/login_v3/data/repository/basic/Token_Manager.kt new file mode 100644 index 0000000..448d6f8 --- /dev/null +++ b/app/src/main/java/com/example/login_v3/data/repository/basic/Token_Manager.kt @@ -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 +) { + 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 = dataStore.data.map { preferences -> + preferences[ACCESS_TOKEN] + } + + val isLogin: Flow = dataStore.data.map { preferences -> + preferences[IS_LOGIN] ?: false + } + + suspend fun clearAuthData() { + dataStore.edit { preferences -> + preferences.clear() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/login_v3/navigation/nav_controller.kt b/app/src/main/java/com/example/login_v3/navigation/nav_controller.kt index 0a2c234..9e98da8 100644 --- a/app/src/main/java/com/example/login_v3/navigation/nav_controller.kt +++ b/app/src/main/java/com/example/login_v3/navigation/nav_controller.kt @@ -28,7 +28,7 @@ fun AppNavGraph( AppScreen.Login -> LoginScreen( paddingValues = paddingValues, - onLoginSuccess = { appViewModel.onLoginSuccess() } + onLoginSuccess = { appViewModel.goTo(AppScreen.ScreensTab) } ) AppScreen.Register -> {