diff --git a/app/src/main/java/app/closer/data/remote/FirestoreCoupleDataSource.kt b/app/src/main/java/app/closer/data/remote/FirestoreCoupleDataSource.kt index b6e9ff8d..fef6fb83 100644 --- a/app/src/main/java/app/closer/data/remote/FirestoreCoupleDataSource.kt +++ b/app/src/main/java/app/closer/data/remote/FirestoreCoupleDataSource.kt @@ -2,7 +2,6 @@ package app.closer.data.remote import app.closer.domain.model.Couple import com.google.firebase.firestore.DocumentSnapshot -import com.google.firebase.firestore.FieldValue import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.SetOptions import kotlinx.coroutines.suspendCancellableCoroutine @@ -112,31 +111,8 @@ class FirestoreCoupleDataSource @Inject constructor(private val db: FirebaseFire .addOnFailureListener { cont.resumeWithException(it) } } - // After successfully clearing the couple state, queue an in-app notification - // for the partner so they see the unpair event even if FCM is delayed. - if (!partnerId.isNullOrBlank()) { - writePartnerLeftNotification(partnerId) - } } - private suspend fun writePartnerLeftNotification(partnerId: String): Unit = - suspendCancellableCoroutine { cont -> - db.collection(FirestoreCollections.USERS) - .document(partnerId) - .collection("notification_queue") - .add( - mapOf( - "type" to "partner_left", - "title" to "Your partner has left", - "body" to "You are no longer paired.", - "read" to false, - "createdAt" to FieldValue.serverTimestamp() - ) - ) - .addOnSuccessListener { cont.resume(Unit) } - .addOnFailureListener { cont.resumeWithException(it) } - } - @Suppress("UNCHECKED_CAST") private fun DocumentSnapshot.toCouple() = Couple( id = id, diff --git a/app/src/main/java/app/closer/domain/usecase/GameSessionManager.kt b/app/src/main/java/app/closer/domain/usecase/GameSessionManager.kt index 8e1b71dc..a1a1727e 100644 --- a/app/src/main/java/app/closer/domain/usecase/GameSessionManager.kt +++ b/app/src/main/java/app/closer/domain/usecase/GameSessionManager.kt @@ -51,32 +51,12 @@ class GameSessionManager @Inject constructor( ): Result { val couple = coupleRepository.getCoupleForUser(userId) ?: return Result.failure(Exception("User is not in a couple")) - - val activeSession = sessionRepository.getActiveSessionForCouple(couple.id) - if (activeSession != null) { - val partnerId = couple.userIds.firstOrNull { it != userId } - val partnerName = partnerId?.let { userRepository.getUser(it) }?.displayName ?: "Partner" - val gameTypeLabel = gameTypeLabel(gameType) - return Result.failure( - Exception("partner_active_session|$partnerName|$gameTypeLabel") - ) - } - - val session = QuestionSession( - coupleId = couple.id, - categoryId = categoryId ?: "", - questionIds = questionIds ?: emptyList(), - startedByUserId = userId, - gameType = gameType, - status = "active" - ) - - val saveResult = sessionRepository.saveSession(session) - return saveResult.map { session.id } + return startGameWithCouple(userId, couple, gameType, categoryId, questionIds) + .map { it.id } } /** - * Start a game for the currently signed-in user, resolving their couple. + * Start a game for the currently signed-in user, resolving their couple once. * Returns a [GameHandle] on success. Fails if the user is solo or a session * is already active (the failure message carries partner/game context). */ @@ -89,8 +69,36 @@ class GameSessionManager @Inject constructor( ?: return Result.failure(Exception("Not signed in")) val couple = coupleRepository.getCoupleForUser(userId) ?: return Result.failure(Exception("User is not in a couple")) - return startGame(userId, gameType, categoryId, questionIds) - .map { sessionId -> GameHandle(sessionId, couple.id) } + return startGameWithCouple(userId, couple, gameType, categoryId, questionIds) + .map { session -> GameHandle(session.id, couple.id) } + } + + private suspend fun startGameWithCouple( + userId: String, + couple: Couple, + gameType: String, + categoryId: String?, + questionIds: List? + ): Result { + val activeSession = sessionRepository.getActiveSessionForCouple(couple.id) + if (activeSession != null) { + val partnerId = couple.userIds.firstOrNull { it != userId } + val partnerName = partnerId?.let { userRepository.getUser(it) }?.displayName ?: "Partner" + return Result.failure( + Exception("partner_active_session|$partnerName|${gameTypeLabel(gameType)}") + ) + } + + val session = QuestionSession( + coupleId = couple.id, + categoryId = categoryId ?: "", + questionIds = questionIds ?: emptyList(), + startedByUserId = userId, + gameType = gameType, + status = "active" + ) + + return sessionRepository.saveSession(session).map { session } } /**