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
|
package app.closer.core.billing
|
||||||
|
|
||||||
|
import app.closer.data.remote.FirestoreCollections
|
||||||
import app.closer.domain.model.AuthState
|
import app.closer.domain.model.AuthState
|
||||||
import app.closer.domain.repository.AuthRepository
|
import app.closer.domain.repository.AuthRepository
|
||||||
import com.google.firebase.firestore.DocumentSnapshot
|
import com.google.firebase.firestore.DocumentSnapshot
|
||||||
|
|
@ -125,7 +126,9 @@ class FirestoreEntitlementChecker @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun entitlementsRef(userId: String) =
|
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 {
|
companion object {
|
||||||
private const val PREMIUM_ENTITLEMENT_ID = "closer_premium"
|
private const val PREMIUM_ENTITLEMENT_ID = "closer_premium"
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ class FirestoreBucketListDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
private val db = FirebaseFirestore.getInstance()
|
||||||
private fun itemsRef(coupleId: String) =
|
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 ────────────────────────────────────────────────────────
|
// ─── 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() {
|
class FirestoreCoupleDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
private val db = FirebaseFirestore.getInstance()
|
||||||
private fun coupleRef(coupleId: String) = db.collection("couples").document(coupleId)
|
private fun coupleRef(coupleId: String) = db.collection(FirestoreCollections.COUPLES).document(coupleId)
|
||||||
private fun userRef(uid: String) = db.collection("users").document(uid)
|
private fun userRef(uid: String) = db.collection(FirestoreCollections.USERS).document(uid)
|
||||||
|
|
||||||
suspend fun createCouple(inviterUserId: String, acceptorUserId: String, inviteCode: String): String {
|
suspend fun createCouple(inviterUserId: String, acceptorUserId: String, inviteCode: String): String {
|
||||||
val coupleId = UUID.randomUUID().toString()
|
val coupleId = UUID.randomUUID().toString()
|
||||||
|
|
@ -89,7 +89,7 @@ class FirestoreCoupleDataSource @Inject constructor() {
|
||||||
|
|
||||||
suspend fun leaveCouple(userId: String) {
|
suspend fun leaveCouple(userId: String) {
|
||||||
val userSnap = suspendCancellableCoroutine<DocumentSnapshot> { cont ->
|
val userSnap = suspendCancellableCoroutine<DocumentSnapshot> { cont ->
|
||||||
db.collection("users").document(userId).get()
|
userRef(userId).get()
|
||||||
.addOnSuccessListener { cont.resume(it) }
|
.addOnSuccessListener { cont.resume(it) }
|
||||||
.addOnFailureListener { cont.resumeWithException(it) }
|
.addOnFailureListener { cont.resumeWithException(it) }
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ class FirestoreCoupleDataSource @Inject constructor() {
|
||||||
suspendCancellableCoroutine<Unit> { cont ->
|
suspendCancellableCoroutine<Unit> { cont ->
|
||||||
val batch = db.batch()
|
val batch = db.batch()
|
||||||
allUserIds.forEach { uid ->
|
allUserIds.forEach { uid ->
|
||||||
batch.update(db.collection("users").document(uid), "coupleId", null)
|
batch.update(userRef(uid), "coupleId", null)
|
||||||
}
|
}
|
||||||
batch.commit()
|
batch.commit()
|
||||||
.addOnSuccessListener { cont.resume(Unit) }
|
.addOnSuccessListener { cont.resume(Unit) }
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ class FirestoreDateMatchDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
private val db = FirebaseFirestore.getInstance()
|
||||||
private fun matchesRef(coupleId: String) =
|
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 {
|
suspend fun createMatch(coupleId: String, dateIdeaId: String, matchedBy: List<String>): String {
|
||||||
val doc = matchesRef(coupleId).document()
|
val doc = matchesRef(coupleId).document()
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,12 @@ class FirestoreDatePlanDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
private val db = FirebaseFirestore.getInstance()
|
||||||
private fun preferencesRef(coupleId: String) =
|
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) =
|
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 ──────────────────────────────────────────────────
|
// ─── Preference methods ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ class FirestoreDateSwipeDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
private val db = FirebaseFirestore.getInstance()
|
||||||
private fun swipesRef(coupleId: String) =
|
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) {
|
suspend fun recordSwipe(coupleId: String, swipe: DateSwipe) {
|
||||||
val path = swipesRef(coupleId).document(swipe.dateIdeaId)
|
val path = swipesRef(coupleId).document(swipe.dateIdeaId)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import kotlin.random.Random
|
||||||
class FirestoreInviteDataSource @Inject constructor() {
|
class FirestoreInviteDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
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)
|
fun generateCode(): String = (1..6)
|
||||||
.map { CODE_CHARS[Random.nextInt(CODE_CHARS.length)] }
|
.map { CODE_CHARS[Random.nextInt(CODE_CHARS.length)] }
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
private val db = FirebaseFirestore.getInstance()
|
private val db = FirebaseFirestore.getInstance()
|
||||||
|
|
||||||
private fun threadsRef(coupleId: String) =
|
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 ─────────────────────────────────────────────────────────────────
|
// ─── Thread ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -77,7 +78,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
val now = FieldValue.serverTimestamp()
|
val now = FieldValue.serverTimestamp()
|
||||||
threadsRef(coupleId)
|
threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("answers")
|
.collection(FirestoreCollections.QuestionThreads.ANSWERS)
|
||||||
.document(userId)
|
.document(userId)
|
||||||
.set(
|
.set(
|
||||||
mapOf(
|
mapOf(
|
||||||
|
|
@ -96,7 +97,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
suspend fun getAnswerCount(coupleId: String, threadId: String): Int {
|
suspend fun getAnswerCount(coupleId: String, threadId: String): Int {
|
||||||
val snap = threadsRef(coupleId)
|
val snap = threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("answers")
|
.collection(FirestoreCollections.QuestionThreads.ANSWERS)
|
||||||
.getAwait()
|
.getAwait()
|
||||||
return snap.size()
|
return snap.size()
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +105,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
fun observeAnswers(coupleId: String, threadId: String): Flow<List<QuestionAnswer>> = callbackFlow {
|
fun observeAnswers(coupleId: String, threadId: String): Flow<List<QuestionAnswer>> = callbackFlow {
|
||||||
val listener = threadsRef(coupleId)
|
val listener = threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("answers")
|
.collection(FirestoreCollections.QuestionThreads.ANSWERS)
|
||||||
.addSnapshotListener { snap, err ->
|
.addSnapshotListener { snap, err ->
|
||||||
if (err != null || snap == null) return@addSnapshotListener
|
if (err != null || snap == null) return@addSnapshotListener
|
||||||
trySend(snap.documents.mapNotNull { it.toQuestionAnswer() })
|
trySend(snap.documents.mapNotNull { it.toQuestionAnswer() })
|
||||||
|
|
@ -117,7 +118,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
suspend fun sendMessage(coupleId: String, threadId: String, message: QuestionMessage) {
|
suspend fun sendMessage(coupleId: String, threadId: String, message: QuestionMessage) {
|
||||||
threadsRef(coupleId)
|
threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("messages")
|
.collection(FirestoreCollections.QuestionThreads.MESSAGES)
|
||||||
.add(
|
.add(
|
||||||
mapOf(
|
mapOf(
|
||||||
"userId" to message.userId,
|
"userId" to message.userId,
|
||||||
|
|
@ -130,7 +131,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
fun observeMessages(coupleId: String, threadId: String): Flow<List<QuestionMessage>> = callbackFlow {
|
fun observeMessages(coupleId: String, threadId: String): Flow<List<QuestionMessage>> = callbackFlow {
|
||||||
val listener = threadsRef(coupleId)
|
val listener = threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("messages")
|
.collection(FirestoreCollections.QuestionThreads.MESSAGES)
|
||||||
.orderBy("createdAt", Query.Direction.ASCENDING)
|
.orderBy("createdAt", Query.Direction.ASCENDING)
|
||||||
.addSnapshotListener { snap, err ->
|
.addSnapshotListener { snap, err ->
|
||||||
if (err != null || snap == null) return@addSnapshotListener
|
if (err != null || snap == null) return@addSnapshotListener
|
||||||
|
|
@ -145,7 +146,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
val docId = "${reaction.userId}_${reaction.targetUserId}"
|
val docId = "${reaction.userId}_${reaction.targetUserId}"
|
||||||
threadsRef(coupleId)
|
threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("reactions")
|
.collection(FirestoreCollections.QuestionThreads.REACTIONS)
|
||||||
.document(docId)
|
.document(docId)
|
||||||
.set(
|
.set(
|
||||||
mapOf(
|
mapOf(
|
||||||
|
|
@ -160,7 +161,7 @@ class FirestoreQuestionThreadDataSource @Inject constructor() {
|
||||||
fun observeReactions(coupleId: String, threadId: String): Flow<List<QuestionReaction>> = callbackFlow {
|
fun observeReactions(coupleId: String, threadId: String): Flow<List<QuestionReaction>> = callbackFlow {
|
||||||
val listener = threadsRef(coupleId)
|
val listener = threadsRef(coupleId)
|
||||||
.document(threadId)
|
.document(threadId)
|
||||||
.collection("reactions")
|
.collection(FirestoreCollections.QuestionThreads.REACTIONS)
|
||||||
.addSnapshotListener { snap, err ->
|
.addSnapshotListener { snap, err ->
|
||||||
if (err != null || snap == null) return@addSnapshotListener
|
if (err != null || snap == null) return@addSnapshotListener
|
||||||
trySend(snap.documents.mapNotNull { it.toQuestionReaction() })
|
trySend(snap.documents.mapNotNull { it.toQuestionReaction() })
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import kotlin.coroutines.resumeWithException
|
||||||
class FirestoreUserDataSource @Inject constructor() {
|
class FirestoreUserDataSource @Inject constructor() {
|
||||||
|
|
||||||
private val db = FirebaseFirestore.getInstance()
|
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? =
|
suspend fun getUser(uid: String): User? =
|
||||||
suspendCancellableCoroutine { cont ->
|
suspendCancellableCoroutine { cont ->
|
||||||
|
|
@ -89,7 +89,7 @@ class FirestoreUserDataSource @Inject constructor() {
|
||||||
token: String,
|
token: String,
|
||||||
metadata: DeviceMetadata
|
metadata: DeviceMetadata
|
||||||
): Unit = suspendCancellableCoroutine { cont ->
|
): Unit = suspendCancellableCoroutine { cont ->
|
||||||
userRef(uid).collection("fcmTokens").document(token)
|
userRef(uid).collection(FirestoreCollections.Users.FCM_TOKENS).document(token)
|
||||||
.set(
|
.set(
|
||||||
mapOf(
|
mapOf(
|
||||||
"token" to token,
|
"token" to token,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package app.closer.data.repository
|
package app.closer.data.repository
|
||||||
|
|
||||||
|
import app.closer.data.remote.FirestoreCollections
|
||||||
import app.closer.domain.model.QuestionSession
|
import app.closer.domain.model.QuestionSession
|
||||||
import app.closer.domain.repository.QuestionSessionRepository
|
import app.closer.domain.repository.QuestionSessionRepository
|
||||||
import com.google.firebase.firestore.FirebaseFirestore
|
import com.google.firebase.firestore.FirebaseFirestore
|
||||||
|
|
@ -14,14 +15,14 @@ class QuestionSessionRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
override suspend fun saveSession(session: QuestionSession): Result<Unit> = runCatching {
|
override suspend fun saveSession(session: QuestionSession): Result<Unit> = runCatching {
|
||||||
val doc = if (session.id.isBlank()) {
|
val doc = if (session.id.isBlank()) {
|
||||||
firestore.collection("couples")
|
firestore.collection(FirestoreCollections.COUPLES)
|
||||||
.document(session.coupleId)
|
.document(session.coupleId)
|
||||||
.collection("sessions")
|
.collection(FirestoreCollections.Couples.SESSIONS)
|
||||||
.document()
|
.document()
|
||||||
} else {
|
} else {
|
||||||
firestore.collection("couples")
|
firestore.collection(FirestoreCollections.COUPLES)
|
||||||
.document(session.coupleId)
|
.document(session.coupleId)
|
||||||
.collection("sessions")
|
.collection(FirestoreCollections.Couples.SESSIONS)
|
||||||
.document(session.id)
|
.document(session.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,9 +42,9 @@ class QuestionSessionRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
override suspend fun getSessionsForCouple(coupleId: String): Result<List<QuestionSession>> =
|
override suspend fun getSessionsForCouple(coupleId: String): Result<List<QuestionSession>> =
|
||||||
runCatching {
|
runCatching {
|
||||||
firestore.collection("couples")
|
firestore.collection(FirestoreCollections.COUPLES)
|
||||||
.document(coupleId)
|
.document(coupleId)
|
||||||
.collection("sessions")
|
.collection(FirestoreCollections.Couples.SESSIONS)
|
||||||
.orderBy("completedAt", com.google.firebase.firestore.Query.Direction.DESCENDING)
|
.orderBy("completedAt", com.google.firebase.firestore.Query.Direction.DESCENDING)
|
||||||
.limit(50)
|
.limit(50)
|
||||||
.get()
|
.get()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue