@@ -18,12 +18,20 @@ 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.database.ChildEventListener
21
22
import com.google.firebase.database.DataSnapshot
23
+ import com.google.firebase.database.DatabaseError
22
24
import com.google.firebase.database.FirebaseDatabase
23
25
import com.google.firebase.database.GenericTypeIndicator
24
26
import com.google.firebase.database.MutableData
27
+ import com.google.firebase.database.Query
28
+ import com.google.firebase.database.ValueEventListener
25
29
import com.google.firebase.ktx.Firebase
26
30
import com.google.firebase.platforminfo.LibraryVersionComponent
31
+ import kotlinx.coroutines.cancel
32
+ import kotlinx.coroutines.channels.awaitClose
33
+ import kotlinx.coroutines.channels.trySendBlocking
34
+ import kotlinx.coroutines.flow.callbackFlow
27
35
28
36
/* * Returns the [FirebaseDatabase] instance of the default [FirebaseApp]. */
29
37
val Firebase .database: FirebaseDatabase
@@ -59,6 +67,68 @@ inline fun <reified T> MutableData.getValue(): T? {
59
67
return getValue(object : GenericTypeIndicator <T >() {})
60
68
}
61
69
70
+ /* *
71
+ * Starts listening to this query and emits its values via a [Flow].
72
+ *
73
+ * - When the returned flow starts being collected, a [ValueEventListener] will be attached.
74
+ * - When the flow completes, the listener will be removed.
75
+ */
76
+ val Query .snapshots
77
+ get() = callbackFlow<DataSnapshot > {
78
+ val listener = addValueEventListener(object : ValueEventListener {
79
+ override fun onDataChange (snapshot : DataSnapshot ) {
80
+ repo.scheduleNow {
81
+ trySendBlocking(snapshot)
82
+ }
83
+ }
84
+
85
+ override fun onCancelled (error : DatabaseError ) {
86
+ cancel(message = " Error getting Query snapshot" , cause = error.toException())
87
+ }
88
+ })
89
+ awaitClose { removeEventListener(listener) }
90
+ }
91
+
92
+ /* *
93
+ * Starts listening to this query's child events and emits its values via a [Flow].
94
+ *
95
+ * - When the returned flow starts being collected, a [ChildEventListener] will be attached.
96
+ * - When the flow completes, the listener will be removed.
97
+ */
98
+ val Query .childEvents
99
+ get() = callbackFlow<ChildEvent > {
100
+ val listener = addChildEventListener(object : ChildEventListener {
101
+ override fun onChildAdded (snapshot : DataSnapshot , previousChildName : String? ) {
102
+ repo.scheduleNow {
103
+ trySendBlocking(ChildEvent .Added (snapshot, previousChildName))
104
+ }
105
+ }
106
+
107
+ override fun onChildChanged (snapshot : DataSnapshot , previousChildName : String? ) {
108
+ repo.scheduleNow {
109
+ trySendBlocking(ChildEvent .Changed (snapshot, previousChildName))
110
+ }
111
+ }
112
+
113
+ override fun onChildRemoved (snapshot : DataSnapshot ) {
114
+ repo.scheduleNow {
115
+ trySendBlocking(ChildEvent .Removed (snapshot))
116
+ }
117
+ }
118
+
119
+ override fun onChildMoved (snapshot : DataSnapshot , previousChildName : String? ) {
120
+ repo.scheduleNow {
121
+ trySendBlocking(ChildEvent .Moved (snapshot, previousChildName))
122
+ }
123
+ }
124
+
125
+ override fun onCancelled (error : DatabaseError ) {
126
+ cancel(message = " Error getting Query childEvent" , cause = error.toException())
127
+ }
128
+ })
129
+ awaitClose { removeEventListener(listener) }
130
+ }
131
+
62
132
internal const val LIBRARY_NAME : String = " fire-db-ktx"
63
133
64
134
/* * @suppress */
0 commit comments