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
2 changes: 1 addition & 1 deletion examples/react-native/.expo/prebuild/cached-packages.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"dependencies": "286a2ddcc75a8a026fb359574760756082f0bdf3",
"dependencies": "e7ed11fc2a9fc81273e0998c2edad995bde6dcf0",
"devDependencies": "c6400748491c6dfba271791c0857744f3949943d"
}
41,326 changes: 12,451 additions & 28,875 deletions examples/react-native/.expo/xcodebuild.log

Large diffs are not rendered by default.

89 changes: 78 additions & 11 deletions examples/react-native/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ A minimal React Native example demonstrating how to use the Controller.c library
- ✅ React Native New Architecture (TurboModules/JSI)
- ✅ Simple session account example
- ✅ Key generation and felt validation
- ✅ iOS and Android support

## Prerequisites

- Node.js >= 20
- pnpm
- Xcode (for iOS)
- CocoaPods
- CocoaPods (for iOS)
- Android Studio with NDK (for Android)
- Rust with Android targets (for building Android native libs)

## Setup
## Quick Start

1. Install dependencies:
```bash
Expand All @@ -28,11 +31,52 @@ pnpm install
pnpm exec expo prebuild
```

3. (iOS only) Install CocoaPods:
3. Run:
```bash
cd ios && pod install && cd ..
# iOS
pnpm run ios

# Android
pnpm run android
```

> **Note:** Pre-built native libraries are included in the repository for both iOS (`Controller.xcframework`) and Android (`jniLibs/*.so`).

## Rebuilding Android Native Libraries (Optional)

If you need to rebuild the Android native libraries (e.g., after Rust code changes):

### Prerequisites

1. Install `cargo-ndk`:
```bash
cargo install cargo-ndk
```

2. Install Android targets:
```bash
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
```

3. Set up Android NDK (Android Studio > SDK Manager > SDK Tools > NDK):
```bash
export ANDROID_NDK_HOME=$HOME/Library/Android/sdk/ndk/<version>
# or
export NDK_HOME=$HOME/Library/Android/sdk/ndk/<version>
```

### Build

```bash
./scripts/build_android.sh
```

This will build `libcontroller_uniffi.so` for all Android ABIs and place them in:
- `modules/controller/android/src/main/jniLibs/arm64-v8a/`
- `modules/controller/android/src/main/jniLibs/armeabi-v7a/`
- `modules/controller/android/src/main/jniLibs/x86/`
- `modules/controller/android/src/main/jniLibs/x86_64/`

## Running

### iOS
Expand Down Expand Up @@ -60,36 +104,59 @@ react-native/
├── modules/
│ └── controller/ # Controller native module
│ ├── ios/ # iOS native code (Obj-C++)
│ ├── cpp/ # C++ bindings
│ ├── android/ # Android native code (Kotlin)
│ ├── cpp/ # Shared C++ bindings
│ ├── src/ # JS/TS module code
│ ├── Controller.podspec
│ ├── Controller.podspec # iOS CocoaPods config
│ ├── Controller.xcframework/ # iOS pre-built libs
│ └── package.json
├── ios/ # iOS native project
├── android/ # Android native project
├── package.json
└── app.json # Expo config
```

## How It Works

### iOS
1. The native Controller module is built as a CocoaPod
2. It uses TurboModules (React Native New Architecture) for performance
3. The Rust FFI is exposed via uniffi-bindgen-react-native
4. JSI (JavaScript Interface) provides direct JS <-> Native communication
2. Pre-built static libraries are in `Controller.xcframework`
3. TurboModules via `ios/Controller.mm`

### Android
1. The native Controller module is built via Gradle/CMake
2. Pre-built shared libraries are in `android/src/main/jniLibs/`
3. TurboModules via Kotlin (`ControllerModule.kt`)

### Both Platforms
1. Uses TurboModules (React Native New Architecture) for performance
2. The Rust FFI is exposed via uniffi-bindgen-react-native
3. JSI (JavaScript Interface) provides direct JS <-> Native communication

## Troubleshooting

### Clean Build
### iOS: Clean Build
```bash
# Clean everything
pnpm prebuild:clean
cd ios && rm -rf Pods Podfile.lock && pod install && cd ..
```

### Clean Xcode Cache
### iOS: Clean Xcode Cache
```bash
rm -rf ~/Library/Developer/Xcode/DerivedData
```

### Android: Clean Build
```bash
cd android && ./gradlew clean && cd ..
```

### Android: Clear Gradle Cache
```bash
rm -rf ~/.gradle/caches
```

## Example Code

See `app/index.tsx` for a simple example that demonstrates:
Expand Down
3 changes: 3 additions & 0 deletions examples/react-native/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ android {
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")

// Controller native module
implementation project(':controller-native')

def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.facebook.react.ReactHost
import com.facebook.react.common.ReleaseLevel
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
import com.facebook.react.defaults.DefaultReactNativeHost
import com.cartridge.controller.ControllerPackage

import expo.modules.ApplicationLifecycleDispatcher
import expo.modules.ReactNativeHostWrapper
Expand All @@ -21,11 +22,11 @@ class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper(
this,
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
}
override fun getPackages(): List<ReactPackage> {
val packages = PackageList(this).packages.toMutableList()
packages.add(ControllerPackage())
return packages
}

override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"

Expand Down
3 changes: 3 additions & 0 deletions examples/react-native/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ rootProject.name = 'Controller Example'
expoAutolinking.useExpoVersionCatalog()

include ':app'
include ':controller-native'
project(':controller-native').projectDir = new File(rootProject.projectDir, '../modules/controller/android')

includeBuild(expoAutolinking.reactNativeGradlePlugin)
Loading