diff --git a/app/src/main/java/app/closer/ui/home/HomeViewModel.kt b/app/src/main/java/app/closer/ui/home/HomeViewModel.kt index 19cc114e..0e4a8ced 100644 --- a/app/src/main/java/app/closer/ui/home/HomeViewModel.kt +++ b/app/src/main/java/app/closer/ui/home/HomeViewModel.kt @@ -197,7 +197,8 @@ class HomeViewModel @Inject constructor( private val activityDataSource: app.closer.data.remote.FirestoreActivityDataSource, private val dailyQuestionResolver: app.closer.domain.usecase.DailyQuestionResolver, private val dateMemoryDataSource: app.closer.data.remote.FirestoreDateMemoryDataSource, - private val dateReflectionDataSource: app.closer.data.remote.FirestoreDateReflectionDataSource + private val dateReflectionDataSource: app.closer.data.remote.FirestoreDateReflectionDataSource, + private val answerDataSource: FirestoreAnswerDataSource ) : ViewModel() { private val _uiState = MutableStateFlow(HomeUiState()) @@ -267,6 +268,27 @@ class HomeViewModel @Inject constructor( } } + // Heal a Room/Firestore desync for today's daily answer (fresh device / cleared DB): + // if Firestore already holds this user's answer but Room doesn't, write it back so Home + // stops showing a stale "your turn" and never offers a re-answer that the immutable + // secure/payload rule would reject (R23). Room-first → a no-op once Room is correct; + // the answers observer then recomputes the card. + val dailyAnswerCoupleId = couple?.id + if (uid != null && dailyAnswerCoupleId != null && dailyQuestion != null) { + launch { + runCatching { + app.closer.ui.questions.reconcileLocalAnswerFromFirestore( + question = dailyQuestion, + coupleId = dailyAnswerCoupleId, + date = FirestoreAnswerDataSource.todayLocalDateString(), + userId = uid, + firestore = answerDataSource, + localAnswers = localAnswerRepository + ) + }.onFailure { Log.w(TAG, "daily answer reconcile failed", it) } + } + } + // Outcome check-in due-state calculation val appSettings = settingsRepository.settings.first() val outcomeBaselineShownAt = appSettings.outcomeBaselineShownAt