fix: use real-time session observation in WaitingForPartnerScreen, add credential type check in Google sign-in

This commit is contained in:
null 2026-06-18 02:50:21 -05:00
parent c894dd8c67
commit dfd9974683
2 changed files with 26 additions and 37 deletions

View File

@ -5,6 +5,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.credentials.CredentialManager import androidx.credentials.CredentialManager
import androidx.credentials.CustomCredential
import androidx.credentials.GetCredentialRequest import androidx.credentials.GetCredentialRequest
import androidx.credentials.exceptions.GetCredentialCancellationException import androidx.credentials.exceptions.GetCredentialCancellationException
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
@ -190,8 +191,15 @@ fun LoginScreen(
.build() .build()
val request = GetCredentialRequest.Builder().addCredentialOption(option).build() val request = GetCredentialRequest.Builder().addCredentialOption(option).build()
val result = credMgr.getCredential(context, request) val result = credMgr.getCredential(context, request)
val idToken = GoogleIdTokenCredential.createFrom(result.credential.data).idToken val credential = result.credential
viewModel.signInWithGoogle(idToken) if (credential is CustomCredential &&
credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
) {
val idToken = GoogleIdTokenCredential.createFrom(credential.data).idToken
viewModel.signInWithGoogle(idToken)
} else {
viewModel.reportError("Google sign-in failed. Please try again.")
}
} catch (_: GetCredentialCancellationException) { } catch (_: GetCredentialCancellationException) {
// user dismissed — do nothing // user dismissed — do nothing
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -30,15 +30,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import app.closer.core.navigation.AppRoute import app.closer.core.navigation.AppRoute
import app.closer.domain.model.QuestionSession
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.CoupleRepository
import app.closer.domain.repository.UserRepository
import app.closer.domain.usecase.GameSessionManager import app.closer.domain.usecase.GameSessionManager
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -63,41 +57,28 @@ class WaitingForPartnerViewModel @Inject constructor(
init { init {
viewModelScope.launch { viewModelScope.launch {
loadGameInfo() val userId = gameSessionManager.currentUserId ?: return@launch
// Poll for partner's session completion val couple = gameSessionManager.getCoupleForUser(userId) ?: return@launch
while (isActive && _uiState.value.navigateTo == null) {
delay(5000) // Check every 5 seconds val partnerId = couple.userIds.firstOrNull { it != userId }
val userId = gameSessionManager.currentUserId ?: "" val partnerName = partnerId?.let { gameSessionManager.getUser(it) }?.displayName ?: "Partner"
val couple = gameSessionManager.getCoupleForUser(userId)
if (couple != null) { gameSessionManager.observeActiveSession(couple.id).collect { session ->
val hasActive = gameSessionManager.hasActiveSession(couple.id) if (session == null) {
if (!hasActive) { _uiState.update { it.copy(navigateTo = AppRoute.PLAY) }
// Partner finished - go back to games menu } else {
_uiState.update { it.copy(navigateTo = AppRoute.PLAY) } _uiState.update {
break it.copy(
isLoading = false,
gameType = session.gameType,
partnerName = partnerName
)
} }
} }
} }
} }
} }
private suspend fun loadGameInfo() {
val userId = gameSessionManager.currentUserId ?: ""
val couple = gameSessionManager.getCoupleForUser(userId)
val activeSession = gameSessionManager.getActiveSession(couple?.id ?: "")
val partnerId = couple?.userIds?.firstOrNull { it != userId }
val partnerName = partnerId?.let { gameSessionManager.getUser(it) }?.displayName ?: "Partner"
_uiState.update {
it.copy(
isLoading = false,
gameType = activeSession?.gameType ?: "wheel",
partnerName = partnerName
)
}
}
fun onNavigated() { fun onNavigated() {
_uiState.update { it.copy(navigateTo = null) } _uiState.update { it.copy(navigateTo = null) }
} }