@@ -18,14 +18,23 @@ import androidx.annotation.Keep
18
18
import com.google.firebase.FirebaseApp
19
19
import com.google.firebase.components.Component
20
20
import com.google.firebase.components.ComponentRegistrar
21
+ import com.google.firebase.firestore.DocumentReference
21
22
import com.google.firebase.firestore.DocumentSnapshot
22
23
import com.google.firebase.firestore.FieldPath
23
24
import com.google.firebase.firestore.FirebaseFirestore
24
25
import com.google.firebase.firestore.FirebaseFirestoreSettings
26
+ import com.google.firebase.firestore.MetadataChanges
27
+ import com.google.firebase.firestore.Query
25
28
import com.google.firebase.firestore.QueryDocumentSnapshot
26
29
import com.google.firebase.firestore.QuerySnapshot
30
+ import com.google.firebase.firestore.util.Executors.BACKGROUND_EXECUTOR
27
31
import com.google.firebase.ktx.Firebase
28
32
import com.google.firebase.platforminfo.LibraryVersionComponent
33
+ import kotlinx.coroutines.cancel
34
+ import kotlinx.coroutines.channels.awaitClose
35
+ import kotlinx.coroutines.channels.trySendBlocking
36
+ import kotlinx.coroutines.flow.Flow
37
+ import kotlinx.coroutines.flow.callbackFlow
29
38
30
39
/* * Returns the [FirebaseFirestore] instance of the default [FirebaseApp]. */
31
40
val Firebase .firestore: FirebaseFirestore
@@ -162,3 +171,49 @@ class FirebaseFirestoreKtxRegistrar : ComponentRegistrar {
162
171
override fun getComponents (): List <Component <* >> =
163
172
listOf (LibraryVersionComponent .create(LIBRARY_NAME , BuildConfig .VERSION_NAME ))
164
173
}
174
+
175
+ /* *
176
+ * Starts listening to the document referenced by this `DocumentReference` with the given options and emits its values via a [Flow].
177
+ *
178
+ * - When the returned flow starts being collected, an [EventListener] will be attached.
179
+ * - When the flow completes, the listener will be removed.
180
+ *
181
+ * @param metadataChanges controls metadata-only changes. Default: [MetadataChanges.EXCLUDE]
182
+ */
183
+ fun DocumentReference.snapshots (
184
+ metadataChanges : MetadataChanges = MetadataChanges .EXCLUDE
185
+ ): Flow <DocumentSnapshot > {
186
+ return callbackFlow {
187
+ val registration = addSnapshotListener(BACKGROUND_EXECUTOR , metadataChanges) { snapshot, exception ->
188
+ if (exception != null ) {
189
+ cancel(message = " Error getting DocumentReference snapshot" , cause = exception)
190
+ } else if (snapshot != null ) {
191
+ trySendBlocking(snapshot)
192
+ }
193
+ }
194
+ awaitClose { registration.remove() }
195
+ }
196
+ }
197
+
198
+ /* *
199
+ * Starts listening to this query with the given options and emits its values via a [Flow].
200
+ *
201
+ * - When the returned flow starts being collected, an [EventListener] will be attached.
202
+ * - When the flow completes, the listener will be removed.
203
+ *
204
+ * @param metadataChanges controls metadata-only changes. Default: [MetadataChanges.EXCLUDE]
205
+ */
206
+ fun Query.snapshots (
207
+ metadataChanges : MetadataChanges = MetadataChanges .EXCLUDE
208
+ ): Flow <QuerySnapshot > {
209
+ return callbackFlow {
210
+ val registration = addSnapshotListener(BACKGROUND_EXECUTOR , metadataChanges) { snapshot, exception ->
211
+ if (exception != null ) {
212
+ cancel(message = " Error getting Query snapshot" , cause = exception)
213
+ } else if (snapshot != null ) {
214
+ trySendBlocking(snapshot)
215
+ }
216
+ }
217
+ awaitClose { registration.remove() }
218
+ }
219
+ }
0 commit comments