Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions Sources/SkipFirebaseCore/SkipFirebaseCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,89 @@ public final class FirebaseOptions {
}
}

// https://firebase.google.com/docs/reference/swift/firebasefirestore/api/reference/Classes/Timestamp
// https://firebase.google.com/docs/reference/android/com/google/firebase/Timestamp

public class Timestamp: Hashable, KotlinConverting<com.google.firebase.Timestamp> {
public let timestamp: com.google.firebase.Timestamp

public init(timestamp: com.google.firebase.Timestamp) {
self.timestamp = timestamp
}

public init(date: Date) {
self.timestamp = com.google.firebase.Timestamp(date.kotlin())
}

public init(seconds: Int64, nanoseconds: Int32) {
self.timestamp = com.google.firebase.Timestamp(seconds, nanoseconds)
}

// SKIP @nooverride
public override func kotlin(nocopy: Bool = false) -> com.google.firebase.Timestamp {
timestamp
}

public var description: String {
timestamp.toString()
}

public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.timestamp == rhs.timestamp
}

public func hash(into hasher: inout Hasher) {
hasher.combine(timestamp.hashCode())
}

public func dateValue() -> Date {
Date(platformValue: timestamp.toDate())
}

public func toDate() -> Date {
dateValue()
}

public var seconds: Int64 {
timestamp.seconds
}

public var nanoseconds: Int32 {
timestamp.nanoseconds
}
}

// MARK: - Kotlin to Swift type conversion helpers

public func deepSwift(value: Any) -> Any {
if let str = value as? String {
return str // needed to not be treated as a Collection
} else if let ts = value as? com.google.firebase.Timestamp {
return Timestamp(timestamp: ts)
} else if let map = value as? kotlin.collections.Map<Any, Any> {
return deepSwift(map: map)
} else if let collection = value as? kotlin.collections.Collection<Any> {
return deepSwift(collection: collection)
} else {
return value
}
}

public func deepSwift<T>(map: kotlin.collections.Map<T, Any>) -> Dictionary<T, Any> {
var dict = Dictionary<T, Any>()
for (key, value) in map {
dict[key] = deepSwift(value: value)
}
return dict
}

public func deepSwift(collection: kotlin.collections.Collection<Any>) -> Array<Any> {
var array = Array<Any>()
for value in collection {
array.append(deepSwift(value: value))
}
return array
}

#endif
#endif
4 changes: 4 additions & 0 deletions Sources/SkipFirebaseCrashlytics/SkipFirebaseCrashlytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public final class Crashlytics {
// public static func crashlytics(app: FirebaseApp) -> Crashlytics {
// Crashlytics(crashlytics: com.google.firebase.crashlytics.FirebaseCrashlytics.getInstance(app.app))
// }

public func log(_ message: String) {
_crashlytics.log(message)
}
}
#endif
#endif
83 changes: 2 additions & 81 deletions Sources/SkipFirebaseFirestore/SkipFirebaseFirestore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Foundation
import SkipFirebaseCore
import kotlinx.coroutines.tasks.await

public typealias Timestamp = SkipFirebaseCore.Timestamp

public final class Firestore: KotlinConverting<com.google.firebase.firestore.FirebaseFirestore> {
public let store: com.google.firebase.firestore.FirebaseFirestore

Expand Down Expand Up @@ -957,55 +959,6 @@ public class DocumentReference: KotlinConverting<com.google.firebase.firestore.D
}
}

public class Timestamp: Hashable, KotlinConverting<com.google.firebase.Timestamp> {
public let timestamp: com.google.firebase.Timestamp

public init(timestamp: com.google.firebase.Timestamp) {
self.timestamp = timestamp
}

public init(date: Date) {
self.timestamp = com.google.firebase.Timestamp(date.kotlin())
}

public init(seconds: Int64, nanoseconds: Int32) {
self.timestamp = com.google.firebase.Timestamp(seconds, nanoseconds)
}

// SKIP @nooverride
public override func kotlin(nocopy: Bool = false) -> com.google.firebase.Timestamp {
timestamp
}

public var description: String {
timestamp.toString()
}

public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.timestamp == rhs.timestamp
}

public func hash(into hasher: inout Hasher) {
hasher.combine(timestamp.hashCode())
}

public func dateValue() -> Date {
Date(platformValue: timestamp.toDate())
}

public func toDate() -> Date {
dateValue()
}

public var seconds: Int64 {
timestamp.seconds
}

public var nanoseconds: Int32 {
timestamp.nanoseconds
}
}

public class WriteBatch {
public let batch: com.google.firebase.firestore.WriteBatch

Expand Down Expand Up @@ -1102,37 +1055,5 @@ fileprivate func asNSError(firestoreException: com.google.firebase.firestore.Fir
return NSError(domain: FirestoreErrorDomain, code: firestoreException.code.value(), userInfo: userInfo)
}

// MARK: Utilies for converting between Swift and Kotlin types

fileprivate func deepSwift(value: Any) -> Any {
if let str = value as? String {
return str // needed to not be treated as a Collection
} else if let ts = value as? com.google.firebase.Timestamp {
return Timestamp(timestamp: ts)
} else if let map = value as? kotlin.collections.Map<Any, Any> {
return deepSwift(map: map)
} else if let collection = value as? kotlin.collections.Collection<Any> {
return deepSwift(collection: collection)
} else {
return value
}
}

fileprivate func deepSwift<T>(map: kotlin.collections.Map<T, Any>) -> Dictionary<T, Any> {
var dict = Dictionary<T, Any>()
for (key, value) in map {
dict[key] = deepSwift(value: value)
}
return dict
}

fileprivate func deepSwift(collection: kotlin.collections.Collection<Any>) -> Array<Any> {
var array = Array<Any>()
for value in collection {
array.append(deepSwift(value: value))
}
return array
}

#endif
#endif
18 changes: 14 additions & 4 deletions Sources/SkipFirebaseFunctions/SkipFirebaseFunctions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Foundation
import SkipFirebaseCore
import kotlinx.coroutines.tasks.await

public typealias Timestamp = SkipFirebaseCore.Timestamp

// https://firebase.google.com/docs/reference/swift/firebasefunctions/api/reference/Classes/Functions
// https://firebase.google.com/docs/reference/android/com/google/firebase/functions/FirebaseFunctions

Expand Down Expand Up @@ -86,11 +88,19 @@ public class HTTPSCallableResult: KotlinConverting<com.google.firebase.functions
}

public var data: Any {
if let data = platformValue.getData() {
return data
} else {
assertionFailure("com.google.firebase.functions.HttpsCallableResult returned nil and the Swift API returns a non-nil Any")
// WORKAROUND: Access getData() result through a local variable first
// to avoid potential crashes in Skip's property access transpilation
let rawData: Any? = platformValue.getData()
return rawData ?? [String: Any]()
}

// Alternative method-based access that properly converts Kotlin types to Swift
public func getDataSafe() -> Any {
guard let rawData = platformValue.getData() else {
return [String: Any]()
}
// Convert Kotlin collections to Swift types (same approach as Firestore)
return deepSwift(value: rawData)
}
}

Expand Down