diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 67a28e164..929e17e9f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -37,6 +37,30 @@ jobs:
- name: Perform typechecks
run: pnpm typecheck
+ eslint:
+ name: ESLint
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v2.2.2
+ with:
+ version: 7.x.x
+
+ - name: Install Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ cache: 'pnpm'
+
+ - name: Install pnpm dependencies
+ run: pnpm i --frozen-lockfile
+
+ - name: Perform linting
+ run: pnpm lint
+
rustfmt:
name: rustfmt
runs-on: ubuntu-latest
diff --git a/Cargo.lock b/Cargo.lock
index 81db9b416..af40c8c2f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5477,15 +5477,30 @@ dependencies = [
"webp",
]
+[[package]]
+name = "sd-core-android"
+version = "0.1.0"
+dependencies = [
+ "jni",
+ "sd-core-mobile",
+ "tracing",
+]
+
+[[package]]
+name = "sd-core-ios"
+version = "0.1.0"
+dependencies = [
+ "objc",
+ "objc-foundation",
+ "objc_id",
+ "sd-core-mobile",
+]
+
[[package]]
name = "sd-core-mobile"
version = "0.1.0"
dependencies = [
"futures",
- "jni",
- "objc",
- "objc-foundation",
- "objc_id",
"once_cell",
"openssl",
"openssl-sys",
diff --git a/Cargo.toml b/Cargo.toml
index 698c9a4d0..edd9b02ce 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,7 +7,7 @@ members = [
# "crates/p2p/tunnel/utils",
"apps/cli",
"apps/desktop/src-tauri",
- "apps/mobile/rust",
+ "apps/mobile/rust/*",
"apps/server",
]
diff --git a/apps/desktop/src-tauri/native/macos/Package.resolved b/apps/desktop/src-tauri/native/macos/Package.resolved
index 3c5275e65..2fd3cde38 100644
--- a/apps/desktop/src-tauri/native/macos/Package.resolved
+++ b/apps/desktop/src-tauri/native/macos/Package.resolved
@@ -6,7 +6,7 @@
"repositoryURL": "https://github.com/brendonovich/swift-rs",
"state": {
"branch": null,
- "revision": "833e29ba333f1dfe303eaa21de78c4f8c5a3f2ff",
+ "revision": "c3003bc0c28a6742d3da341b61887d8e072fda0a",
"version": null
}
}
diff --git a/apps/desktop/src-tauri/native/macos/Package.swift b/apps/desktop/src-tauri/native/macos/Package.swift
index 2ea0a6845..c98047dfe 100644
--- a/apps/desktop/src-tauri/native/macos/Package.swift
+++ b/apps/desktop/src-tauri/native/macos/Package.swift
@@ -18,7 +18,7 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
- .package(url: "https://github.com/brendonovich/swift-rs", revision: "833e29ba333f1dfe303eaa21de78c4f8c5a3f2ff"),
+ .package(url: "https://github.com/brendonovich/swift-rs", revision: "c3003bc0c28a6742d3da341b61887d8e072fda0a"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs
index 5de1b570c..24e8395df 100644
--- a/apps/desktop/src-tauri/src/main.rs
+++ b/apps/desktop/src-tauri/src/main.rs
@@ -17,8 +17,10 @@ use tauri::{
use tokio::task::block_in_place;
use tokio::time::sleep;
use tracing::{debug, error};
+
#[cfg(target_os = "macos")]
mod macos;
+
mod menu;
#[tauri::command(async)]
diff --git a/apps/landing/.eslintrc.js b/apps/landing/.eslintrc.js
index 01aae4aa3..615ceae2b 100644
--- a/apps/landing/.eslintrc.js
+++ b/apps/landing/.eslintrc.js
@@ -1,8 +1,7 @@
module.exports = {
- ...require('@sd/config/eslint-react.js'),
+ extends: [require.resolve('@sd/config/eslint/web.js')],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
- },
- ignorePatterns: ['**/*.js', '**/*.json', 'node_modules', 'public', 'dist', 'vite.config.ts']
+ }
};
diff --git a/apps/landing/package.json b/apps/landing/package.json
index 7a472f641..39b0b7c97 100644
--- a/apps/landing/package.json
+++ b/apps/landing/package.json
@@ -7,7 +7,7 @@
"build": "vite build",
"server": "ts-node ./server",
"server:prod": "cross-env NODE_ENV=production ts-node ./server",
- "lint": "eslint src/**/*.{ts,tsx} && tsc --noEmit",
+ "lint": "eslint src",
"typecheck": "tsc -b"
},
"dependencies": {
diff --git a/apps/landing/public/app-ui-explorer.webp b/apps/landing/public/app-ui-explorer.webp
new file mode 100644
index 000000000..4f67d894e
Binary files /dev/null and b/apps/landing/public/app-ui-explorer.webp differ
diff --git a/apps/landing/public/database-table-plus.webp b/apps/landing/public/database-table-plus.webp
new file mode 100644
index 000000000..b89a5b1e2
Binary files /dev/null and b/apps/landing/public/database-table-plus.webp differ
diff --git a/apps/landing/public/schema.webp b/apps/landing/public/schema.webp
new file mode 100644
index 000000000..b4be52706
Binary files /dev/null and b/apps/landing/public/schema.webp differ
diff --git a/apps/landing/src/components/Footer.tsx b/apps/landing/src/components/Footer.tsx
index 8c01ee31a..6dfb709d2 100644
--- a/apps/landing/src/components/Footer.tsx
+++ b/apps/landing/src/components/Footer.tsx
@@ -61,7 +61,7 @@ export function Footer() {
Team
FAQ
Careers
- Changelog
+ Changelog
Blog
@@ -98,11 +98,11 @@ export function Footer() {
License
-
diff --git a/apps/mobile/.eslintrc.js b/apps/mobile/.eslintrc.js
index 11305df15..cd041390b 100644
--- a/apps/mobile/.eslintrc.js
+++ b/apps/mobile/.eslintrc.js
@@ -1,5 +1,5 @@
module.exports = {
- ...require('@sd/config/eslint-react-native.js'),
+ extends: [require.resolve('@sd/config/eslint/reactNative.js')],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle
index 1433bd53c..37a827676 100644
--- a/apps/mobile/android/app/build.gradle
+++ b/apps/mobile/android/app/build.gradle
@@ -6,8 +6,8 @@ import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
cargo {
- module = "../../rust"
- libname = "sd_core_mobile"
+ module = "../../rust/android"
+ libname = "sd_core_android"
pythonCommand = 'python3'
profile = 'release'
targets = ["arm", "arm64", "x86", "x86_64"]
diff --git a/apps/mobile/android/app/src/main/java/com/spacedrive/app/SDCore.java b/apps/mobile/android/app/src/main/java/com/spacedrive/app/SDCore.java
index d6c9f011d..9be5d33eb 100644
--- a/apps/mobile/android/app/src/main/java/com/spacedrive/app/SDCore.java
+++ b/apps/mobile/android/app/src/main/java/com/spacedrive/app/SDCore.java
@@ -28,7 +28,7 @@ public class SDCore extends ReactContextBaseJavaModule {
}
static {
- System.loadLibrary("sd_core_mobile");
+ System.loadLibrary("sd_core_android");
}
// is exposed by Rust and is used to register the subscription
@@ -78,4 +78,4 @@ public class SDCore extends ReactContextBaseJavaModule {
.emit("SDCoreEvent", body);
}
}
-}
\ No newline at end of file
+}
diff --git a/apps/mobile/ios/Podfile.lock b/apps/mobile/ios/Podfile.lock
index 478c112c2..cf0e6258b 100644
--- a/apps/mobile/ios/Podfile.lock
+++ b/apps/mobile/ios/Podfile.lock
@@ -12,11 +12,11 @@ PODS:
- EXMediaLibrary (15.0.0):
- ExpoModulesCore
- React-Core
- - Expo (47.0.10):
+ - Expo (47.0.13):
- ExpoModulesCore
- ExpoKeepAwake (11.0.1):
- ExpoModulesCore
- - ExpoModulesCore (1.1.0):
+ - ExpoModulesCore (1.1.1):
- React-Core
- ReactCommon/turbomodule/core
- EXSplashScreen (0.17.5):
@@ -564,9 +564,9 @@ SPEC CHECKSUMS:
EXFileSystem: 60602b6eefa6873f97172c684b7537c9760b50d6
EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80
EXMediaLibrary: b1c4f78878e45f6a359aff3a059e1660c41b73ab
- Expo: a694d89d2461fdfc6b977bf489bf7d341ed03bca
+ Expo: b9fa98bf260992312ee3c424400819fb9beadafe
ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318
- ExpoModulesCore: fc7e27657bc33878e1451c30cef481020518f2e1
+ ExpoModulesCore: 65ae09e2b2d3dd8ece30a5acc83c569968125ab0
EXSplashScreen: 3e989924f61a8dd07ee4ea584c6ba14be9b51949
FBLazyVector: affa4ba1bfdaac110a789192f4d452b053a86624
FBReactNativeSpec: fe8b5f1429cfe83a8d72dc8ed61dc7704cac8745
diff --git a/apps/mobile/ios/Spacedrive.xcodeproj/project.pbxproj b/apps/mobile/ios/Spacedrive.xcodeproj/project.pbxproj
index 5425054ec..2c8edf54e 100644
--- a/apps/mobile/ios/Spacedrive.xcodeproj/project.pbxproj
+++ b/apps/mobile/ios/Spacedrive.xcodeproj/project.pbxproj
@@ -148,7 +148,7 @@
buildPhases = (
EE23FABC21723647AF9773BD /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */,
- 55B1130D28AB3061006C377F /* Build Spacedrive Core */,
+ 350DC403297BF2B8009CD6A1 /* Build sd-core-ios */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
@@ -224,6 +224,25 @@
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\n`node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n";
};
+ 350DC403297BF2B8009CD6A1 /* Build sd-core-ios */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Build sd-core-ios";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/zsh;
+ shellScript = "env -i CONFIGURATION=$CONFIGURATION PLATFORM_NAME=$PLATFORM_NAME ./build-rust.sh\n";
+ };
37F7445AEFB5A9FBEDBB3916 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -244,29 +263,6 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-resources.sh\"\n";
showEnvVarsInLog = 0;
};
- 55B1130D28AB3061006C377F /* Build Spacedrive Core */ = {
- isa = PBXShellScriptBuildPhase;
- alwaysOutOfDate = 1;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- );
- inputPaths = (
- "../../../core/src/*.rs",
- "../rust/src/*.rs",
- "../../../core/src/*/*.rs",
- );
- name = "Build Spacedrive Core";
- outputFileListPaths = (
- );
- outputPaths = (
- "../../../target/sdcore-universal-ios.a",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/zsh;
- shellScript = "set -e\n\nif [[ -n \"${DEVELOPER_SDK_DIR:-}\" ]]; then\n # Assume we're in Xcode, which means we're probably cross-compiling.\n # In this case, we need to add an extra library search path for build scripts and proc-macros,\n # which run on the host instead of the target.\n # (macOS Big Sur does not have linkable libraries in /usr/lib/.)\n export LIBRARY_PATH=\"${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}\"\nfi\n\nCARGO_FLAGS=\nif [[ \"$BUILDVARIANT\" != \"debug\" ]]; then\n CARGO_FLAGS=--release\nfi\n\nTARGET_DIRECTORY=../../../target\nif [[ $PLATFORM_NAME = \"iphonesimulator\" ]]\nthen\n cargo build -p sd-core-mobile $CARGO_FLAGS --lib --target aarch64-apple-ios-sim\n lipo -create -output $TARGET_DIRECTORY/libsd_core_mobile-iossim.a $TARGET_DIRECTORY/aarch64-apple-ios-sim/release/libsd_core_mobile.a\nelse\n cargo build -p sd-core-mobile $CARGO_FLAGS --lib --target aarch64-apple-ios\n lipo -create -output $TARGET_DIRECTORY/libsd_core_mobile-ios.a $TARGET_DIRECTORY/aarch64-apple-ios/release/libsd_core_mobile.a\nfi\n";
- };
EE23FABC21723647AF9773BD /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -424,13 +420,13 @@
"$(inherited)",
"-ObjC",
"-lc++",
- "-lsd_core_mobile-ios",
+ "-lsd_core_ios-ios",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"$(inherited)",
"-ObjC",
"-lc++",
- "-lsd_core_mobile-iossim",
+ "-lsd_core_ios-iossim",
);
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = com.spacedrive.app;
@@ -519,13 +515,13 @@
"$(inherited)",
"-ObjC",
"-lc++",
- "-lsd_core_mobile-ios",
+ "-lsd_core_ios-ios",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"$(inherited)",
"-ObjC",
"-lc++",
- "-lsd_core_mobile-iossim",
+ "-lsd_core_ios-iossim",
);
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.spacedrive.app;
diff --git a/apps/mobile/ios/build-rust.sh b/apps/mobile/ios/build-rust.sh
new file mode 100755
index 000000000..d1c07c290
--- /dev/null
+++ b/apps/mobile/ios/build-rust.sh
@@ -0,0 +1,19 @@
+#! /bin/zsh
+
+set -e
+
+TARGET_DIRECTORY=../../../target
+
+CARGO_FLAGS=
+if [[ $CONFIGURATION != "Debug" ]]; then
+ CARGO_FLAGS=--release
+fi
+
+if [[ $PLATFORM_NAME = "iphonesimulator" ]]
+then
+ cargo build -p sd-core-ios --target aarch64-apple-ios-sim
+ lipo -create -output $TARGET_DIRECTORY/libsd_core_ios-iossim.a $TARGET_DIRECTORY/aarch64-apple-ios-sim/debug/libsd_core_ios.a
+else
+ cargo build -p sd-core-ios --target aarch64-apple-ios
+ lipo -create -output $TARGET_DIRECTORY/libsd_core_ios-ios.a $TARGET_DIRECTORY/aarch64-apple-ios/debug/libsd_core_ios.a
+fi
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index 56aacbf7c..424e2f782 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -10,7 +10,7 @@
"ios": "expo run:ios",
"xcode": "open ios/spacedrive.xcworkspace",
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
- "lint": "eslint src/**/*.{ts,tsx} && tsc --noEmit",
+ "lint": "eslint src",
"postinstall": "node scripts/postinstall.js",
"typecheck": "tsc -b"
},
diff --git a/apps/mobile/rust/Cargo.toml b/apps/mobile/rust/Cargo.toml
deleted file mode 100644
index c7cf918b0..000000000
--- a/apps/mobile/rust/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-[package]
-name = "sd-core-mobile"
-version = "0.1.0"
-edition = "2021"
-rust-version = "1.64.0"
-
-[lib]
-crate-type = ["staticlib", "cdylib"] # staticlib for IOS and cdylib for Android
-
-[dependencies]
-once_cell = "1.15.0"
-sd-core = { path = "../../../core", features = [
- "mobile",
- "p2p",
-], default-features = false }
-rspc = { workspace = true }
-serde_json = "1.0.85"
-tokio = "1.21.2"
-openssl = { version = "0.10.42", features = [
- "vendored",
-] } # Override features of transitive dependencies
-openssl-sys = { version = "0.9.76", features = [
- "vendored",
-] } # Override features of transitive dependencies to support IOS Simulator on M1
-futures = "0.3.24"
-tracing = "0.1.37"
-
-[target.'cfg(target_os = "ios")'.dependencies]
-objc = "0.2.7"
-objc_id = "0.1.1"
-objc-foundation = "0.1.1"
-
-# This is `not(ios)` instead of `android` because of https://github.com/mozilla/rust-android-gradle/issues/93
-[target.'cfg(not(target_os = "ios"))'.dependencies]
-jni = "0.19.0"
-
-[target.'cfg(not(target_os = "ios"))'.features]
-default = ["sd-core/android"]
-
diff --git a/apps/mobile/rust/android/Cargo.toml b/apps/mobile/rust/android/Cargo.toml
new file mode 100644
index 000000000..01c488c76
--- /dev/null
+++ b/apps/mobile/rust/android/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "sd-core-android"
+version = "0.1.0"
+edition = "2021"
+rust-version = "1.64.0"
+
+[lib]
+# Android can use dynamic linking since all FFI is done via JNI
+crate-type = ["cdylib"]
+
+[dependencies]
+# FFI
+jni = "0.19.0"
+
+# Core mobile handling stuff
+sd-core-mobile = { path = "../mobile", features = ["android"] }
+
+# Other
+tracing = "0.1.37"
diff --git a/apps/mobile/rust/android/src/lib.rs b/apps/mobile/rust/android/src/lib.rs
new file mode 100644
index 000000000..b92d6b80a
--- /dev/null
+++ b/apps/mobile/rust/android/src/lib.rs
@@ -0,0 +1,105 @@
+use std::panic;
+
+use jni::{
+ objects::{JClass, JObject, JString},
+ JNIEnv,
+};
+
+use sd_core_mobile::*;
+
+use tracing::error;
+
+#[no_mangle]
+pub extern "system" fn Java_com_spacedrive_app_SDCore_registerCoreEventListener(
+ env: JNIEnv,
+ class: JClass,
+) {
+ let result = panic::catch_unwind(|| {
+ let jvm = env.get_java_vm().unwrap();
+ let class = env.new_global_ref(class).unwrap();
+
+ spawn_core_event_listener(move |data| {
+ let env = jvm.attach_current_thread().unwrap();
+ env.call_method(
+ &class,
+ "sendCoreEvent",
+ "(Ljava/lang/String;)V",
+ &[env
+ .new_string(data)
+ .expect("Couldn't create java string!")
+ .into()],
+ )
+ .unwrap();
+ })
+ });
+
+ if let Err(err) = result {
+ // TODO: Send rspc error or something here so we can show this in the UI.
+ // TODO: Maybe reinitialise the core cause it could be in an invalid state?
+ println!(
+ "Error in Java_com_spacedrive_app_SDCore_registerCoreEventListener: {:?}",
+ err
+ );
+ }
+}
+
+#[no_mangle]
+pub extern "system" fn Java_com_spacedrive_app_SDCore_handleCoreMsg(
+ env: JNIEnv,
+ class: JClass,
+ query: JString,
+ callback: JObject,
+) {
+ let result = panic::catch_unwind(|| {
+ let jvm = env.get_java_vm().unwrap();
+
+ let query: String = env
+ .get_string(query)
+ .expect("Couldn't get java string!")
+ .into();
+
+ let class = env.new_global_ref(class).unwrap();
+ let callback = env.new_global_ref(callback).unwrap();
+
+ let data_directory = {
+ let env = jvm.attach_current_thread().unwrap();
+ let data_dir = env
+ .call_method(&class, "getDataDirectory", "()Ljava/lang/String;", &[])
+ .unwrap()
+ .l()
+ .unwrap();
+
+ env.get_string(data_dir.into()).unwrap().into()
+ };
+
+ handle_core_msg(query, data_directory, move |result| match result {
+ Ok(data) => {
+ let env = jvm.attach_current_thread().unwrap();
+ env.call_method(
+ &callback,
+ "resolve",
+ "(Ljava/lang/Object;)V",
+ &[env
+ .new_string(data)
+ .expect("Couldn't create java string!")
+ .into()],
+ )
+ .unwrap();
+ }
+ Err(_) => {
+ // TODO: handle error
+ }
+ });
+ });
+
+ if let Err(err) = result {
+ // TODO: Send rspc error or something here so we can show this in the UI.
+ // TODO: Maybe reinitialise the core cause it could be in an invalid state?
+
+ // TODO: This log statement doesn't work. I recon the JNI env is being dropped before it's called.
+ error!(
+ "Error in Java_com_spacedrive_app_SDCore_registerCoreEventListener: {:?}",
+ err
+ );
+ }
+}
diff --git a/apps/mobile/rust/ios/Cargo.toml b/apps/mobile/rust/ios/Cargo.toml
new file mode 100644
index 000000000..26b034bad
--- /dev/null
+++ b/apps/mobile/rust/ios/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "sd-core-ios"
+version = "0.1.0"
+edition = "2021"
+
+rust-version = "1.64.0"
+
+[lib]
+# iOS requires static linking
+# Makes sense considering this lib needs to link against call_resolve and get_data_directory,
+# which are only available when linking against the app's ObjC
+crate-type = ["staticlib"]
+
+
+[target.'cfg(target_os = "ios")'.dependencies]
+# FFI
+objc = "0.2.7"
+objc_id = "0.1.1"
+objc-foundation = "0.1.1"
+
+[dependencies]
+# Core mobile handling stuff
+sd-core-mobile = { path = "../mobile" }
diff --git a/apps/mobile/rust/ios/src/lib.rs b/apps/mobile/rust/ios/src/lib.rs
new file mode 100644
index 000000000..5fe98fb80
--- /dev/null
+++ b/apps/mobile/rust/ios/src/lib.rs
@@ -0,0 +1,81 @@
+#![cfg(target_os = "ios")]
+
+use std::{
+ ffi::{CStr, CString},
+ os::raw::{c_char, c_void},
+ panic,
+};
+
+use objc::{msg_send, runtime::Object, sel, sel_impl};
+use objc_foundation::{INSString, NSString};
+use objc_id::Id;
+
+use sd_core_mobile::*;
+
+extern "C" {
+ fn get_data_directory() -> *const c_char;
+ fn call_resolve(resolve: *const c_void, result: *const c_char);
+}
+
+// This struct wraps the function pointer which represent a Javascript Promise. We wrap the
+// function pointers in a struct so we can unsafely assert to Rust that they are `Send`.
+// We know they are send as we have ensured Objective-C won't deallocate the function pointer
+// until `call_resolve` is called.
+struct RNPromise(*const c_void);
+
+unsafe impl Send for RNPromise {}
+
+impl RNPromise {
+ // resolve the promise
+ unsafe fn resolve(self, result: CString) {
+ call_resolve(self.0, result.as_ptr());
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn register_core_event_listener(id: *mut Object) {
+ let result = panic::catch_unwind(|| {
+ let id = Id::