From 720b52a33bcc264ec7fd08e88cbb48463c3d213e Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Jun 2026 16:07:19 -0500 Subject: [PATCH] chore: firebase config, gitignore updates, build tweaks --- .firebaserc | 2 +- .gitignore | 1 + app/build.gradle.kts | 2 +- .../data/remote/FirestoreInviteDataSource.kt | 14 +++++++++++--- .../ui/pairing/CreateInviteViewModel.kt | 6 ++++++ firestore.indexes.json | 19 ++++++++++++++++++- 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/.firebaserc b/.firebaserc index 1c341ef5..052d335f 100644 --- a/.firebaserc +++ b/.firebaserc @@ -1,5 +1,5 @@ { "projects": { - "default": "couples-connect-dev" + "default": "closer-real-app" } } diff --git a/.gitignore b/.gitignore index 2cd1f56f..41d1ffee 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ UI-PLAN.md # Build plans (agent-only, never commit) *_build_plan.md closer_partner_proof_reveal_privacy.md +app/google-services.json.bk diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2134474e..1553fec5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,7 +13,7 @@ android { compileSdk = 35 defaultConfig { - applicationId = "app.closer" + applicationId = "closer.app.package" minSdk = 26 targetSdk = 35 versionCode = 1 diff --git a/app/src/main/java/app/closer/data/remote/FirestoreInviteDataSource.kt b/app/src/main/java/app/closer/data/remote/FirestoreInviteDataSource.kt index 3e0d5a27..fee31e18 100644 --- a/app/src/main/java/app/closer/data/remote/FirestoreInviteDataSource.kt +++ b/app/src/main/java/app/closer/data/remote/FirestoreInviteDataSource.kt @@ -41,14 +41,22 @@ class FirestoreInviteDataSource @Inject constructor( ?: throw IllegalStateException("Invalid response from createInviteCallable") val returnedCode = data["code"] as? String ?: throw IllegalStateException("Missing code in createInviteCallable response") - val expiresAt = data["expiresAt"] as? com.google.firebase.Timestamp - ?: throw IllegalStateException("Missing expiresAt in createInviteCallable response") + // Callable SDK returns Timestamps as Map<_seconds, _nanoseconds>, not firebase.Timestamp. + val expiresAt: com.google.firebase.Timestamp? = when (val raw = data["expiresAt"]) { + is com.google.firebase.Timestamp -> raw + is Map<*, *> -> { + val s = (raw["_seconds"] as? Long) ?: (raw["_seconds"] as? Int)?.toLong() + val n = (raw["_nanoseconds"] as? Long) ?: (raw["_nanoseconds"] as? Int)?.toLong() + if (s != null && n != null) com.google.firebase.Timestamp(s, n.toInt()) else null + } + else -> null + } return CreateInviteResponse(returnedCode, expiresAt) } data class CreateInviteResponse( val code: String, - val expiresAt: com.google.firebase.Timestamp + val expiresAt: com.google.firebase.Timestamp? = null ) /** diff --git a/app/src/main/java/app/closer/ui/pairing/CreateInviteViewModel.kt b/app/src/main/java/app/closer/ui/pairing/CreateInviteViewModel.kt index 7c6aacba..6b9c9243 100644 --- a/app/src/main/java/app/closer/ui/pairing/CreateInviteViewModel.kt +++ b/app/src/main/java/app/closer/ui/pairing/CreateInviteViewModel.kt @@ -1,5 +1,6 @@ package app.closer.ui.pairing +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import app.closer.core.navigation.AppRoute @@ -48,6 +49,7 @@ class CreateInviteViewModel @Inject constructor( _uiState.update { it.copy(isLoading = false, inviteCode = result.code, recoveryPhrase = result.recoveryPhrase) } } .onFailure { e -> + Log.e(TAG, "createInvite failed", e) _uiState.update { it.copy(isLoading = false, error = e.message ?: "Couldn't create invite. Please try again.") } } } @@ -55,4 +57,8 @@ class CreateInviteViewModel @Inject constructor( fun onNavigated() = _uiState.update { it.copy(navigateTo = null) } fun dismissError() = _uiState.update { it.copy(error = null) } + + companion object { + private const val TAG = "CreateInviteViewModel" + } } diff --git a/firestore.indexes.json b/firestore.indexes.json index 086b3b68..3124c680 100644 --- a/firestore.indexes.json +++ b/firestore.indexes.json @@ -1,5 +1,22 @@ { - "indexes": [], + "indexes": [ + { + "collectionGroup": "invites", + "queryScope": "COLLECTION", + "fields": [ + { "fieldPath": "inviterUserId", "order": "ASCENDING" }, + { "fieldPath": "createdAt", "order": "DESCENDING" } + ] + }, + { + "collectionGroup": "capsules", + "queryScope": "COLLECTION_GROUP", + "fields": [ + { "fieldPath": "status", "order": "ASCENDING" }, + { "fieldPath": "unlockAt", "order": "ASCENDING" } + ] + } + ], "fieldOverrides": [ { "collectionGroup": "invite_attempts",