Skip to content

Commit

Permalink
feat(core): add plugin methods getArgs and getRawArgs for iOS and And…
Browse files Browse the repository at this point in the history
…roid (#10761)

* feat(api): add method getArgsData

* chore

* return JSObject instead

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
  • Loading branch information
rdlabo and lucasfernog authored Aug 26, 2024
1 parent fb6bf31 commit f86a814
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .changes/mobile-plugin-get-args.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
11 changes: 11 additions & 0 deletions core/tauri/mobile/ios-api/Sources/Tauri/Invoke.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
101 changes: 101 additions & 0 deletions core/tauri/mobile/ios-api/Sources/Tauri/JSTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

0 comments on commit f86a814

Please sign in to comment.