feat(core): add plugin methods getArgs and getRawArgs for iOS and Android (#10761)

* feat(api): add method getArgsData

* chore

* return JSObject instead

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Masahiko Sakakibara 2024-08-27 04:55:51 +09:00 committed by GitHub
parent fb6bf31425
commit f86a8146ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,6 @@
---
"tauri": patch:enhance
---
Added `getArgs` and `getRawArgs` methods to the plugin `Invoke` class (Kotlin and Swift),
which lets you parse the arguments manually instead of through the `parseArgs` method.

View File

@ -17,6 +17,14 @@ class Invoke(
private val argsJson: String,
private val jsonMapper: ObjectMapper
) {
fun getRawArgs(): String {
return argsJson
}
fun getArgs(): JSObject {
return JSObject(argsJson)
}
fun<T> parseArgs(cls: Class<T>): T {
return jsonMapper.readValue(argsJson, cls)
}

View File

@ -26,6 +26,17 @@ import UIKit
self.sendChannelData = sendChannelData
}
public func getRawArgs() -> String {
return self.data
}
public func getArgs() throws -> JSObject {
let jsonData = self.data.data(using: .utf8)!
let data = try JSONSerialization.jsonObject(with: jsonData, options: [])
return JSTypes.coerceDictionaryToJSObject(
(data as! NSDictionary), formattingDatesAsStrings: true)!
}
public func parseArgs<T: Decodable>(_ type: T.Type) throws -> T {
let jsonData = self.data.data(using: .utf8)!
let decoder = JSONDecoder()

View File

@ -20,3 +20,104 @@ extension Dictionary: JSValue where Key == String, Value == JSValue {}
// convenience aliases
public typealias JSObject = [String: JSValue]
public typealias JSArray = [JSValue]
extension Dictionary where Key == String, Value == JSValue {
public func getValue(_ key: String) -> JSValue? {
return self[key]
}
public func getString(_ key: String) -> String? {
return self[key] as? String
}
public func getBool(_ key: String) -> Bool? {
return self[key] as? Bool
}
public func getInt(_ key: String) -> Int? {
return self[key] as? Int
}
public func getFloat(_ key: String) -> Float? {
if let floatValue = self[key] as? Float {
return floatValue
} else if let doubleValue = self[key] as? Double {
return Float(doubleValue)
}
return nil
}
public func getDouble(_ key: String) -> Double? {
return self[key] as? Double
}
public func getArray(_ key: String) -> JSArray? {
return self[key] as? JSArray
}
public func getObject(_ key: String) -> JSObject? {
return self[key] as? JSObject
}
}
/*
Simply casting objects from foundation class clusters (such as __NSArrayM)
doesn't work with the JSValue protocol and will always fail. So we need to
recursively and explicitly convert each value in the dictionary.
*/
public enum JSTypes {}
extension JSTypes {
public static func coerceDictionaryToJSObject(
_ dictionary: NSDictionary?, formattingDatesAsStrings: Bool = false
) -> JSObject? {
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
}
public static func coerceDictionaryToJSObject(
_ dictionary: [AnyHashable: Any]?, formattingDatesAsStrings: Bool = false
) -> JSObject? {
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
}
}
private let dateStringFormatter = ISO8601DateFormatter()
// We need a large switch statement because we have a lot of types.
// swiftlint:disable:next cyclomatic_complexity
private func coerceToJSValue(_ value: Any?, formattingDates: Bool) -> JSValue? {
guard let value = value else {
return nil
}
switch value {
case let stringValue as String:
return stringValue
case let numberValue as NSNumber:
return numberValue
case let boolValue as Bool:
return boolValue
case let intValue as Int:
return intValue
case let floatValue as Float:
return floatValue
case let doubleValue as Double:
return doubleValue
case let dateValue as Date:
if formattingDates {
return dateStringFormatter.string(from: dateValue)
}
return dateValue
case let nullValue as NSNull:
return nullValue
case let arrayValue as NSArray:
return arrayValue.compactMap { coerceToJSValue($0, formattingDates: formattingDates) }
case let dictionaryValue as NSDictionary:
let keys = dictionaryValue.allKeys.compactMap { $0 as? String }
var result: JSObject = [:]
for key in keys {
result[key] = coerceToJSValue(dictionaryValue[key], formattingDates: formattingDates)
}
return result
default:
return nil
}
}