refactor: centralize all Firestore collection paths in FirestoreCollections constants
This commit is contained in:
parent
d86a5de2a0
commit
662a49df9d
|
|
@ -1,5 +1,6 @@
|
|||
package app.closer.core.billing
|
||||
|
||||
import app.closer.data.remote.FirestoreCollections
|
||||
import app.closer.domain.model.AuthState
|
||||
import app.closer.domain.repository.AuthRepository
|
||||
import com.google.firebase.firestore.DocumentSnapshot
|
||||
|
|
@ -125,7 +126,9 @@ class FirestoreEntitlementChecker @Inject constructor(
|
|||
}
|
||||
|
||||
private fun entitlementsRef(userId: String) =
|
||||
firestore.collection("users").document(userId).collection("entitlements").document("premium")
|
||||
firestore.collection(FirestoreCollections.USERS).document(userId)
|
||||
.collection(FirestoreCollections.Users.ENTITLEMENTS)
|
||||
.document(FirestoreCollections.Users.ENTITLEMENT_PREMIUM_DOC)
|
||||
|
||||
companion object {
|
||||
private const val PREMIUM_ENTITLEMENT_ID = "closer_premium"
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ class FirestoreBucketListDataSource @Inject constructor() {
|
|||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun itemsRef(coupleId: String) =
|
||||
db.collection("couples").document(coupleId).collection("bucket_list")
|
||||
db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
.collection(FirestoreCollections.Couples.BUCKET_LIST)
|
||||
|
||||
// ─── CRUD methods ────────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package app.closer.data.remote
|
||||
|
||||
/**
|
||||
* Single source of truth for all Firestore collection and fixed document-ID names.
|
||||
*
|
||||
* Use these constants everywhere instead of inline string literals so that a path
|
||||
* rename requires a change in exactly one place and the compiler catches every caller.
|
||||
*/
|
||||
object FirestoreCollections {
|
||||
|
||||
// ── Top-level collections ─────────────────────────────────────────────────
|
||||
const val USERS = "users"
|
||||
const val COUPLES = "couples"
|
||||
const val INVITES = "invites"
|
||||
|
||||
// ── Subcollections under users/{uid} ──────────────────────────────────────
|
||||
object Users {
|
||||
const val ENTITLEMENTS = "entitlements"
|
||||
const val FCM_TOKENS = "fcmTokens"
|
||||
const val ENTITLEMENT_PREMIUM_DOC = "premium"
|
||||
}
|
||||
|
||||
// ── Subcollections under couples/{coupleId} ───────────────────────────────
|
||||
object Couples {
|
||||
const val SESSIONS = "sessions"
|
||||
const val QUESTION_THREADS = "question_threads"
|
||||
const val DATE_SWIPES = "date_swipes"
|
||||
const val DATE_MATCHES = "date_matches"
|
||||
const val DATE_PLAN_PREFERENCES = "date_plan_preferences"
|
||||
const val DATE_PLANS = "date_plans"
|
||||
const val BUCKET_LIST = "bucket_list"
|
||||
}
|
||||
|
||||
// ── Subcollections under …/question_threads/{threadId} ────────────────────
|
||||
object QuestionThreads {
|
||||
const val ANSWERS = "answers"
|
||||
const val MESSAGES = "messages"
|
||||
const val REACTIONS = "reactions"
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,8 @@ import kotlin.coroutines.resumeWithException
|
|||
class FirestoreCoupleDataSource @Inject constructor() {
|
||||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun coupleRef(coupleId: String) = db.collection("couples").document(coupleId)
|
||||
private fun userRef(uid: String) = db.collection("users").document(uid)
|
||||
private fun coupleRef(coupleId: String) = db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
private fun userRef(uid: String) = db.collection(FirestoreCollections.USERS).document(uid)
|
||||
|
||||
suspend fun createCouple(inviterUserId: String, acceptorUserId: String, inviteCode: String): String {
|
||||
val coupleId = UUID.randomUUID().toString()
|
||||
|
|
@ -89,7 +89,7 @@ class FirestoreCoupleDataSource @Inject constructor() {
|
|||
|
||||
suspend fun leaveCouple(userId: String) {
|
||||
val userSnap = suspendCancellableCoroutine<DocumentSnapshot> { cont ->
|
||||
db.collection("users").document(userId).get()
|
||||
userRef(userId).get()
|
||||
.addOnSuccessListener { cont.resume(it) }
|
||||
.addOnFailureListener { cont.resumeWithException(it) }
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ class FirestoreCoupleDataSource @Inject constructor() {
|
|||
suspendCancellableCoroutine<Unit> { cont ->
|
||||
val batch = db.batch()
|
||||
allUserIds.forEach { uid ->
|
||||
batch.update(db.collection("users").document(uid), "coupleId", null)
|
||||
batch.update(userRef(uid), "coupleId", null)
|
||||
}
|
||||
batch.commit()
|
||||
.addOnSuccessListener { cont.resume(Unit) }
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ class FirestoreDateMatchDataSource @Inject constructor() {
|
|||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun matchesRef(coupleId: String) =
|
||||
db.collection("couples").document(coupleId).collection("date_matches")
|
||||
db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
.collection(FirestoreCollections.Couples.DATE_MATCHES)
|
||||
|
||||
suspend fun createMatch(coupleId: String, dateIdeaId: String, matchedBy: List<String>): String {
|
||||
val doc = matchesRef(coupleId).document()
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@ class FirestoreDatePlanDataSource @Inject constructor() {
|
|||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun preferencesRef(coupleId: String) =
|
||||
db.collection("couples").document(coupleId).collection("date_plan_preferences")
|
||||
db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
.collection(FirestoreCollections.Couples.DATE_PLAN_PREFERENCES)
|
||||
|
||||
private fun plansRef(coupleId: String) =
|
||||
db.collection("couples").document(coupleId).collection("date_plans")
|
||||
db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
.collection(FirestoreCollections.Couples.DATE_PLANS)
|
||||
|
||||
// ─── Preference methods ──────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ class FirestoreDateSwipeDataSource @Inject constructor() {
|
|||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun swipesRef(coupleId: String) =
|
||||
db.collection("couples").document(coupleId).collection("date_swipes")
|
||||
db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
.collection(FirestoreCollections.Couples.DATE_SWIPES)
|
||||
|
||||
suspend fun recordSwipe(coupleId: String, swipe: DateSwipe) {
|
||||
val path = swipesRef(coupleId).document(swipe.dateIdeaId)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import kotlin.random.Random
|
|||
class FirestoreInviteDataSource @Inject constructor() {
|
||||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun inviteRef(code: String) = db.collection("invites").document(code)
|
||||
private fun inviteRef(code: String) = db.collection(FirestoreCollections.INVITES).document(code)
|
||||
|
||||
fun generateCode(): String = (1..6)
|
||||
.map { CODE_CHARS[Random.nextInt(CODE_CHARS.length)] }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
private val db = FirebaseFirestore.getInstance()
|
||||
|
||||
private fun threadsRef(coupleId: String) =
|
||||
db.collection("couples").document(coupleId).collection("question_threads")
|
||||
db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||
.collection(FirestoreCollections.Couples.QUESTION_THREADS)
|
||||
|
||||
// ─── Thread ─────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -77,7 +78,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
val now = FieldValue.serverTimestamp()
|
||||
threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("answers")
|
||||
.collection(FirestoreCollections.QuestionThreads.ANSWERS)
|
||||
.document(userId)
|
||||
.set(
|
||||
mapOf(
|
||||
|
|
@ -96,7 +97,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
suspend fun getAnswerCount(coupleId: String, threadId: String): Int {
|
||||
val snap = threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("answers")
|
||||
.collection(FirestoreCollections.QuestionThreads.ANSWERS)
|
||||
.getAwait()
|
||||
return snap.size()
|
||||
}
|
||||
|
|
@ -104,7 +105,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
fun observeAnswers(coupleId: String, threadId: String): Flow<List<QuestionAnswer>> = callbackFlow {
|
||||
val listener = threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("answers")
|
||||
.collection(FirestoreCollections.QuestionThreads.ANSWERS)
|
||||
.addSnapshotListener { snap, err ->
|
||||
if (err != null || snap == null) return@addSnapshotListener
|
||||
trySend(snap.documents.mapNotNull { it.toQuestionAnswer() })
|
||||
|
|
@ -117,7 +118,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
suspend fun sendMessage(coupleId: String, threadId: String, message: QuestionMessage) {
|
||||
threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("messages")
|
||||
.collection(FirestoreCollections.QuestionThreads.MESSAGES)
|
||||
.add(
|
||||
mapOf(
|
||||
"userId" to message.userId,
|
||||
|
|
@ -130,7 +131,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
fun observeMessages(coupleId: String, threadId: String): Flow<List<QuestionMessage>> = callbackFlow {
|
||||
val listener = threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("messages")
|
||||
.collection(FirestoreCollections.QuestionThreads.MESSAGES)
|
||||
.orderBy("createdAt", Query.Direction.ASCENDING)
|
||||
.addSnapshotListener { snap, err ->
|
||||
if (err != null || snap == null) return@addSnapshotListener
|
||||
|
|
@ -145,7 +146,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
val docId = "${reaction.userId}_${reaction.targetUserId}"
|
||||
threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("reactions")
|
||||
.collection(FirestoreCollections.QuestionThreads.REACTIONS)
|
||||
.document(docId)
|
||||
.set(
|
||||
mapOf(
|
||||
|
|
@ -160,7 +161,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
|||
fun observeReactions(coupleId: String, threadId: String): Flow<List<QuestionReaction>> = callbackFlow {
|
||||
val listener = threadsRef(coupleId)
|
||||
.document(threadId)
|
||||
.collection("reactions")
|
||||
.collection(FirestoreCollections.QuestionThreads.REACTIONS)
|
||||
.addSnapshotListener { snap, err ->
|
||||
if (err != null || snap == null) return@addSnapshotListener
|
||||
trySend(snap.documents.mapNotNull { it.toQuestionReaction() })
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import kotlin.coroutines.resumeWithException
|
|||
class FirestoreUserDataSource @Inject constructor() {
|
||||
|
||||
private val db = FirebaseFirestore.getInstance()
|
||||
private fun userRef(uid: String) = db.collection("users").document(uid)
|
||||
private fun userRef(uid: String) = db.collection(FirestoreCollections.USERS).document(uid)
|
||||
|
||||
suspend fun getUser(uid: String): User? =
|
||||
suspendCancellableCoroutine { cont ->
|
||||
|
|
@ -89,7 +89,7 @@ class FirestoreUserDataSource @Inject constructor() {
|
|||
token: String,
|
||||
metadata: DeviceMetadata
|
||||
): Unit = suspendCancellableCoroutine { cont ->
|
||||
userRef(uid).collection("fcmTokens").document(token)
|
||||
userRef(uid).collection(FirestoreCollections.Users.FCM_TOKENS).document(token)
|
||||
.set(
|
||||
mapOf(
|
||||
"token" to token,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package app.closer.data.repository
|
||||
|
||||
import app.closer.data.remote.FirestoreCollections
|
||||
import app.closer.domain.model.QuestionSession
|
||||
import app.closer.domain.repository.QuestionSessionRepository
|
||||
import com.google.firebase.firestore.FirebaseFirestore
|
||||
|
|
@ -14,14 +15,14 @@ class QuestionSessionRepositoryImpl @Inject constructor(
|
|||
|
||||
override suspend fun saveSession(session: QuestionSession): Result<Unit> = runCatching {
|
||||
val doc = if (session.id.isBlank()) {
|
||||
firestore.collection("couples")
|
||||
firestore.collection(FirestoreCollections.COUPLES)
|
||||
.document(session.coupleId)
|
||||
.collection("sessions")
|
||||
.collection(FirestoreCollections.Couples.SESSIONS)
|
||||
.document()
|
||||
} else {
|
||||
firestore.collection("couples")
|
||||
firestore.collection(FirestoreCollections.COUPLES)
|
||||
.document(session.coupleId)
|
||||
.collection("sessions")
|
||||
.collection(FirestoreCollections.Couples.SESSIONS)
|
||||
.document(session.id)
|
||||
}
|
||||
|
||||
|
|
@ -41,9 +42,9 @@ class QuestionSessionRepositoryImpl @Inject constructor(
|
|||
|
||||
override suspend fun getSessionsForCouple(coupleId: String): Result<List<QuestionSession>> =
|
||||
runCatching {
|
||||
firestore.collection("couples")
|
||||
firestore.collection(FirestoreCollections.COUPLES)
|
||||
.document(coupleId)
|
||||
.collection("sessions")
|
||||
.collection(FirestoreCollections.Couples.SESSIONS)
|
||||
.orderBy("completedAt", com.google.firebase.firestore.Query.Direction.DESCENDING)
|
||||
.limit(50)
|
||||
.get()
|
||||
|
|
|
|||
Loading…
Reference in New Issue