1+ package dev.gitlive.firebase.firestore.internal
2+
3+ import com.google.android.gms.tasks.TaskExecutors
4+ import com.google.firebase.firestore.FieldPath
5+ import com.google.firebase.firestore.MetadataChanges
6+ import com.google.firebase.firestore.Query
7+ import dev.gitlive.firebase.firestore.Direction
8+ import dev.gitlive.firebase.firestore.EncodedFieldPath
9+ import dev.gitlive.firebase.firestore.Filter
10+ import dev.gitlive.firebase.firestore.NativeDocumentSnapshot
11+ import dev.gitlive.firebase.firestore.QuerySnapshot
12+ import dev.gitlive.firebase.firestore.Source
13+ import dev.gitlive.firebase.firestore.WhereConstraint
14+ import kotlinx.coroutines.channels.ProducerScope
15+ import kotlinx.coroutines.channels.awaitClose
16+ import kotlinx.coroutines.flow.callbackFlow
17+ import kotlinx.coroutines.tasks.await
18+
19+ @PublishedApi
20+ internal actual open class NativeQueryWrapper actual internal constructor(actual open val native : Query ) {
21+
22+ actual fun limit (limit : Number ) = native.limit(limit.toLong())
23+
24+ actual val snapshots get() = callbackFlow<QuerySnapshot > {
25+ val listener = native.addSnapshotListener { snapshot, exception ->
26+ snapshot?.let { trySend(QuerySnapshot (snapshot)) }
27+ exception?.let { close(exception) }
28+ }
29+ awaitClose { listener.remove() }
30+ }
31+
32+ actual fun snapshots (includeMetadataChanges : Boolean ) = callbackFlow<QuerySnapshot > {
33+ val metadataChanges =
34+ if (includeMetadataChanges) MetadataChanges .INCLUDE else MetadataChanges .EXCLUDE
35+ val listener = native.addSnapshotListener(metadataChanges) { snapshot, exception ->
36+ snapshot?.let { trySend(QuerySnapshot (snapshot)) }
37+ exception?.let { close(exception) }
38+ }
39+ awaitClose { listener.remove() }
40+ }
41+
42+ actual suspend fun get (source : Source ): QuerySnapshot =
43+ QuerySnapshot (native.get(source.toAndroidSource()).await())
44+
45+ actual fun where (filter : Filter ) = native.where(filter.toAndroidFilter())
46+
47+ private fun Filter.toAndroidFilter (): com.google.firebase.firestore.Filter = when (this ) {
48+ is Filter .And -> com.google.firebase.firestore.Filter .and (* filters.map { it.toAndroidFilter() }
49+ .toTypedArray())
50+ is Filter .Or -> com.google.firebase.firestore.Filter .or (* filters.map { it.toAndroidFilter() }
51+ .toTypedArray())
52+ is Filter .Field -> {
53+ when (constraint) {
54+ is WhereConstraint .ForNullableObject -> {
55+ val modifier: (String , Any? ) -> com.google.firebase.firestore.Filter = when (constraint) {
56+ is WhereConstraint .EqualTo -> com.google.firebase.firestore.Filter ::equalTo
57+ is WhereConstraint .NotEqualTo -> com.google.firebase.firestore.Filter ::notEqualTo
58+ }
59+ modifier.invoke(field, constraint.safeValue)
60+ }
61+ is WhereConstraint .ForObject -> {
62+ val modifier: (String , Any ) -> com.google.firebase.firestore.Filter = when (constraint) {
63+ is WhereConstraint .LessThan -> com.google.firebase.firestore.Filter ::lessThan
64+ is WhereConstraint .GreaterThan -> com.google.firebase.firestore.Filter ::greaterThan
65+ is WhereConstraint .LessThanOrEqualTo -> com.google.firebase.firestore.Filter ::lessThanOrEqualTo
66+ is WhereConstraint .GreaterThanOrEqualTo -> com.google.firebase.firestore.Filter ::greaterThanOrEqualTo
67+ is WhereConstraint .ArrayContains -> com.google.firebase.firestore.Filter ::arrayContains
68+ }
69+ modifier.invoke(field, constraint.safeValue)
70+ }
71+ is WhereConstraint .ForArray -> {
72+ val modifier: (String , List <Any >) -> com.google.firebase.firestore.Filter = when (constraint) {
73+ is WhereConstraint .InArray -> com.google.firebase.firestore.Filter ::inArray
74+ is WhereConstraint .ArrayContainsAny -> com.google.firebase.firestore.Filter ::arrayContainsAny
75+ is WhereConstraint .NotInArray -> com.google.firebase.firestore.Filter ::notInArray
76+ }
77+ modifier.invoke(field, constraint.safeValues)
78+ }
79+ }
80+ }
81+ is Filter .Path -> {
82+ when (constraint) {
83+ is WhereConstraint .ForNullableObject -> {
84+ val modifier: (FieldPath , Any? ) -> com.google.firebase.firestore.Filter = when (constraint) {
85+ is WhereConstraint .EqualTo -> com.google.firebase.firestore.Filter ::equalTo
86+ is WhereConstraint .NotEqualTo -> com.google.firebase.firestore.Filter ::notEqualTo
87+ }
88+ modifier.invoke(path.android, constraint.safeValue)
89+ }
90+ is WhereConstraint .ForObject -> {
91+ val modifier: (FieldPath , Any ) -> com.google.firebase.firestore.Filter = when (constraint) {
92+ is WhereConstraint .LessThan -> com.google.firebase.firestore.Filter ::lessThan
93+ is WhereConstraint .GreaterThan -> com.google.firebase.firestore.Filter ::greaterThan
94+ is WhereConstraint .LessThanOrEqualTo -> com.google.firebase.firestore.Filter ::lessThanOrEqualTo
95+ is WhereConstraint .GreaterThanOrEqualTo -> com.google.firebase.firestore.Filter ::greaterThanOrEqualTo
96+ is WhereConstraint .ArrayContains -> com.google.firebase.firestore.Filter ::arrayContains
97+ }
98+ modifier.invoke(path.android, constraint.safeValue)
99+ }
100+ is WhereConstraint .ForArray -> {
101+ val modifier: (FieldPath , List <Any >) -> com.google.firebase.firestore.Filter = when (constraint) {
102+ is WhereConstraint .InArray -> com.google.firebase.firestore.Filter ::inArray
103+ is WhereConstraint .ArrayContainsAny -> com.google.firebase.firestore.Filter ::arrayContainsAny
104+ is WhereConstraint .NotInArray -> com.google.firebase.firestore.Filter ::notInArray
105+ }
106+ modifier.invoke(path.android, constraint.safeValues)
107+ }
108+ }
109+ }
110+ }
111+
112+ actual fun orderBy (field : String , direction : Direction ) = native.orderBy(field, direction)
113+ actual fun orderBy (field : EncodedFieldPath , direction : Direction ) = native.orderBy(field, direction)
114+
115+ actual fun startAfter (document : NativeDocumentSnapshot ) = native.startAfter(document)
116+ actual fun startAfter (vararg fieldValues : Any ) = native.startAfter(* fieldValues)
117+ actual fun startAt (document : NativeDocumentSnapshot ) = native.startAt(document)
118+ actual fun startAt (vararg fieldValues : Any ) = native.startAt(* fieldValues)
119+
120+ actual fun endBefore (document : NativeDocumentSnapshot ) = native.endBefore(document)
121+ actual fun endBefore (vararg fieldValues : Any ) = native.endBefore(* fieldValues)
122+ actual fun endAt (document : NativeDocumentSnapshot ) = native.endAt(document)
123+ actual fun endAt (vararg fieldValues : Any ) = native.endAt(* fieldValues)
124+
125+ private fun addSnapshotListener (
126+ includeMetadataChanges : Boolean = false,
127+ listener : ProducerScope <QuerySnapshot >.(com.google.firebase.firestore.QuerySnapshot ? , com.google.firebase.firestore.FirebaseFirestoreException ? ) -> Unit
128+ ) = callbackFlow {
129+ val executor = callbackExecutorMap[native.firestore] ? : TaskExecutors .MAIN_THREAD
130+ val metadataChanges =
131+ if (includeMetadataChanges) MetadataChanges .INCLUDE else MetadataChanges .EXCLUDE
132+ val registration =
133+ native.addSnapshotListener(executor, metadataChanges) { snapshots, exception ->
134+ listener(snapshots, exception)
135+ }
136+ awaitClose { registration.remove() }
137+ }
138+ }
0 commit comments