-
-
Notifications
You must be signed in to change notification settings - Fork 166
improve native serialization and timestamp fixes #371
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Changes from all commits
aa8189f
3f28db6
c03dc3f
1fcb535
8c268f6
3bacb97
87a5862
41ee794
4d75507
d4365d6
4df30d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -453,6 +453,8 @@ external object firebase { | |
fun update(field: FieldPath, value: Any?, vararg moreFieldsAndValues: Any?): Promise<Unit> | ||
fun delete(): Promise<Unit> | ||
fun onSnapshot(next: (snapshot: DocumentSnapshot) -> Unit, error: (error: Error) -> Unit): ()->Unit | ||
|
||
fun isEqual(other: DocumentReference): Boolean | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. proper equality checks help a lot when writing tests in the applications using this SDK |
||
} | ||
|
||
open class WriteBatch { | ||
|
@@ -477,6 +479,8 @@ external object firebase { | |
companion object { | ||
val documentId: FieldPath | ||
} | ||
|
||
fun isEqual(other: FieldPath): Boolean | ||
} | ||
|
||
abstract class FieldValue { | ||
|
@@ -490,6 +494,13 @@ external object firebase { | |
|
||
fun isEqual(other: FieldValue): Boolean | ||
} | ||
|
||
open class GeoPoint(latitude: Double, longitude: Double) { | ||
val latitude: Double | ||
val longitude: Double | ||
|
||
fun isEqual(other: GeoPoint): Boolean | ||
} | ||
} | ||
|
||
fun remoteConfig(app: App? = definedExternally): remoteConfig.RemoteConfig | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package dev.gitlive.firebase.firestore | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
/** A class representing a platform specific Firebase GeoPoint. */ | ||
actual typealias NativeGeoPoint = com.google.firebase.firestore.GeoPoint | ||
|
||
/** A class representing a Firebase GeoPoint. */ | ||
@Serializable(with = GeoPointSerializer::class) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this approach is similar to a PR #312 |
||
actual class GeoPoint internal actual constructor(internal actual val nativeValue: NativeGeoPoint) { | ||
actual constructor(latitude: Double, longitude: Double) : this(NativeGeoPoint(latitude, longitude)) | ||
actual val latitude: Double = nativeValue.latitude | ||
actual val longitude: Double = nativeValue.longitude | ||
|
||
override fun equals(other: Any?): Boolean = | ||
this === other || other is GeoPoint && nativeValue == other.nativeValue | ||
override fun hashCode(): Int = nativeValue.hashCode() | ||
override fun toString(): String = nativeValue.toString() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package dev.gitlive.firebase.firestore | ||
|
||
import dev.gitlive.firebase.SpecialValueSerializer | ||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.SerializationException | ||
|
||
/** A class representing a platform specific Firebase GeoPoint. */ | ||
expect class NativeGeoPoint | ||
|
||
/** A class representing a Firebase GeoPoint. */ | ||
@Serializable(with = GeoPointSerializer::class) | ||
expect class GeoPoint internal constructor(nativeValue: NativeGeoPoint) { | ||
constructor(latitude: Double, longitude: Double) | ||
val latitude: Double | ||
val longitude: Double | ||
internal val nativeValue: NativeGeoPoint | ||
} | ||
|
||
/** Serializer for [GeoPoint]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */ | ||
object GeoPointSerializer : KSerializer<GeoPoint> by SpecialValueSerializer( | ||
serialName = "GeoPoint", | ||
toNativeValue = GeoPoint::nativeValue, | ||
fromNativeValue = { value -> | ||
when (value) { | ||
is NativeGeoPoint -> GeoPoint(value) | ||
else -> throw SerializationException("Cannot deserialize $value") | ||
} | ||
} | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,17 @@ | ||
package dev.gitlive.firebase.firestore | ||
|
||
import dev.gitlive.firebase.FirebaseDecoder | ||
import dev.gitlive.firebase.FirebaseEncoder | ||
import dev.gitlive.firebase.SpecialValueSerializer | ||
import dev.gitlive.firebase.firestore.DoubleAsTimestampSerializer.serverTimestamp | ||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.SerializationException | ||
import kotlin.time.Duration | ||
import kotlin.time.Duration.Companion.milliseconds | ||
import kotlin.time.Duration.Companion.nanoseconds | ||
import kotlin.time.Duration.Companion.seconds | ||
import kotlin.time.DurationUnit | ||
|
||
/** A class representing a platform specific Firebase Timestamp. */ | ||
expect class NativeTimestamp | ||
|
@@ -31,12 +38,17 @@ expect class Timestamp internal constructor(nativeValue: NativeTimestamp): BaseT | |
object ServerTimestamp: BaseTimestamp | ||
} | ||
|
||
fun Timestamp.Companion.fromMilliseconds(milliseconds: Double): Timestamp = | ||
Timestamp((milliseconds / 1000).toLong(), (milliseconds * 1000).toInt() % 1000000) | ||
fun Timestamp.toMilliseconds(): Double = seconds * 1000 + (nanoseconds / 1000.0) | ||
fun Timestamp.Companion.fromDuration(duration: Duration): Timestamp = | ||
duration.toComponents { seconds, nanoseconds -> | ||
Timestamp(seconds, nanoseconds) | ||
} | ||
fun Timestamp.toDuration(): Duration = seconds.seconds + nanoseconds.nanoseconds | ||
|
||
fun Timestamp.Companion.fromMilliseconds(milliseconds: Double): Timestamp = fromDuration(milliseconds.milliseconds) | ||
fun Timestamp.toMilliseconds(): Double = toDuration().toDouble(DurationUnit.MILLISECONDS) | ||
|
||
/** A serializer for [BaseTimestamp]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */ | ||
object BaseTimestampSerializer : SpecialValueSerializer<BaseTimestamp>( | ||
/** A serializer for [BaseTimestamp]. Must be used with [FirebaseEncoder]/[FirebaseDecoder]. */ | ||
object BaseTimestampSerializer : KSerializer<BaseTimestamp> by SpecialValueSerializer( | ||
serialName = "Timestamp", | ||
toNativeValue = { value -> | ||
when (value) { | ||
|
@@ -54,8 +66,8 @@ object BaseTimestampSerializer : SpecialValueSerializer<BaseTimestamp>( | |
} | ||
) | ||
|
||
/** A serializer for [Timestamp]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */ | ||
object TimestampSerializer : SpecialValueSerializer<Timestamp>( | ||
/** A serializer for [Timestamp]. Must be used with [FirebaseEncoder]/[FirebaseDecoder]. */ | ||
object TimestampSerializer : KSerializer<Timestamp> by SpecialValueSerializer( | ||
serialName = "Timestamp", | ||
toNativeValue = Timestamp::nativeValue, | ||
fromNativeValue = { value -> | ||
|
@@ -66,8 +78,8 @@ object TimestampSerializer : SpecialValueSerializer<Timestamp>( | |
} | ||
) | ||
|
||
/** A serializer for [Timestamp.ServerTimestamp]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */ | ||
object ServerTimestampSerializer : SpecialValueSerializer<Timestamp.ServerTimestamp>( | ||
/** A serializer for [Timestamp.ServerTimestamp]. Must be used with [FirebaseEncoder]/[FirebaseDecoder]. */ | ||
object ServerTimestampSerializer : KSerializer<Timestamp.ServerTimestamp> by SpecialValueSerializer( | ||
serialName = "Timestamp", | ||
toNativeValue = { FieldValue.serverTimestamp.nativeValue }, | ||
fromNativeValue = { value -> | ||
|
@@ -79,12 +91,12 @@ object ServerTimestampSerializer : SpecialValueSerializer<Timestamp.ServerTimest | |
) | ||
|
||
/** A serializer for a Double field which is stored as a Timestamp. */ | ||
object DoubleAsTimestampSerializer : SpecialValueSerializer<Double>( | ||
object DoubleAsTimestampSerializer : KSerializer<Double> by SpecialValueSerializer( | ||
serialName = "Timestamp", | ||
toNativeValue = { value -> | ||
when(value) { | ||
serverTimestamp -> FieldValue.serverTimestamp.nativeValue | ||
else -> Timestamp.fromMilliseconds(value) | ||
else -> Timestamp.fromMilliseconds(value).nativeValue | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a bug fix - the native value shall be extracted as in the line above |
||
} | ||
}, | ||
fromNativeValue = { value -> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it helped me a lot so why not to mention it for other devs