dm-184
This commit is contained in:
parent
eb22555b62
commit
b3d00e12fc
4 changed files with 38 additions and 8 deletions
|
|
@ -63,6 +63,7 @@ import kotlin.text.ifEmpty
|
||||||
@Composable
|
@Composable
|
||||||
fun LoginScreen(
|
fun LoginScreen(
|
||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
|
onLoginSuccess: () -> Unit = {},
|
||||||
viewModel: AuthViewModel = hiltViewModel()
|
viewModel: AuthViewModel = hiltViewModel()
|
||||||
){
|
){
|
||||||
|
|
||||||
|
|
@ -75,6 +76,11 @@ fun LoginScreen(
|
||||||
var usernameError by remember { mutableStateOf("") }
|
var usernameError by remember { mutableStateOf("") }
|
||||||
var passwordError by remember { mutableStateOf("") }
|
var passwordError by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
LaunchedEffect(uiState) {
|
||||||
|
if (uiState is LoginUiState.Success) {
|
||||||
|
onLoginSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//background
|
//background
|
||||||
|
|
@ -97,7 +103,6 @@ fun LoginScreen(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Motion_logo
|
//Motion_logo
|
||||||
SvgImage(
|
SvgImage(
|
||||||
resId = R.raw.tg_chat_v3,
|
resId = R.raw.tg_chat_v3,
|
||||||
|
|
@ -145,7 +150,6 @@ fun LoginScreen(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.example.login_v3.data.repository.basic
|
package com.example.login_v3.data.repository.basic
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.example.login_v3.data.api.RefreshRequest
|
import com.example.login_v3.data.api.RefreshRequest
|
||||||
import com.example.login_v3.data.api.TecnologiaApi
|
import com.example.login_v3.data.api.TecnologiaApi
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
@ -18,8 +19,10 @@ class TokenAuthenticator @Inject constructor(
|
||||||
|
|
||||||
override fun authenticate(route: Route?, response: Response): Request? {
|
override fun authenticate(route: Route?, response: Response): Request? {
|
||||||
// 1. 取得 DataStore 中的當前帳號資訊
|
// 1. 取得 DataStore 中的當前帳號資訊
|
||||||
|
Log.d("AuthDebug", "--- 進入 Authenticator (觸發網址: ${response.request.url}) ---")
|
||||||
val refreshToken = runBlocking { tokenManager.currentRefreshToken.first() }
|
val refreshToken = runBlocking { tokenManager.currentRefreshToken.first() }
|
||||||
val currentUserId = runBlocking { tokenManager.currentUserId.first() }
|
val currentUserId = runBlocking { tokenManager.currentUserId.first() }
|
||||||
|
Log.d("AuthDebug", "當前用戶: $currentUserId, Token是否存在: ${!refreshToken.isNullOrEmpty()}")
|
||||||
|
|
||||||
if (refreshToken.isNullOrEmpty() || currentUserId.isNullOrEmpty()) {
|
if (refreshToken.isNullOrEmpty() || currentUserId.isNullOrEmpty()) {
|
||||||
return null // 沒有憑證資訊,不重試,直接拋出原 401 錯誤
|
return null // 沒有憑證資訊,不重試,直接拋出原 401 錯誤
|
||||||
|
|
@ -37,6 +40,9 @@ class TokenAuthenticator @Inject constructor(
|
||||||
|
|
||||||
// 3. 判斷刷新是否成功
|
// 3. 判斷刷新是否成功
|
||||||
if (refreshResponse != null && refreshResponse.isSuccessful) {
|
if (refreshResponse != null && refreshResponse.isSuccessful) {
|
||||||
|
Log.d("AuthDebug", "✅ Token 刷新成功,準備寫入 DataStore")
|
||||||
|
// saveAuthData...
|
||||||
|
Log.d("AuthDebug", "✅ DataStore 寫入完成,重新發送原請求")
|
||||||
val newAuthData = refreshResponse.body()
|
val newAuthData = refreshResponse.body()
|
||||||
if (newAuthData != null) {
|
if (newAuthData != null) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
@ -71,11 +72,26 @@ class AppViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun observeGlobalLogout() {
|
private fun observeGlobalLogout() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
// 監聽全域狀態。如果使用者在操作過程中(例如 TokenAuthenticator 刷新失敗觸發 logout),
|
// 同時監聽「帳號清單」與「當前 Access Token」的狀態
|
||||||
// 導致帳號清單變空了,就把畫面強制踢回歡迎頁。
|
// 只要這兩個其中一個被清空(變成空或 null),就代表完全失聯,必須踢回登入流程
|
||||||
hasAccountLoggedIn.collect { hasAccount ->
|
combine(hasAccountLoggedIn, tokenManager.currentAccessToken) { hasAccount, token ->
|
||||||
if (!hasAccount && _currentScreen.value == AppScreen.ScreensTab) {
|
hasAccount to token
|
||||||
_currentScreen.value = AppScreen.PreReg
|
}.collect { (hasAccount, token) ->
|
||||||
|
|
||||||
|
// 🌟 修正後的黃金判斷式:
|
||||||
|
// 如果判定「已經沒有帳號登入」或者「當前畫面在主分頁但 Token 卻是空值」
|
||||||
|
if (!hasAccount || (token.isNullOrEmpty() && _currentScreen.value == AppScreen.ScreensTab)) {
|
||||||
|
Log.e("AuthDebug", "🚨 觸發強制跳轉條件!")
|
||||||
|
|
||||||
|
// 為了避免干擾正在註冊(PreReg, Register, Login)的使用者,
|
||||||
|
// 只有在當前不在這些認證頁面時,才強制踢回 PreReg
|
||||||
|
if (_currentScreen.value != AppScreen.PreReg &&
|
||||||
|
_currentScreen.value != AppScreen.Login &&
|
||||||
|
_currentScreen.value != AppScreen.Register) {
|
||||||
|
|
||||||
|
Log.d("NavTest", "偵測到 Token 或帳號失效,強制回歡迎頁")
|
||||||
|
_currentScreen.value = AppScreen.PreReg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,11 @@ fun AppNavGraph(
|
||||||
)
|
)
|
||||||
|
|
||||||
AppScreen.Login -> LoginScreen(
|
AppScreen.Login -> LoginScreen(
|
||||||
paddingValues = paddingValues
|
paddingValues = paddingValues,
|
||||||
|
// 🌟 在這裡呼叫 AppViewModel 跳轉到主頁分頁
|
||||||
|
onLoginSuccess = {
|
||||||
|
appViewModel.goTo(AppScreen.ScreensTab)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
AppScreen.AddAccount -> {
|
AppScreen.AddAccount -> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue