# ⚙️ Native Module ### Navigation - [🏡 Native modules made easy with Expo](/gYH9xz-oR2ai0Yih8if50w) - [👶 First Steps](/ANE6NSUlTSimTIrN-gMsBw) - [👉 ⚙️ Native Module](/mAIt0ctDTvSL5xV4uE9nWQ) - [📈 Passing data to view](/_gWWp8uoQwGkqKcEyfk8Tg) - [📚 View Props](/96IjlLNDRvydILdkbfaA5A) - [🔥 View Events](/PQWXYmxLRCebmLfx3Fh_gg) - [🏞️ View Functions](/DcjStCFdT6euzWqnJqCL6w) - [👷‍♂️ Classes and Shared Objects](/__42gVw8RqiIgfSbVseIvw) - [📊 Views and shared object](/IgHyIAHQQPCbeBD74Ri4BA) --- ### Task 1 Export from the `ChartModule` a sync `add` function that sums two integers. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Function("add") { a: Int, b: Int -> return@Function a + b } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Function("add") { (a: Int, b: Int) in return a + b } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/a06f2111ac03e5c79cacde9f277b8e9ec2745381) --- ### Task 2 Export from the `ChartModule` an async `addAsync` function that sums two integers. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin AsyncFunction("addAsync") { a: Int, b: Int -> return@AsyncFunction a + b } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift AsyncFunction("addAsync") { (a: Int, b: Int) in return a + b } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/d22d184f4ebcec4bc538d1d9819bd7b4ca0ad36c) --- ### Task 3 Export a sync function called `calculateAverage`. This function should receive an array of doubles and calculate their average value. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Function("calculateAverage") { data: List<Double> -> return@Function data.average() } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Function("calculateAverage") { (data: [Double]) in return data.reduce(0.0, +) / Double(data.count) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/d008477527a65d50e0ca1a4c1f25bead7a6043a8) --- ### Task 4 Export an asynchronous function named `generateDataAsync`, which takes in a single integer - `size` and outputs an array containing numbers ranging from `0` to `size-1`. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin AsyncFunction("generateDataAsync") { size: Int -> return@AsyncFunction IntArray(size) { it } } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift AsyncFunction("generateDataAsync") { (size: Int) -> [Int] in var result: [Int] = [] for i in 0..<size { result.append(i) } return result } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/0cc15b384ce2232a29591ecdf5aef647fe9b2fa2) --- ### Task 5 Adjust the previous example to throw a custom coded exception if the size given is less than `0`. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin class InvalidSizeException : CodedException( message = "Provided size was invalid" ) ``` ```kotlin AsyncFunction("generateDataAsync") { size: Int -> if (size < 0) { throw InvalidSizeException() } return@AsyncFunction IntArray(size) { it } } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift internal class InvalidSizeException : Exception { override var reason: String { "Provided size was invalid" } } ``` ```swift AsyncFunction("generateDataAsync") { (size: Int) -> [Int] in if size < 0 { throw InvalidSizeException() } var result: [Int] = [] for i in 0..<size { result.append(i) } return result } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/03b488e7fe77f9a97620977c9bd6632433b8a966) --- ### Task 6 Export a `VERY_IMPORTANT_CONSTANT` constant equal to `2`. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Constants( "VERY_IMPORTANT_CONSTANT" to 2 ) ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Constants([ "VERY_IMPORTANT_CONSTANT": 2 ]) ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/728e02ec297e2d08ace1797243537510688823c4) --- ### Task 7 Export a synchronous `typeOf` function that returns type of the provided argument. > Use `JavaScriptValue` class as a function parameter. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Function("typeOf") { value: JavaScriptValue -> return@Function value.kind() } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Function("typeOf") { (value: JavaScriptValue) in return value.kind.rawValue } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/48eb3d10656a87041e62ac68798230457f62fb3d) --- ### Task 8 Export a synchronous `modifyJSObject` function that will alter a provided `JavaScriptObject` by adding a new property called `expo` with the value of `is awesome`. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Function("modifyJSObject") { jsObject: JavaScriptObject -> jsObject.setProperty("expo", "is awesome") } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Function("modifyJSObject") { (jsObject: JavaScriptObject) in jsObject.setProperty("expo", value: "is awesome") } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/b20b22677b3b4843537496cd77dc8f24db05b0dd) --- ### Task 9 Export a sync `callJSFunction` function that operates synchronously. This function should receive a `JavaScriptFunction<Double>` and use it to perform calculations with `100` and `200` as arguments. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Function("callJSFunction") { jsFunction: JavaScriptFunction<Double> -> return@Function jsFunction(100, 200) } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Function("callJSFunction") { (jsFunction: JavaScriptFunction<Double>) in return try jsFunction.call(100, 200) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/21cf6d1cb74a7560b3e99388f19828c87dfe808f) --- ### Task 10 Export an async `objectSummary` function that summaries the provided object by calling `toString` (in Kotlin) or `description` (in Swift). > Try using `Map<String, Any>`/`[String: Any]` instead of the `JavaScriptObject` class. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin AsyncFunction("objectSummary") { jsObject: Map<String, Any> -> return@AsyncFunction jsObject.toString() } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift AsyncFunction("objectSummary") { (jsObject: [String: Any]) in return jsObject.description } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/ec5e12450590ce35b40db66361907659df32f647) --- ### Task 11 Export a module's event named `onNewData` along with its corresponding sync function (`sendOnNewDataEvent`) that will trigger it. The event payload should be equal to `{ value: 123 }`. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin Events("onNewData") AsyncFunction("sendOnNewDataEvent") { sendEvent("onNewData", mapOf( "value" to 123, )) } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift Events("onNewData") AsyncFunction("sendOnNewDataEvent") { sendEvent("onNewData", [ "value": 123, ]) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/282045b4e03907744668bf8d4c7942163bb42ad1) --- ### Task 12 Create a custom `Record` called `Point` representing an `x` and `y` coordinates. Then export a sync function `calculateDistance` which will calculate an distance between two points. > $$ distance = \sqrt{(p1.y - p2.y)^2 + (p1.x - p2.x)^2} $$ :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin data class Point( @Field @Required val x: Double, @Field @Required val y: Double ) : Record ``` ```kotlin Function("calculateDistance") { p1: Point, p2: Point -> sqrt((p1.y - p2.y) * (p1.y - p2.y) + (p1.x - p2.x) * (p1.x - p2.x)) } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift internal struct Point: Record { @Field var x: Double @Field var y: Double } ``` ```swift Function("calculateDistance") { (p1: Point, p2: Point) in return sqrt((p1.y - p2.y) * (p1.y - p2.y) + (p1.x - p2.x) * (p1.x - p2.x)) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/48fec3f15c32e8f7060b3b26222666573801e9c7) --- ### Task 13 Create a property that includes a getter and setter to store a Double value. The setter should automatically square any value that is provided. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/ChartsModule.kt` ```kotlin var x = -1.0 // ... Property("x") .get { x } .set { newValue: Double -> x = newValue * newValue } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/ChartsModule.swift` ```swift var x = -1.0 // ... Property("x") .get { self.x } .set { (newValue: Double) in self.x = newValue * newValue } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/e333a71de151bcbffb672e3d7318b0724249b589) --- ### [📈 Passing data to view](/_gWWp8uoQwGkqKcEyfk8Tg)