Skip to content

Commit f86a814

Browse files
rdlabolucasfernog
andauthored
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>
1 parent fb6bf31 commit f86a814

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

.changes/mobile-plugin-get-args.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri": patch:enhance
3+
---
4+
5+
Added `getArgs` and `getRawArgs` methods to the plugin `Invoke` class (Kotlin and Swift),
6+
which lets you parse the arguments manually instead of through the `parseArgs` method.

core/tauri/mobile/android/src/main/java/app/tauri/plugin/Invoke.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ class Invoke(
1717
private val argsJson: String,
1818
private val jsonMapper: ObjectMapper
1919
) {
20+
fun getRawArgs(): String {
21+
return argsJson
22+
}
23+
24+
fun getArgs(): JSObject {
25+
return JSObject(argsJson)
26+
}
27+
2028
fun<T> parseArgs(cls: Class<T>): T {
2129
return jsonMapper.readValue(argsJson, cls)
2230
}

core/tauri/mobile/ios-api/Sources/Tauri/Invoke.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ import UIKit
2626
self.sendChannelData = sendChannelData
2727
}
2828

29+
public func getRawArgs() -> String {
30+
return self.data
31+
}
32+
33+
public func getArgs() throws -> JSObject {
34+
let jsonData = self.data.data(using: .utf8)!
35+
let data = try JSONSerialization.jsonObject(with: jsonData, options: [])
36+
return JSTypes.coerceDictionaryToJSObject(
37+
(data as! NSDictionary), formattingDatesAsStrings: true)!
38+
}
39+
2940
public func parseArgs<T: Decodable>(_ type: T.Type) throws -> T {
3041
let jsonData = self.data.data(using: .utf8)!
3142
let decoder = JSONDecoder()

core/tauri/mobile/ios-api/Sources/Tauri/JSTypes.swift

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,104 @@ extension Dictionary: JSValue where Key == String, Value == JSValue {}
2020
// convenience aliases
2121
public typealias JSObject = [String: JSValue]
2222
public typealias JSArray = [JSValue]
23+
24+
extension Dictionary where Key == String, Value == JSValue {
25+
public func getValue(_ key: String) -> JSValue? {
26+
return self[key]
27+
}
28+
29+
public func getString(_ key: String) -> String? {
30+
return self[key] as? String
31+
}
32+
33+
public func getBool(_ key: String) -> Bool? {
34+
return self[key] as? Bool
35+
}
36+
37+
public func getInt(_ key: String) -> Int? {
38+
return self[key] as? Int
39+
}
40+
41+
public func getFloat(_ key: String) -> Float? {
42+
if let floatValue = self[key] as? Float {
43+
return floatValue
44+
} else if let doubleValue = self[key] as? Double {
45+
return Float(doubleValue)
46+
}
47+
return nil
48+
}
49+
50+
public func getDouble(_ key: String) -> Double? {
51+
return self[key] as? Double
52+
}
53+
54+
public func getArray(_ key: String) -> JSArray? {
55+
return self[key] as? JSArray
56+
}
57+
58+
public func getObject(_ key: String) -> JSObject? {
59+
return self[key] as? JSObject
60+
}
61+
}
62+
63+
/*
64+
Simply casting objects from foundation class clusters (such as __NSArrayM)
65+
doesn't work with the JSValue protocol and will always fail. So we need to
66+
recursively and explicitly convert each value in the dictionary.
67+
*/
68+
public enum JSTypes {}
69+
extension JSTypes {
70+
public static func coerceDictionaryToJSObject(
71+
_ dictionary: NSDictionary?, formattingDatesAsStrings: Bool = false
72+
) -> JSObject? {
73+
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
74+
}
75+
76+
public static func coerceDictionaryToJSObject(
77+
_ dictionary: [AnyHashable: Any]?, formattingDatesAsStrings: Bool = false
78+
) -> JSObject? {
79+
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
80+
}
81+
}
82+
83+
private let dateStringFormatter = ISO8601DateFormatter()
84+
85+
// We need a large switch statement because we have a lot of types.
86+
// swiftlint:disable:next cyclomatic_complexity
87+
private func coerceToJSValue(_ value: Any?, formattingDates: Bool) -> JSValue? {
88+
guard let value = value else {
89+
return nil
90+
}
91+
switch value {
92+
case let stringValue as String:
93+
return stringValue
94+
case let numberValue as NSNumber:
95+
return numberValue
96+
case let boolValue as Bool:
97+
return boolValue
98+
case let intValue as Int:
99+
return intValue
100+
case let floatValue as Float:
101+
return floatValue
102+
case let doubleValue as Double:
103+
return doubleValue
104+
case let dateValue as Date:
105+
if formattingDates {
106+
return dateStringFormatter.string(from: dateValue)
107+
}
108+
return dateValue
109+
case let nullValue as NSNull:
110+
return nullValue
111+
case let arrayValue as NSArray:
112+
return arrayValue.compactMap { coerceToJSValue($0, formattingDates: formattingDates) }
113+
case let dictionaryValue as NSDictionary:
114+
let keys = dictionaryValue.allKeys.compactMap { $0 as? String }
115+
var result: JSObject = [:]
116+
for key in keys {
117+
result[key] = coerceToJSValue(dictionaryValue[key], formattingDates: formattingDates)
118+
}
119+
return result
120+
default:
121+
return nil
122+
}
123+
}

0 commit comments

Comments
 (0)