diff --git a/realtimedb/src/main/kotlin/de/sipgate/federmappe/realtimedb/DatabaseReferenceExt.kt b/realtimedb/src/main/kotlin/de/sipgate/federmappe/realtimedb/DatabaseReferenceExt.kt new file mode 100644 index 0000000..5986637 --- /dev/null +++ b/realtimedb/src/main/kotlin/de/sipgate/federmappe/realtimedb/DatabaseReferenceExt.kt @@ -0,0 +1,46 @@ +package de.sipgate.federmappe.realtimedb + +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.ValueEventListener +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerializationException +import kotlinx.serialization.serializer + + +@ExperimentalSerializationApi +inline fun DatabaseReference.toObject( + serializer: KSerializer = serializer(), + crossinline errorHandler: (Throwable) -> T? = { throw it } +): Flow { + return callbackFlow { + val valueEventListener = object : ValueEventListener { + override fun onCancelled(error: DatabaseError) { + close(IllegalStateException(error.toException())) + } + + override fun onDataChange(dataSnapshot: DataSnapshot) { + val decodedAppData = + try { + dataSnapshot.toObjectWithSerializer(serializer) + } catch (ex: SerializationException) { + errorHandler(ex) + } + + if (decodedAppData != null) { + trySend(decodedAppData) + } + } + } + + this@toObject.addValueEventListener(valueEventListener) + + awaitClose { this@toObject.removeEventListener(valueEventListener) } + } +} +